jtag: linuxgpiod: drop extra parenthesis
[openocd.git] / src / flash / nor / kinetis_ke.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2
3 /***************************************************************************
4 * Copyright (C) 2015 by Ivan Meleca *
5 * ivan@artekit.eu *
6 * *
7 * Modified from kinetis.c *
8 * *
9 * Copyright (C) 2011 by Mathias Kuester *
10 * kesmtp@freenet.de *
11 * *
12 * Copyright (C) 2011 sleep(5) ltd *
13 * tomas@sleepfive.com *
14 * *
15 * Copyright (C) 2012 by Christopher D. Kilgour *
16 * techie at whiterocker.com *
17 * *
18 * Copyright (C) 2013 Nemui Trinomius *
19 * nemuisan_kawausogasuki@live.jp *
20 * *
21 * Copyright (C) 2015 Tomas Vanek *
22 * vanekt@fbl.cz *
23 ***************************************************************************/
24
25 #ifdef HAVE_CONFIG_H
26 #include "config.h"
27 #endif
28
29 #include "jtag/interface.h"
30 #include "imp.h"
31 #include <helper/binarybuffer.h>
32 #include <target/algorithm.h>
33 #include <target/arm_adi_v5.h>
34 #include <target/armv7m.h>
35 #include <target/cortex_m.h>
36
37 /* Addresses */
38 #define SIM_SRSID 0x40048000
39 #define ICS_C1 0x40064000
40 #define ICS_C2 0x40064001
41 #define ICS_C3 0x40064002
42 #define ICS_C4 0x40064003
43 #define ICS_S 0x40064004
44 #define SIM_BUSDIV 0x40048018
45 #define SIM_CLKDIV_KE06 0x40048024
46 #define SIM_CLKDIV_KE04_44_64_80 0x40048024
47 #define SIM_CLKDIV_KE04_16_20_24 0x4004801C
48 #define WDOG_CS1 0x40052000
49
50 #define ICS_C2_BDIV_MASK 0xE0
51 #define ICS_C2_BDIV_SHIFT 5
52 #define ICS_C2_BDIV(x) (((uint8_t)(((uint8_t)(x))<<ICS_C2_BDIV_SHIFT))&ICS_C2_BDIV_MASK)
53 #define ICS_S_LOCK_MASK 0x40
54 #define ICS_C4_SCFTRIM_MASK 0x1
55 #define SIM_CLKDIV_OUTDIV2_MASK 0x1000000
56 #define FTMRX_FCLKDIV_FDIV_MASK 0x3F
57 #define FTMRX_FCLKDIV_FDIV_SHIFT 0
58 #define FTMRX_FCLKDIV_FDIV(x) (((uint8_t)(((uint8_t)(x))<<FTMRX_FCLKDIV_FDIV_SHIFT))&FTMRX_FCLKDIV_FDIV_MASK)
59 #define FTMRX_FCLKDIV_FDIVLCK_MASK 0x40
60 #define FTMRX_FCLKDIV_FDIVLCK_SHIFT 6
61 #define FTMRX_FCLKDIV_FDIVLD_MASK 0x80
62 #define FTMRX_FCLKDIV_FDIVLD_SHIFT 7
63 #define FTMRX_FSTAT_CCIF_MASK 0x80
64 #define FTMRX_FSTAT_MGSTAT0_MASK 0x01
65 #define FTMRX_FSTAT_MGSTAT1_MASK 0x02
66
67 /* Commands */
68 #define FTMRX_CMD_ALLERASED 0x01
69 #define FTMRX_CMD_BLOCKERASED 0x02
70 #define FTMRX_CMD_SECTIONERASED 0x03
71 #define FTMRX_CMD_READONCE 0x04
72 #define FTMRX_CMD_PROGFLASH 0x06
73 #define FTMRX_CMD_PROGONCE 0x07
74 #define FTMRX_CMD_ERASEALL 0x08
75 #define FTMRX_CMD_ERASEBLOCK 0x09
76 #define FTMRX_CMD_ERASESECTOR 0x0A
77 #define FTMRX_CMD_UNSECURE 0x0B
78 #define FTMRX_CMD_VERIFYACCESS 0x0C
79 #define FTMRX_CMD_SETMARGINLVL 0x0D
80 #define FTMRX_CMD_SETFACTORYLVL 0x0E
81 #define FTMRX_CMD_CONFIGNVM 0x0F
82
83 /* Error codes */
84 #define FTMRX_ERROR_ACCERR 0x20
85 #define FTMRX_ERROR_FPVIOL 0x10
86
87 #define KINETIS_KE_SRSID_FAMID(x) ((x >> 28) & 0x0F)
88 #define KINETIS_KE_SRSID_SUBFAMID(x) ((x >> 24) & 0x0F)
89 #define KINETIS_KE_SRSID_PINCOUNT(x) ((x >> 16) & 0x0F)
90
91 #define KINETIS_KE_SRSID_KEX2 0x02
92 #define KINETIS_KE_SRSID_KEX4 0x04
93 #define KINETIS_KE_SRSID_KEX6 0x06
94
95 struct kinetis_ke_flash_bank {
96 uint32_t sector_size;
97 uint32_t protection_size;
98
99 uint32_t sim_srsid;
100 uint32_t ftmrx_fclkdiv_addr;
101 uint32_t ftmrx_fccobix_addr;
102 uint32_t ftmrx_fstat_addr;
103 uint32_t ftmrx_fprot_addr;
104 uint32_t ftmrx_fccobhi_addr;
105 uint32_t ftmrx_fccoblo_addr;
106 };
107
108 #define MDM_REG_STAT 0x00
109 #define MDM_REG_CTRL 0x04
110 #define MDM_REG_ID 0xfc
111
112 #define MDM_STAT_FMEACK (1<<0)
113 #define MDM_STAT_FREADY (1<<1)
114 #define MDM_STAT_SYSSEC (1<<2)
115 #define MDM_STAT_SYSRES (1<<3)
116 #define MDM_STAT_FMEEN (1<<5)
117 #define MDM_STAT_BACKDOOREN (1<<6)
118 #define MDM_STAT_LPEN (1<<7)
119 #define MDM_STAT_VLPEN (1<<8)
120 #define MDM_STAT_LLSMODEXIT (1<<9)
121 #define MDM_STAT_VLLSXMODEXIT (1<<10)
122 #define MDM_STAT_CORE_HALTED (1<<16)
123 #define MDM_STAT_CORE_SLEEPDEEP (1<<17)
124 #define MDM_STAT_CORESLEEPING (1<<18)
125
126 #define MEM_CTRL_FMEIP (1<<0)
127 #define MEM_CTRL_DBG_DIS (1<<1)
128 #define MEM_CTRL_DBG_REQ (1<<2)
129 #define MEM_CTRL_SYS_RES_REQ (1<<3)
130 #define MEM_CTRL_CORE_HOLD_RES (1<<4)
131 #define MEM_CTRL_VLLSX_DBG_REQ (1<<5)
132 #define MEM_CTRL_VLLSX_DBG_ACK (1<<6)
133 #define MEM_CTRL_VLLSX_STAT_ACK (1<<7)
134
135 #define MDM_ACCESS_TIMEOUT 3000 /* iterations */
136
137 static int kinetis_ke_mdm_write_register(struct adiv5_dap *dap, unsigned reg, uint32_t value)
138 {
139 LOG_DEBUG("MDM_REG[0x%02x] <- %08" PRIX32, reg, value);
140
141 struct adiv5_ap *ap = dap_get_ap(dap, 1);
142 if (!ap) {
143 LOG_DEBUG("MDM: failed to get AP");
144 return ERROR_FAIL;
145 }
146
147 int retval = dap_queue_ap_write(ap, reg, value);
148 if (retval != ERROR_OK) {
149 LOG_DEBUG("MDM: failed to queue a write request");
150 dap_put_ap(ap);
151 return retval;
152 }
153
154 retval = dap_run(dap);
155 dap_put_ap(ap);
156 if (retval != ERROR_OK) {
157 LOG_DEBUG("MDM: dap_run failed");
158 return retval;
159 }
160
161 return ERROR_OK;
162 }
163
164 static int kinetis_ke_mdm_read_register(struct adiv5_dap *dap, unsigned reg, uint32_t *result)
165 {
166 struct adiv5_ap *ap = dap_get_ap(dap, 1);
167 if (!ap) {
168 LOG_DEBUG("MDM: failed to get AP");
169 return ERROR_FAIL;
170 }
171
172 int retval = dap_queue_ap_read(ap, reg, result);
173 if (retval != ERROR_OK) {
174 LOG_DEBUG("MDM: failed to queue a read request");
175 dap_put_ap(ap);
176 return retval;
177 }
178
179 retval = dap_run(dap);
180 dap_put_ap(ap);
181 if (retval != ERROR_OK) {
182 LOG_DEBUG("MDM: dap_run failed");
183 return retval;
184 }
185
186 LOG_DEBUG("MDM_REG[0x%02x]: %08" PRIX32, reg, *result);
187 return ERROR_OK;
188 }
189
190 static int kinetis_ke_mdm_poll_register(struct adiv5_dap *dap, unsigned reg, uint32_t mask, uint32_t value)
191 {
192 uint32_t val;
193 int retval;
194 int timeout = MDM_ACCESS_TIMEOUT;
195
196 do {
197 retval = kinetis_ke_mdm_read_register(dap, reg, &val);
198 if (retval != ERROR_OK || (val & mask) == value)
199 return retval;
200
201 alive_sleep(1);
202 } while (timeout--);
203
204 LOG_DEBUG("MDM: polling timed out");
205 return ERROR_FAIL;
206 }
207
208 static int kinetis_ke_prepare_flash(struct flash_bank *bank)
209 {
210 struct target *target = bank->target;
211 struct kinetis_ke_flash_bank *kinfo = bank->driver_priv;
212 uint8_t c2, c3, c4, s = 0;
213 uint16_t trim_value = 0;
214 uint16_t timeout = 0;
215 uint32_t bus_clock = 0;
216 uint32_t bus_reg_val = 0;
217 uint32_t bus_reg_addr = 0;
218 uint32_t flash_clk_div;
219 uint8_t fclkdiv;
220 int result;
221
222 /*
223 * The RM states that the flash clock has to be set to 1MHz for writing and
224 * erasing operations (otherwise it can damage the flash).
225 * This function configures the entire clock tree to make sure we
226 * run at the specified clock. We'll set FEI mode running from the ~32KHz
227 * internal clock. So we need to:
228 * - Trim internal clock.
229 * - Configure the divider for ICSOUTCLK (ICS module).
230 * - Configure the divider to get a bus clock (SIM module).
231 * - Configure the flash clock that depends on the bus clock.
232 *
233 * For MKE02_40 and MKE02_20 we set ICSOUTCLK = 20MHz and bus clock = 20MHz.
234 * For MKE04 and MKE06 we run at ICSOUTCLK = 48MHz and bus clock = 24MHz.
235 */
236
237 /*
238 * Trim internal clock
239 */
240 switch (KINETIS_KE_SRSID_SUBFAMID(kinfo->sim_srsid)) {
241
242 case KINETIS_KE_SRSID_KEX2:
243 /* Both KE02_20 and KE02_40 should get the same trim value */
244 trim_value = 0x4C;
245 break;
246
247 case KINETIS_KE_SRSID_KEX4:
248 trim_value = 0x54;
249 break;
250
251 case KINETIS_KE_SRSID_KEX6:
252 trim_value = 0x58;
253 break;
254 }
255
256 result = target_read_u8(target, ICS_C4, &c4);
257 if (result != ERROR_OK)
258 return result;
259
260 c3 = trim_value;
261 c4 = (c4 & ~(ICS_C4_SCFTRIM_MASK)) | ((trim_value >> 8) & 0x01);
262
263 result = target_write_u8(target, ICS_C3, c3);
264 if (result != ERROR_OK)
265 return result;
266
267 result = target_write_u8(target, ICS_C4, c4);
268 if (result != ERROR_OK)
269 return result;
270
271 result = target_read_u8(target, ICS_S, &s);
272 if (result != ERROR_OK)
273 return result;
274
275 /* Wait */
276 while (!(s & ICS_S_LOCK_MASK)) {
277
278 if (timeout <= 1000) {
279 timeout++;
280 alive_sleep(1);
281 } else {
282 return ERROR_FAIL;
283 }
284
285 result = target_read_u8(target, ICS_S, &s);
286 if (result != ERROR_OK)
287 return result;
288 }
289
290 /* ... trim done ... */
291
292 /*
293 * Configure SIM (bus clock)
294 */
295 switch (KINETIS_KE_SRSID_SUBFAMID(kinfo->sim_srsid)) {
296
297 /* KE02 sub-family operates on SIM_BUSDIV */
298 case KINETIS_KE_SRSID_KEX2:
299 bus_reg_val = 0;
300 bus_reg_addr = SIM_BUSDIV;
301 bus_clock = 20000000;
302 break;
303
304 /* KE04 and KE06 sub-family operates on SIM_CLKDIV
305 * Clocks are divided by:
306 * DIV1 = core clock = 48MHz
307 * DIV2 = bus clock = 24Mhz
308 * DIV3 = timer clocks
309 * So we need to configure SIM_CLKDIV, DIV1 and DIV2 value
310 */
311 case KINETIS_KE_SRSID_KEX4:
312 /* KE04 devices have the SIM_CLKDIV register at a different offset
313 * depending on the pin count. */
314 switch (KINETIS_KE_SRSID_PINCOUNT(kinfo->sim_srsid)) {
315
316 /* 16, 20 and 24 pins */
317 case 1:
318 case 2:
319 case 3:
320 bus_reg_addr = SIM_CLKDIV_KE04_16_20_24;
321 break;
322
323 /* 44, 64 and 80 pins */
324 case 5:
325 case 7:
326 case 8:
327 bus_reg_addr = SIM_CLKDIV_KE04_44_64_80;
328 break;
329
330 default:
331 LOG_ERROR("KE04 - Unknown pin count");
332 return ERROR_FAIL;
333 }
334
335 bus_reg_val = SIM_CLKDIV_OUTDIV2_MASK;
336 bus_clock = 24000000;
337 break;
338
339 case KINETIS_KE_SRSID_KEX6:
340 bus_reg_val = SIM_CLKDIV_OUTDIV2_MASK;
341 bus_reg_addr = SIM_CLKDIV_KE06;
342 bus_clock = 24000000;
343 break;
344 }
345
346 result = target_write_u32(target, bus_reg_addr, bus_reg_val);
347 if (result != ERROR_OK)
348 return result;
349
350 /*
351 * Configure ICS to FEI (internal source)
352 */
353 result = target_read_u8(target, ICS_C2, &c2);
354 if (result != ERROR_OK)
355 return result;
356
357 c2 &= ~ICS_C2_BDIV_MASK;
358
359 switch (KINETIS_KE_SRSID_SUBFAMID(kinfo->sim_srsid)) {
360
361 case KINETIS_KE_SRSID_KEX2:
362 /* Note: since there are two KE02 types, the KE02_40 @ 40MHz and the
363 * KE02_20 @ 20MHz, we divide here the ~40MHz ICSFLLCLK down to 20MHz,
364 * for compatibility.
365 */
366 c2 |= ICS_C2_BDIV(1);
367 break;
368
369 case KINETIS_KE_SRSID_KEX4:
370 case KINETIS_KE_SRSID_KEX6:
371 /* For KE04 and KE06, the ICSFLLCLK can be 48MHz. */
372 c2 |= ICS_C2_BDIV(0);
373 break;
374 }
375
376 result = target_write_u8(target, ICS_C2, c2);
377 if (result != ERROR_OK)
378 return result;
379
380 /* Internal clock as reference (IREFS = 1) */
381 result = target_write_u8(target, ICS_C1, 4);
382 if (result != ERROR_OK)
383 return result;
384
385 /* Wait for FLL to lock */
386 result = target_read_u8(target, ICS_S, &s);
387 if (result != ERROR_OK)
388 return result;
389
390 while (!(s & ICS_S_LOCK_MASK)) {
391
392 if (timeout <= 1000) {
393 timeout++;
394 alive_sleep(1);
395 } else {
396 return ERROR_FLASH_OPERATION_FAILED;
397 }
398
399 result = target_read_u8(target, ICS_S, &s);
400 if (result != ERROR_OK)
401 return result;
402 }
403
404 /*
405 * Configure flash clock to 1MHz.
406 */
407 flash_clk_div = bus_clock / 1000000L - 1;
408
409 /* Check if the FCLKDIV register is locked */
410 result = target_read_u8(target, kinfo->ftmrx_fclkdiv_addr, &fclkdiv);
411 if (result != ERROR_OK)
412 return result;
413
414 if (!(fclkdiv & FTMRX_FCLKDIV_FDIVLCK_MASK)) {
415 /* Unlocked. Check if the register was configured, and if so, if it has the right value */
416 if ((fclkdiv & FTMRX_FCLKDIV_FDIVLD_MASK) &&
417 ((fclkdiv & FTMRX_FCLKDIV_FDIV_MASK) != FTMRX_FCLKDIV_FDIV(flash_clk_div))) {
418 LOG_WARNING("Flash clock was already set and contains an invalid value.");
419 LOG_WARNING("Please reset the target.");
420 return ERROR_FAIL;
421 }
422
423 /* Finally, configure the flash clock */
424 fclkdiv = (fclkdiv & ~(FTMRX_FCLKDIV_FDIV_MASK)) | FTMRX_FCLKDIV_FDIV(flash_clk_div);
425 result = target_write_u8(target, kinfo->ftmrx_fclkdiv_addr, fclkdiv);
426 if (result != ERROR_OK)
427 return result;
428 } else {
429 /* Locked. Check if the current value is correct. */
430 if ((fclkdiv & FTMRX_FCLKDIV_FDIV_MASK) != FTMRX_FCLKDIV_FDIV(flash_clk_div)) {
431 LOG_WARNING("Flash clock register is locked and contains an invalid value.");
432 LOG_WARNING("Please reset the target.");
433 return ERROR_FAIL;
434 }
435 }
436
437 LOG_INFO("Flash clock ready");
438 return ERROR_OK;
439 }
440
441 static int kinetis_ke_stop_watchdog(struct target *target)
442 {
443 struct working_area *watchdog_algorithm;
444 struct armv7m_algorithm armv7m_info;
445 int retval;
446 uint8_t cs1;
447
448 static const uint8_t watchdog_code[] = {
449 #include "../../../contrib/loaders/flash/kinetis_ke/kinetis_ke_watchdog.inc"
450 };
451
452 if (target->state != TARGET_HALTED) {
453 LOG_ERROR("Target not halted");
454 return ERROR_TARGET_NOT_HALTED;
455 }
456
457 /* Check if the watchdog is enabled */
458 retval = target_read_u8(target, WDOG_CS1, &cs1);
459 if (retval != ERROR_OK)
460 return retval;
461
462 if (!(cs1 & 0x80)) {
463 /* Already stopped */
464 return ERROR_OK;
465 }
466
467 /* allocate working area with watchdog code */
468 if (target_alloc_working_area(target, sizeof(watchdog_code), &watchdog_algorithm) != ERROR_OK) {
469 LOG_WARNING("No working area available for watchdog algorithm");
470 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
471 }
472
473 retval = target_write_buffer(target, watchdog_algorithm->address,
474 sizeof(watchdog_code), watchdog_code);
475 if (retval != ERROR_OK)
476 return retval;
477
478 armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
479 armv7m_info.core_mode = ARM_MODE_THREAD;
480
481 retval = target_run_algorithm(target, 0, NULL, 0, NULL,
482 watchdog_algorithm->address, 0, 100000, &armv7m_info);
483 if (retval != ERROR_OK) {
484 LOG_ERROR("Error executing Kinetis KE watchdog algorithm");
485 } else {
486 LOG_INFO("Watchdog stopped");
487 }
488
489 target_free_working_area(target, watchdog_algorithm);
490
491 return retval;
492 }
493
494 COMMAND_HANDLER(kinetis_ke_disable_wdog_handler)
495 {
496 struct target *target = get_current_target(CMD_CTX);
497
498 if (CMD_ARGC > 0)
499 return ERROR_COMMAND_SYNTAX_ERROR;
500
501 return kinetis_ke_stop_watchdog(target);
502 }
503
504 COMMAND_HANDLER(kinetis_ke_mdm_mass_erase)
505 {
506 struct target *target = get_current_target(CMD_CTX);
507 struct cortex_m_common *cortex_m = target_to_cm(target);
508 struct adiv5_dap *dap = cortex_m->armv7m.arm.dap;
509
510 if (!dap) {
511 LOG_ERROR("Cannot perform mass erase with a high-level adapter");
512 return ERROR_FAIL;
513 }
514
515 int retval;
516
517 /* According to chapter 18.3.7.2 of the KE02 reference manual */
518
519 /* assert SRST */
520 if (jtag_get_reset_config() & RESET_HAS_SRST)
521 adapter_assert_reset();
522
523 /*
524 * 1. Reset the device by asserting RESET pin or DAP_CTRL[3]
525 */
526 retval = kinetis_ke_mdm_write_register(dap, MDM_REG_CTRL, MEM_CTRL_SYS_RES_REQ);
527 if (retval != ERROR_OK)
528 return retval;
529
530 /*
531 * ... Read the MDM-AP status register until the Flash Ready bit sets...
532 */
533 retval = kinetis_ke_mdm_poll_register(dap, MDM_REG_STAT,
534 MDM_STAT_FREADY | MDM_STAT_SYSRES,
535 MDM_STAT_FREADY);
536 if (retval != ERROR_OK) {
537 LOG_ERROR("MDM : flash ready timeout");
538 return retval;
539 }
540
541 /*
542 * 2. Set DAP_CTRL[0] bit to invoke debug mass erase via SWD
543 * 3. Release reset by deasserting RESET pin or DAP_CTRL[3] bit via SWD.
544 */
545 retval = kinetis_ke_mdm_write_register(dap, MDM_REG_CTRL, MEM_CTRL_FMEIP);
546 if (retval != ERROR_OK)
547 return retval;
548
549 /* As a sanity check make sure that device started mass erase procedure */
550 retval = kinetis_ke_mdm_poll_register(dap, MDM_REG_STAT,
551 MDM_STAT_FMEACK, MDM_STAT_FMEACK);
552 if (retval != ERROR_OK)
553 return retval;
554
555 /*
556 * 4. Wait till DAP_CTRL[0] bit is cleared (after mass erase completes,
557 * DAP_CTRL[0] bit is cleared automatically).
558 */
559 retval = kinetis_ke_mdm_poll_register(dap, MDM_REG_CTRL,
560 MEM_CTRL_FMEIP,
561 0);
562 if (retval != ERROR_OK)
563 return retval;
564
565 if (jtag_get_reset_config() & RESET_HAS_SRST)
566 adapter_deassert_reset();
567
568 return ERROR_OK;
569 }
570
571 static const uint32_t kinetis_ke_known_mdm_ids[] = {
572 0x001C0020, /* Kinetis-L/M/V/E/KE Series */
573 };
574
575 /*
576 * This function implements the procedure to connect to
577 * SWD/JTAG on Kinetis K and L series of devices as it is described in
578 * AN4835 "Production Flash Programming Best Practices for Kinetis K-
579 * and L-series MCUs" Section 4.1.1
580 */
581 COMMAND_HANDLER(kinetis_ke_check_flash_security_status)
582 {
583 struct target *target = get_current_target(CMD_CTX);
584 struct cortex_m_common *cortex_m = target_to_cm(target);
585 struct adiv5_dap *dap = cortex_m->armv7m.arm.dap;
586
587 if (!dap) {
588 LOG_WARNING("Cannot check flash security status with a high-level adapter");
589 return ERROR_OK;
590 }
591
592 uint32_t val;
593 int retval;
594
595 /*
596 * ... The MDM-AP ID register can be read to verify that the
597 * connection is working correctly...
598 */
599 retval = kinetis_ke_mdm_read_register(dap, MDM_REG_ID, &val);
600 if (retval != ERROR_OK) {
601 LOG_ERROR("MDM: failed to read ID register");
602 goto fail;
603 }
604
605 bool found = false;
606 for (size_t i = 0; i < ARRAY_SIZE(kinetis_ke_known_mdm_ids); i++) {
607 if (val == kinetis_ke_known_mdm_ids[i]) {
608 found = true;
609 break;
610 }
611 }
612
613 if (!found)
614 LOG_WARNING("MDM: unknown ID %08" PRIX32, val);
615
616 /*
617 * ... Read the MDM-AP status register until the Flash Ready bit sets...
618 */
619 retval = kinetis_ke_mdm_poll_register(dap, MDM_REG_STAT,
620 MDM_STAT_FREADY,
621 MDM_STAT_FREADY);
622 if (retval != ERROR_OK) {
623 LOG_ERROR("MDM: flash ready timeout");
624 goto fail;
625 }
626
627 /*
628 * ... Read the System Security bit to determine if security is enabled.
629 * If System Security = 0, then proceed. If System Security = 1, then
630 * communication with the internals of the processor, including the
631 * flash, will not be possible without issuing a mass erase command or
632 * unsecuring the part through other means (backdoor key unlock)...
633 */
634 retval = kinetis_ke_mdm_read_register(dap, MDM_REG_STAT, &val);
635 if (retval != ERROR_OK) {
636 LOG_ERROR("MDM: failed to read MDM_REG_STAT");
637 goto fail;
638 }
639
640 if (val & MDM_STAT_SYSSEC) {
641 jtag_poll_set_enabled(false);
642
643 LOG_WARNING("*********** ATTENTION! ATTENTION! ATTENTION! ATTENTION! **********");
644 LOG_WARNING("**** ****");
645 LOG_WARNING("**** Your Kinetis MCU is in secured state, which means that, ****");
646 LOG_WARNING("**** with exception for very basic communication, JTAG/SWD ****");
647 LOG_WARNING("**** interface will NOT work. In order to restore its ****");
648 LOG_WARNING("**** functionality please issue 'kinetis_ke mdm mass_erase' ****");
649 LOG_WARNING("**** command, power cycle the MCU and restart OpenOCD. ****");
650 LOG_WARNING("**** ****");
651 LOG_WARNING("*********** ATTENTION! ATTENTION! ATTENTION! ATTENTION! **********");
652 } else {
653 LOG_INFO("MDM: Chip is unsecured. Continuing.");
654 jtag_poll_set_enabled(true);
655 }
656
657 return ERROR_OK;
658
659 fail:
660 LOG_ERROR("MDM: Failed to check security status of the MCU. Cannot proceed further");
661 jtag_poll_set_enabled(false);
662 return retval;
663 }
664
665 FLASH_BANK_COMMAND_HANDLER(kinetis_ke_flash_bank_command)
666 {
667 struct kinetis_ke_flash_bank *bank_info;
668
669 if (CMD_ARGC < 6)
670 return ERROR_COMMAND_SYNTAX_ERROR;
671
672 LOG_INFO("add flash_bank kinetis_ke %s", bank->name);
673
674 bank_info = malloc(sizeof(struct kinetis_ke_flash_bank));
675
676 memset(bank_info, 0, sizeof(struct kinetis_ke_flash_bank));
677
678 bank->driver_priv = bank_info;
679
680 return ERROR_OK;
681 }
682
683 /* Kinetis Program-LongWord Microcodes */
684 static uint8_t kinetis_ke_flash_write_code[] = {
685 #include "../../../contrib/loaders/flash/kinetis_ke/kinetis_ke_flash.inc"
686 };
687
688 static int kinetis_ke_write_words(struct flash_bank *bank, const uint8_t *buffer,
689 uint32_t offset, uint32_t words)
690 {
691 struct kinetis_ke_flash_bank *kinfo = bank->driver_priv;
692 struct target *target = bank->target;
693 uint32_t ram_buffer_size = 512 + 16;
694 struct working_area *write_algorithm;
695 struct working_area *source;
696 uint32_t address = bank->base + offset;
697 struct reg_param reg_params[4];
698 struct armv7m_algorithm armv7m_info;
699 int retval = ERROR_OK;
700 uint32_t flash_code_size;
701
702 LOG_INFO("Kinetis KE: FLASH Write ...");
703
704 /* allocate working area with flash programming code */
705 if (target_alloc_working_area(target, sizeof(kinetis_ke_flash_write_code),
706 &write_algorithm) != ERROR_OK) {
707 LOG_WARNING("no working area available, can't do block memory writes");
708 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
709 }
710
711 /* Patch the FTMRx registers addresses */
712 flash_code_size = sizeof(kinetis_ke_flash_write_code);
713 buf_set_u32(&kinetis_ke_flash_write_code[flash_code_size-16], 0, 32, kinfo->ftmrx_fstat_addr);
714 buf_set_u32(&kinetis_ke_flash_write_code[flash_code_size-12], 0, 32, kinfo->ftmrx_fccobix_addr);
715 buf_set_u32(&kinetis_ke_flash_write_code[flash_code_size-8], 0, 32, kinfo->ftmrx_fccobhi_addr);
716 buf_set_u32(&kinetis_ke_flash_write_code[flash_code_size-4], 0, 32, kinfo->ftmrx_fccoblo_addr);
717
718 retval = target_write_buffer(target, write_algorithm->address,
719 sizeof(kinetis_ke_flash_write_code), kinetis_ke_flash_write_code);
720 if (retval != ERROR_OK)
721 return retval;
722
723 /* memory buffer */
724 if (target_alloc_working_area(target, ram_buffer_size, &source) != ERROR_OK) {
725 /* free working area, write algorithm already allocated */
726 target_free_working_area(target, write_algorithm);
727
728 LOG_WARNING("No large enough working area available, can't do block memory writes");
729 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
730 }
731
732 armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
733 armv7m_info.core_mode = ARM_MODE_THREAD;
734
735 init_reg_param(&reg_params[0], "r0", 32, PARAM_IN_OUT);
736 init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
737 init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT);
738 init_reg_param(&reg_params[3], "r3", 32, PARAM_OUT);
739
740 buf_set_u32(reg_params[0].value, 0, 32, address);
741 buf_set_u32(reg_params[1].value, 0, 32, words);
742 buf_set_u32(reg_params[2].value, 0, 32, source->address);
743 buf_set_u32(reg_params[3].value, 0, 32, source->address + source->size);
744
745 retval = target_run_flash_async_algorithm(target, buffer, words, 4,
746 0, NULL,
747 4, reg_params,
748 source->address, source->size,
749 write_algorithm->address, 0,
750 &armv7m_info);
751
752 if (retval == ERROR_FLASH_OPERATION_FAILED) {
753 if (buf_get_u32(reg_params[0].value, 0, 32) & FTMRX_ERROR_ACCERR)
754 LOG_ERROR("flash access error");
755
756 if (buf_get_u32(reg_params[0].value, 0, 32) & FTMRX_ERROR_FPVIOL)
757 LOG_ERROR("flash protection violation");
758 }
759
760 target_free_working_area(target, source);
761 target_free_working_area(target, write_algorithm);
762
763 destroy_reg_param(&reg_params[0]);
764 destroy_reg_param(&reg_params[1]);
765 destroy_reg_param(&reg_params[2]);
766 destroy_reg_param(&reg_params[3]);
767
768 return retval;
769 }
770
771 static int kinetis_ke_protect(struct flash_bank *bank, int set,
772 unsigned int first, unsigned int last)
773 {
774 LOG_WARNING("kinetis_ke_protect not supported yet");
775 /* FIXME: TODO */
776
777 if (bank->target->state != TARGET_HALTED) {
778 LOG_ERROR("Target not halted");
779 return ERROR_TARGET_NOT_HALTED;
780 }
781
782 return ERROR_FLASH_BANK_INVALID;
783 }
784
785 static int kinetis_ke_protect_check(struct flash_bank *bank)
786 {
787 struct kinetis_ke_flash_bank *kinfo = bank->driver_priv;
788
789 if (bank->target->state != TARGET_HALTED) {
790 LOG_ERROR("Target not halted");
791 return ERROR_TARGET_NOT_HALTED;
792 }
793
794 int result;
795 uint8_t fprot;
796 uint8_t fpopen, fpldis, fphdis;
797 uint8_t fphs, fpls;
798 uint32_t lprot_size = 0, hprot_size = 0;
799 uint32_t lprot_to = 0, hprot_from = 0;
800
801 /* read protection register */
802 result = target_read_u8(bank->target, kinfo->ftmrx_fprot_addr, &fprot);
803
804 if (result != ERROR_OK)
805 return result;
806
807 fpopen = fprot & 0x80;
808 fpldis = fprot & 0x04;
809 fphdis = fprot & 0x20;
810 fphs = (fprot >> 3) & 0x03;
811 fpls = fprot & 0x03;
812
813 /* Fully unprotected? */
814 if (fpopen && fpldis && fphdis) {
815 LOG_WARNING("No flash protection found.");
816
817 for (unsigned int i = 0; i < bank->num_sectors; i++)
818 bank->sectors[i].is_protected = 0;
819
820 kinfo->protection_size = 0;
821 } else {
822 LOG_WARNING("Flash protected. FPOPEN=%i FPLDIS=%i FPHDIS=%i FPLS=%i FPHS=%i",
823 fpopen ? 1 : 0, fpldis ? 1 : 0, fphdis ? 1 : 0, fpls, fphs);
824
825 /* Retrieve which region is protected and how much */
826 if (fpopen) {
827 if (fpldis == 0)
828 lprot_size = (kinfo->sector_size * 4) << fpls;
829
830 if (fphdis == 0)
831 hprot_size = (kinfo->sector_size * 2) << fphs;
832 } else {
833 if (fpldis == 1)
834 lprot_size = (kinfo->sector_size * 4) << fpls;
835
836 if (fphdis == 1)
837 hprot_size = (kinfo->sector_size * 2) << fphs;
838 }
839
840 kinfo->protection_size = lprot_size + hprot_size;
841
842 /* lprot_to indicates up to where the lower region is protected */
843 lprot_to = lprot_size / kinfo->sector_size;
844
845 /* hprot_from indicates from where the upper region is protected */
846 hprot_from = (0x8000 - hprot_size) / kinfo->sector_size;
847
848 for (unsigned int i = 0; i < bank->num_sectors; i++) {
849
850 /* Check if the sector is in the lower region */
851 if (bank->sectors[i].offset < 0x4000) {
852 /* Compare the sector start address against lprot_to */
853 if (lprot_to && (i < lprot_to))
854 bank->sectors[i].is_protected = 1;
855 else
856 bank->sectors[i].is_protected = 0;
857
858 /* Check if the sector is between the lower and upper region
859 * OR after the upper region */
860 } else if (bank->sectors[i].offset < 0x6000 || bank->sectors[i].offset >= 0x8000) {
861 /* If fpopen is 1 then these regions are protected */
862 if (fpopen)
863 bank->sectors[i].is_protected = 0;
864 else
865 bank->sectors[i].is_protected = 1;
866
867 /* Check if the sector is in the upper region */
868 } else if (bank->sectors[i].offset < 0x8000) {
869 if (hprot_from && (i > hprot_from))
870 bank->sectors[i].is_protected = 1;
871 else
872 bank->sectors[i].is_protected = 0;
873 }
874 }
875 }
876
877 return ERROR_OK;
878 }
879
880 static int kinetis_ke_ftmrx_command(struct flash_bank *bank, uint8_t count,
881 uint8_t *FCCOBIX, uint8_t *FCCOBHI, uint8_t *FCCOBLO, uint8_t *fstat)
882 {
883 uint8_t i;
884 int result;
885 struct target *target = bank->target;
886 struct kinetis_ke_flash_bank *kinfo = bank->driver_priv;
887 uint32_t timeout = 0;
888
889 /* Clear error flags */
890 result = target_write_u8(target, kinfo->ftmrx_fstat_addr, 0x30);
891 if (result != ERROR_OK)
892 return result;
893
894 for (i = 0; i < count; i++) {
895 /* Write index */
896 result = target_write_u8(target, kinfo->ftmrx_fccobix_addr, FCCOBIX[i]);
897 if (result != ERROR_OK)
898 return result;
899
900 /* Write high part */
901 result = target_write_u8(target, kinfo->ftmrx_fccobhi_addr, FCCOBHI[i]);
902 if (result != ERROR_OK)
903 return result;
904
905 /* Write low part (that is not always required) */
906 if (FCCOBLO) {
907 result = target_write_u8(target, kinfo->ftmrx_fccoblo_addr, FCCOBLO[i]);
908 if (result != ERROR_OK)
909 return result;
910 }
911 }
912
913 /* Launch the command */
914 result = target_write_u8(target, kinfo->ftmrx_fstat_addr, 0x80);
915 if (result != ERROR_OK)
916 return result;
917
918 /* Wait for it to finish */
919 result = target_read_u8(target, kinfo->ftmrx_fstat_addr, fstat);
920 if (result != ERROR_OK)
921 return result;
922
923 while (!(*fstat & FTMRX_FSTAT_CCIF_MASK)) {
924 if (timeout <= 1000) {
925 timeout++;
926 alive_sleep(1);
927 } else {
928 return ERROR_FLASH_OPERATION_FAILED;
929 }
930
931 result = target_read_u8(target, kinfo->ftmrx_fstat_addr, fstat);
932 if (result != ERROR_OK)
933 return result;
934 }
935
936 return ERROR_OK;
937 }
938
939 static int kinetis_ke_erase(struct flash_bank *bank, unsigned int first,
940 unsigned int last)
941 {
942 int result;
943 uint8_t FCCOBIX[2], FCCOBHI[2], FCCOBLO[2], fstat;
944 bool fcf_erased = false;
945
946 if (bank->target->state != TARGET_HALTED) {
947 LOG_ERROR("Target not halted");
948 return ERROR_TARGET_NOT_HALTED;
949 }
950
951 if ((first > bank->num_sectors) || (last > bank->num_sectors))
952 return ERROR_FLASH_OPERATION_FAILED;
953
954 result = kinetis_ke_prepare_flash(bank);
955 if (result != ERROR_OK)
956 return result;
957
958 for (unsigned int i = first; i <= last; i++) {
959 FCCOBIX[0] = 0;
960 FCCOBHI[0] = FTMRX_CMD_ERASESECTOR;
961 FCCOBLO[0] = (bank->base + bank->sectors[i].offset) >> 16;
962
963 FCCOBIX[1] = 1;
964 FCCOBHI[1] = (bank->base + bank->sectors[i].offset) >> 8;
965 FCCOBLO[1] = (bank->base + bank->sectors[i].offset);
966
967 result = kinetis_ke_ftmrx_command(bank, 2, FCCOBIX, FCCOBHI, FCCOBLO, &fstat);
968
969 if (result != ERROR_OK) {
970 LOG_WARNING("erase sector %u failed", i);
971 return ERROR_FLASH_OPERATION_FAILED;
972 }
973
974 if (i == 2)
975 fcf_erased = true;
976 }
977
978 if (fcf_erased) {
979 LOG_WARNING
980 ("flash configuration field erased, please reset the device");
981 }
982
983 return ERROR_OK;
984 }
985
986 static int kinetis_ke_write(struct flash_bank *bank, const uint8_t *buffer,
987 uint32_t offset, uint32_t count)
988 {
989 int result;
990 uint8_t *new_buffer = NULL;
991 uint32_t words = count / 4;
992
993 if (bank->target->state != TARGET_HALTED) {
994 LOG_ERROR("Target not halted");
995 return ERROR_TARGET_NOT_HALTED;
996 }
997
998 if (offset > bank->size)
999 return ERROR_FLASH_BANK_INVALID;
1000
1001 if (offset & 0x3) {
1002 LOG_WARNING("offset 0x%" PRIx32 " breaks the required alignment", offset);
1003 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
1004 }
1005
1006 result = kinetis_ke_stop_watchdog(bank->target);
1007 if (result != ERROR_OK)
1008 return result;
1009
1010 result = kinetis_ke_prepare_flash(bank);
1011 if (result != ERROR_OK)
1012 return result;
1013
1014 if (count & 0x3) {
1015 uint32_t old_count = count;
1016 count = (old_count | 3) + 1;
1017 new_buffer = malloc(count);
1018 if (!new_buffer) {
1019 LOG_ERROR("odd number of bytes to write and no memory "
1020 "for padding buffer");
1021 return ERROR_FAIL;
1022 }
1023
1024 LOG_INFO("odd number of bytes to write (%" PRIu32 "), extending to %" PRIu32 " "
1025 "and padding with 0xff", old_count, count);
1026
1027 memset(new_buffer, 0xff, count);
1028 buffer = memcpy(new_buffer, buffer, old_count);
1029 words++;
1030 }
1031
1032 result = kinetis_ke_write_words(bank, buffer, offset, words);
1033 free(new_buffer);
1034
1035 return result;
1036 }
1037
1038 static int kinetis_ke_probe(struct flash_bank *bank)
1039 {
1040 int result;
1041 uint32_t offset = 0;
1042 struct target *target = bank->target;
1043 struct kinetis_ke_flash_bank *kinfo = bank->driver_priv;
1044
1045 result = target_read_u32(target, SIM_SRSID, &kinfo->sim_srsid);
1046 if (result != ERROR_OK)
1047 return result;
1048
1049 if (KINETIS_KE_SRSID_FAMID(kinfo->sim_srsid) != 0x00) {
1050 LOG_ERROR("Unsupported KE family");
1051 return ERROR_FLASH_OPER_UNSUPPORTED;
1052 }
1053
1054 switch (KINETIS_KE_SRSID_SUBFAMID(kinfo->sim_srsid)) {
1055 case KINETIS_KE_SRSID_KEX2:
1056 LOG_INFO("KE02 sub-family");
1057 break;
1058
1059 case KINETIS_KE_SRSID_KEX4:
1060 LOG_INFO("KE04 sub-family");
1061 break;
1062
1063 case KINETIS_KE_SRSID_KEX6:
1064 LOG_INFO("KE06 sub-family");
1065 break;
1066
1067 default:
1068 LOG_ERROR("Unsupported KE sub-family");
1069 return ERROR_FLASH_OPER_UNSUPPORTED;
1070 }
1071
1072 /* We can only retrieve the ke0x part, but there is no way to know
1073 * the flash size, so assume the maximum flash size for the entire
1074 * sub family.
1075 */
1076 bank->base = 0x00000000;
1077 kinfo->sector_size = 512;
1078
1079 switch (KINETIS_KE_SRSID_SUBFAMID(kinfo->sim_srsid)) {
1080
1081 case KINETIS_KE_SRSID_KEX2:
1082 /* Max. 64KB */
1083 bank->size = 0x00010000;
1084 bank->num_sectors = 128;
1085
1086 /* KE02 uses the FTMRH flash controller,
1087 * and registers have a different offset from the
1088 * FTMRE flash controller. Sort this out here.
1089 */
1090 kinfo->ftmrx_fclkdiv_addr = 0x40020000;
1091 kinfo->ftmrx_fccobix_addr = 0x40020002;
1092 kinfo->ftmrx_fstat_addr = 0x40020006;
1093 kinfo->ftmrx_fprot_addr = 0x40020008;
1094 kinfo->ftmrx_fccobhi_addr = 0x4002000A;
1095 kinfo->ftmrx_fccoblo_addr = 0x4002000B;
1096 break;
1097
1098 case KINETIS_KE_SRSID_KEX6:
1099 case KINETIS_KE_SRSID_KEX4:
1100 /* Max. 128KB */
1101 bank->size = 0x00020000;
1102 bank->num_sectors = 256;
1103
1104 /* KE04 and KE06 use the FTMRE flash controller,
1105 * and registers have a different offset from the
1106 * FTMRH flash controller. Sort this out here.
1107 */
1108 kinfo->ftmrx_fclkdiv_addr = 0x40020003;
1109 kinfo->ftmrx_fccobix_addr = 0x40020001;
1110 kinfo->ftmrx_fstat_addr = 0x40020005;
1111 kinfo->ftmrx_fprot_addr = 0x4002000B;
1112 kinfo->ftmrx_fccobhi_addr = 0x40020009;
1113 kinfo->ftmrx_fccoblo_addr = 0x40020008;
1114 break;
1115 }
1116
1117 free(bank->sectors);
1118
1119 assert(bank->num_sectors > 0);
1120 bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
1121
1122 for (unsigned int i = 0; i < bank->num_sectors; i++) {
1123 bank->sectors[i].offset = offset;
1124 bank->sectors[i].size = kinfo->sector_size;
1125 offset += kinfo->sector_size;
1126 bank->sectors[i].is_erased = -1;
1127 bank->sectors[i].is_protected = 1;
1128 }
1129
1130 return ERROR_OK;
1131 }
1132
1133 static int kinetis_ke_auto_probe(struct flash_bank *bank)
1134 {
1135 struct kinetis_ke_flash_bank *kinfo = bank->driver_priv;
1136
1137 if (kinfo->sim_srsid)
1138 return ERROR_OK;
1139
1140 return kinetis_ke_probe(bank);
1141 }
1142
1143 static int kinetis_ke_info(struct flash_bank *bank, struct command_invocation *cmd)
1144 {
1145 command_print_sameline(cmd, "%s driver for flash bank %s at " TARGET_ADDR_FMT,
1146 bank->driver->name, bank->name, bank->base);
1147
1148 return ERROR_OK;
1149 }
1150
1151 static int kinetis_ke_blank_check(struct flash_bank *bank)
1152 {
1153 uint8_t FCCOBIX[3], FCCOBHI[3], FCCOBLO[3], fstat;
1154 uint16_t longwords = 0;
1155 int result;
1156
1157 if (bank->target->state != TARGET_HALTED) {
1158 LOG_ERROR("Target not halted");
1159 return ERROR_TARGET_NOT_HALTED;
1160 }
1161
1162 result = kinetis_ke_prepare_flash(bank);
1163 if (result != ERROR_OK)
1164 return result;
1165
1166 /* check if whole bank is blank */
1167 FCCOBIX[0] = 0;
1168 FCCOBHI[0] = FTMRX_CMD_ALLERASED;
1169
1170 result = kinetis_ke_ftmrx_command(bank, 1, FCCOBIX, FCCOBHI, NULL, &fstat);
1171
1172 if (result != ERROR_OK)
1173 return result;
1174
1175 if (fstat & (FTMRX_FSTAT_MGSTAT0_MASK | FTMRX_FSTAT_MGSTAT1_MASK)) {
1176 /* the whole bank is not erased, check sector-by-sector */
1177 for (unsigned int i = 0; i < bank->num_sectors; i++) {
1178 FCCOBIX[0] = 0;
1179 FCCOBHI[0] = FTMRX_CMD_SECTIONERASED;
1180 FCCOBLO[0] = (bank->base + bank->sectors[i].offset) >> 16;
1181
1182 FCCOBIX[1] = 1;
1183 FCCOBHI[1] = (bank->base + bank->sectors[i].offset) >> 8;
1184 FCCOBLO[1] = (bank->base + bank->sectors[i].offset);
1185
1186 longwords = 128;
1187
1188 FCCOBIX[2] = 2;
1189 FCCOBHI[2] = longwords >> 8;
1190 FCCOBLO[2] = longwords;
1191
1192 result = kinetis_ke_ftmrx_command(bank, 3, FCCOBIX, FCCOBHI, FCCOBLO, &fstat);
1193
1194 if (result == ERROR_OK) {
1195 bank->sectors[i].is_erased = !(fstat & (FTMRX_FSTAT_MGSTAT0_MASK | FTMRX_FSTAT_MGSTAT1_MASK));
1196 } else {
1197 LOG_DEBUG("Ignoring error on PFlash sector blank-check");
1198 bank->sectors[i].is_erased = -1;
1199 }
1200 }
1201 } else {
1202 /* the whole bank is erased, update all sectors */
1203 for (unsigned int i = 0; i < bank->num_sectors; i++)
1204 bank->sectors[i].is_erased = 1;
1205 }
1206
1207 return ERROR_OK;
1208 }
1209
1210 static const struct command_registration kinetis_ke_security_command_handlers[] = {
1211 {
1212 .name = "check_security",
1213 .mode = COMMAND_EXEC,
1214 .help = "Check status of device security lock",
1215 .usage = "",
1216 .handler = kinetis_ke_check_flash_security_status,
1217 },
1218 {
1219 .name = "mass_erase",
1220 .mode = COMMAND_EXEC,
1221 .help = "Issue a complete flash erase via the MDM-AP",
1222 .usage = "",
1223 .handler = kinetis_ke_mdm_mass_erase,
1224 },
1225 COMMAND_REGISTRATION_DONE
1226 };
1227
1228 static const struct command_registration kinetis_ke_exec_command_handlers[] = {
1229 {
1230 .name = "mdm",
1231 .mode = COMMAND_ANY,
1232 .help = "MDM-AP command group",
1233 .usage = "",
1234 .chain = kinetis_ke_security_command_handlers,
1235 },
1236 {
1237 .name = "disable_wdog",
1238 .mode = COMMAND_EXEC,
1239 .help = "Disable the watchdog timer",
1240 .usage = "",
1241 .handler = kinetis_ke_disable_wdog_handler,
1242 },
1243 COMMAND_REGISTRATION_DONE
1244 };
1245
1246 static const struct command_registration kinetis_ke_command_handler[] = {
1247 {
1248 .name = "kinetis_ke",
1249 .mode = COMMAND_ANY,
1250 .help = "Kinetis KE flash controller commands",
1251 .usage = "",
1252 .chain = kinetis_ke_exec_command_handlers,
1253 },
1254 COMMAND_REGISTRATION_DONE
1255 };
1256
1257 const struct flash_driver kinetis_ke_flash = {
1258 .name = "kinetis_ke",
1259 .commands = kinetis_ke_command_handler,
1260 .flash_bank_command = kinetis_ke_flash_bank_command,
1261 .erase = kinetis_ke_erase,
1262 .protect = kinetis_ke_protect,
1263 .write = kinetis_ke_write,
1264 .read = default_flash_read,
1265 .probe = kinetis_ke_probe,
1266 .auto_probe = kinetis_ke_auto_probe,
1267 .erase_check = kinetis_ke_blank_check,
1268 .protect_check = kinetis_ke_protect_check,
1269 .info = kinetis_ke_info,
1270 .free_driver_priv = default_flash_free_driver_priv,
1271 };

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)