]> git.sur5r.net Git - openocd/commitdiff
flash Kinetis: add KL28 device
authorTomas Vanek <vanekt@fbl.cz>
Fri, 10 Mar 2017 20:43:46 +0000 (21:43 +0100)
committerFreddie Chopin <freddie.chopin@gmail.com>
Sat, 17 Jun 2017 11:02:07 +0000 (12:02 +0100)
This device differs a lot from others in KL series.

Unfortunately the System Integration Module, where device
identification resides, moved to a new address so probe now have
to try both addresses of SIM_SDID.

Introduce a new bank creation option: -sim-base to ensure error free probe.

WDOG32 is slightly different from KE1x and on different address.
System Mode Controler changed layout to word aligned.

Change-Id: I2c9dca0c4ad4228fcc941d6078d15f5e394833ff
Signed-off-by: Tomas Vanek <vanekt@fbl.cz>
Reviewed-on: http://openocd.zylin.com/4059
Tested-by: jenkins
Reviewed-by: Joakim NohlgÄrd <joakim.nohlgard@eistec.se>
Reviewed-by: Freddie Chopin <freddie.chopin@gmail.com>
doc/openocd.texi
src/flash/nor/kinetis.c

index 5fd43009d8681c942ecb7f27f45e8bb2195deded..d26c55a68366e15377a7f4a3d213313debc5c724 100644 (file)
@@ -5368,6 +5368,11 @@ recognizes flash size and a number of flash banks (1-4) using the chip
 identification register, and autoconfigures itself.
 Use kinetis_ke driver for KE0x devices.
 
+The @var{kinetis} driver defines option:
+@itemize
+@item -sim-base @var{addr} ... base of System Integration Module where chip identification resides. Driver tries two known locations if option is omitted.
+@end itemize
+
 @example
 flash bank $_FLASHNAME kinetis 0 0 0 0 $_TARGETNAME
 @end example
index 1f2383d00d4bce963ea3fd57a134e5704de35922..cc86f971a4ee4c36a70b4bb1c8a9724685fb3cf5 100644 (file)
 #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
 
@@ -272,6 +278,7 @@ struct kinetis_chip {
        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,
@@ -297,6 +304,11 @@ struct kinetis_chip {
                KINETIS_WDOG32_KL28,
        } watchdog_type;
 
+       enum {
+               KINETIS_SMC,
+               KINETIS_SMC32,
+       } sysmodectrlr_type;
+
        char name[40];
 
        unsigned num_banks;
@@ -844,11 +856,25 @@ static struct kinetis_chip *kinetis_get_chip(struct target *target)
        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;
@@ -865,6 +891,11 @@ FLASH_BANK_COMMAND_HANDLER(kinetis_flash_bank_command)
                }
 
                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) {
@@ -1467,17 +1498,44 @@ static int kinetis_ftfx_command(struct target *target, uint8_t fcmd, uint32_t fa
 }
 
 
-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;
 
@@ -1487,13 +1545,21 @@ static int kinetis_check_run_mode(struct target *target)
        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;
 
@@ -1539,8 +1605,9 @@ static int kinetis_erase(struct flash_bank *bank, int first, int last)
 {
        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;
 
@@ -1816,8 +1883,9 @@ static int kinetis_write(struct flash_bank *bank, const uint8_t *buffer,
        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;
 
@@ -1902,7 +1970,18 @@ static int kinetis_probe_chip(struct kinetis_chip *k_chip)
 
        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;
 
@@ -2004,7 +2083,7 @@ static int kinetis_probe_chip(struct kinetis_chip *k_chip)
                        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;
 
@@ -2112,8 +2191,21 @@ static int kinetis_probe_chip(struct kinetis_chip *k_chip)
                        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;
@@ -2234,11 +2326,11 @@ static int kinetis_probe_chip(struct kinetis_chip *k_chip)
                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;
 
@@ -2573,7 +2665,7 @@ static int kinetis_blank_check(struct flash_bank *bank)
        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;
 
@@ -2653,6 +2745,8 @@ COMMAND_HANDLER(kinetis_nvm_partition)
        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;
@@ -2665,7 +2759,11 @@ COMMAND_HANDLER(kinetis_nvm_partition)
        }
        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;
 
@@ -2748,7 +2846,7 @@ COMMAND_HANDLER(kinetis_nvm_partition)
        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;
 
@@ -2765,7 +2863,6 @@ COMMAND_HANDLER(kinetis_nvm_partition)
 
        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;