jtag: linuxgpiod: drop extra parenthesis
[openocd.git] / src / flash / nor / atsamv.c
1 // SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-Source-Code)
2
3 /*
4 * Copyright (C) 2009 by Duane Ellis <openocd@duaneellis.com>
5 *
6 * at91sam3s* support
7 * Copyright (C) 2010 by Olaf Lüke <olaf@uni-paderborn.de>
8 *
9 * at91sam3x* & at91sam4 support
10 * Copyright (C) 2011 by Olivier Schonken and Jim Norris
11 *
12 * atsamv, atsams, and atsame support
13 * Copyright (C) 2015 Morgan Quigley
14 *
15 * Some of the lower level code was based on code supplied by
16 * ATMEL under BSD-Source-Code License and this copyright.
17 * ATMEL Microcontroller Software Support
18 * Copyright (c) 2009, Atmel Corporation. All rights reserved.
19 */
20
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 #include "imp.h"
26 #include <helper/time_support.h>
27
28 #define REG_NAME_WIDTH (12)
29
30 #define SAMV_EFC_FCMD_GETD (0x0) /* (EFC) Get Flash Descriptor */
31 #define SAMV_EFC_FCMD_WP (0x1) /* (EFC) Write Page */
32 #define SAMV_EFC_FCMD_WPL (0x2) /* (EFC) Write Page and Lock */
33 #define SAMV_EFC_FCMD_EWP (0x3) /* (EFC) Erase Page and Write Page */
34 #define SAMV_EFC_FCMD_EWPL (0x4) /* (EFC) Erase Page, Write Page then Lock*/
35 #define SAMV_EFC_FCMD_EA (0x5) /* (EFC) Erase All */
36 #define SAMV_EFC_FCMD_EPA (0x7) /* (EFC) Erase pages */
37 #define SAMV_EFC_FCMD_SLB (0x8) /* (EFC) Set Lock Bit */
38 #define SAMV_EFC_FCMD_CLB (0x9) /* (EFC) Clear Lock Bit */
39 #define SAMV_EFC_FCMD_GLB (0xA) /* (EFC) Get Lock Bit */
40 #define SAMV_EFC_FCMD_SFB (0xB) /* (EFC) Set Fuse Bit */
41 #define SAMV_EFC_FCMD_CFB (0xC) /* (EFC) Clear Fuse Bit */
42 #define SAMV_EFC_FCMD_GFB (0xD) /* (EFC) Get Fuse Bit */
43
44 #define OFFSET_EFC_FMR 0
45 #define OFFSET_EFC_FCR 4
46 #define OFFSET_EFC_FSR 8
47 #define OFFSET_EFC_FRR 12
48
49 #define SAMV_CHIPID_CIDR (0x400E0940)
50 #define SAMV_NUM_GPNVM_BITS 9
51 #define SAMV_CONTROLLER_ADDR (0x400e0c00)
52 #define SAMV_SECTOR_SIZE 16384
53 #define SAMV_PAGE_SIZE 512
54 #define SAMV_FLASH_BASE 0x00400000
55
56 struct samv_flash_bank {
57 bool probed;
58 unsigned size_bytes;
59 unsigned gpnvm[SAMV_NUM_GPNVM_BITS];
60 };
61
62 /* The actual sector size of the SAMV7 flash memory is 128K bytes.
63 * 16 sectors for a 2048KB device. The lock regions are 16KB per lock
64 * region, with a 2048KB device having 128 lock regions.
65 * For the best results, num_sectors is thus set to the number of lock
66 * regions, and the sector_size set to the lock region size. Page
67 * erases are used to erase 16KB sections when programming */
68
69 static int samv_efc_get_status(struct target *target, uint32_t *v)
70 {
71 int r = target_read_u32(target, SAMV_CONTROLLER_ADDR + OFFSET_EFC_FSR, v);
72 return r;
73 }
74
75 static int samv_efc_get_result(struct target *target, uint32_t *v)
76 {
77 uint32_t rv;
78 int r = target_read_u32(target, SAMV_CONTROLLER_ADDR + OFFSET_EFC_FRR, &rv);
79 if (v)
80 *v = rv;
81 return r;
82 }
83
84 static int samv_efc_start_command(struct target *target,
85 unsigned command, unsigned argument)
86 {
87 uint32_t v;
88 samv_efc_get_status(target, &v);
89 if (!(v & 1)) {
90 LOG_ERROR("flash controller is not ready");
91 return ERROR_FAIL;
92 }
93
94 v = (0x5A << 24) | (argument << 8) | command;
95 LOG_DEBUG("starting flash command: 0x%08x", (unsigned int)(v));
96 int r = target_write_u32(target, SAMV_CONTROLLER_ADDR + OFFSET_EFC_FCR, v);
97 if (r != ERROR_OK)
98 LOG_DEBUG("write failed");
99 return r;
100 }
101
102 static int samv_efc_perform_command(struct target *target,
103 unsigned command, unsigned argument, uint32_t *status)
104 {
105 int r;
106 uint32_t v;
107 int64_t ms_now, ms_end;
108
109 if (status)
110 *status = 0;
111
112 r = samv_efc_start_command(target, command, argument);
113 if (r != ERROR_OK)
114 return r;
115
116 ms_end = 10000 + timeval_ms();
117
118 do {
119 r = samv_efc_get_status(target, &v);
120 if (r != ERROR_OK)
121 return r;
122 ms_now = timeval_ms();
123 if (ms_now > ms_end) {
124 /* error */
125 LOG_ERROR("Command timeout");
126 return ERROR_FAIL;
127 }
128 } while ((v & 1) == 0);
129
130 /* if requested, copy the flash controller error bits back to the caller */
131 if (status)
132 *status = (v & 0x6);
133 return ERROR_OK;
134 }
135
136 static int samv_erase_pages(struct target *target,
137 int first_page, int num_pages, uint32_t *status)
138 {
139 uint8_t erase_pages;
140 switch (num_pages) {
141 case 4:
142 erase_pages = 0x00;
143 break;
144 case 8:
145 erase_pages = 0x01;
146 break;
147 case 16:
148 erase_pages = 0x02;
149 break;
150 case 32:
151 erase_pages = 0x03;
152 break;
153 default:
154 erase_pages = 0x00;
155 break;
156 }
157
158 /* SAMV_EFC_FCMD_EPA
159 * According to the datasheet FARG[15:2] defines the page from which
160 * the erase will start.This page must be modulo 4, 8, 16 or 32
161 * according to the number of pages to erase. FARG[1:0] defines the
162 * number of pages to be erased. Previously (firstpage << 2) was used
163 * to conform to this, seems it should not be shifted...
164 */
165 return samv_efc_perform_command(target, SAMV_EFC_FCMD_EPA,
166 first_page | erase_pages, status);
167 }
168
169 static int samv_get_gpnvm(struct target *target, unsigned gpnvm, unsigned *out)
170 {
171 uint32_t v;
172 int r;
173
174 if (gpnvm >= SAMV_NUM_GPNVM_BITS) {
175 LOG_ERROR("invalid gpnvm %d, max: %d", gpnvm, SAMV_NUM_GPNVM_BITS);
176 return ERROR_FAIL;
177 }
178
179 r = samv_efc_perform_command(target, SAMV_EFC_FCMD_GFB, 0, NULL);
180 if (r != ERROR_OK) {
181 LOG_ERROR("samv_get_gpnvm failed");
182 return r;
183 }
184
185 r = samv_efc_get_result(target, &v);
186
187 if (out)
188 *out = (v >> gpnvm) & 1;
189
190 return r;
191 }
192
193 static int samv_clear_gpnvm(struct target *target, unsigned gpnvm)
194 {
195 int r;
196 unsigned v;
197
198 if (gpnvm >= SAMV_NUM_GPNVM_BITS) {
199 LOG_ERROR("invalid gpnvm %d, max: %d", gpnvm, SAMV_NUM_GPNVM_BITS);
200 return ERROR_FAIL;
201 }
202 r = samv_get_gpnvm(target, gpnvm, &v);
203 if (r != ERROR_OK) {
204 LOG_DEBUG("get gpnvm failed: %d", r);
205 return r;
206 }
207 r = samv_efc_perform_command(target, SAMV_EFC_FCMD_CFB, gpnvm, NULL);
208 LOG_DEBUG("clear gpnvm result: %d", r);
209 return r;
210 }
211
212 static int samv_set_gpnvm(struct target *target, unsigned gpnvm)
213 {
214 int r;
215 unsigned v;
216 if (gpnvm >= SAMV_NUM_GPNVM_BITS) {
217 LOG_ERROR("invalid gpnvm %d, max: %d", gpnvm, SAMV_NUM_GPNVM_BITS);
218 return ERROR_FAIL;
219 }
220
221 r = samv_get_gpnvm(target, gpnvm, &v);
222 if (r != ERROR_OK)
223 return r;
224 if (v) {
225 r = ERROR_OK; /* the gpnvm bit is already set */
226 } else {
227 /* we need to set it */
228 r = samv_efc_perform_command(target, SAMV_EFC_FCMD_SFB, gpnvm, NULL);
229 }
230 return r;
231 }
232
233 static int samv_flash_unlock(struct target *target,
234 unsigned start_sector, unsigned end_sector)
235 {
236 int r;
237 uint32_t status;
238 uint32_t pg;
239 uint32_t pages_per_sector;
240
241 /* todo: look into this... i think this should be done on lock regions */
242 pages_per_sector = SAMV_SECTOR_SIZE / SAMV_PAGE_SIZE;
243 while (start_sector <= end_sector) {
244 pg = start_sector * pages_per_sector;
245 r = samv_efc_perform_command(target, SAMV_EFC_FCMD_CLB, pg, &status);
246 if (r != ERROR_OK)
247 return r;
248 start_sector++;
249 }
250 return ERROR_OK;
251 }
252
253 static int samv_flash_lock(struct target *target,
254 unsigned start_sector, unsigned end_sector)
255 {
256 uint32_t status;
257 uint32_t pg;
258 uint32_t pages_per_sector;
259 int r;
260
261 /* todo: look into this... i think this should be done on lock regions */
262 pages_per_sector = SAMV_SECTOR_SIZE / SAMV_PAGE_SIZE;
263 while (start_sector <= end_sector) {
264 pg = start_sector * pages_per_sector;
265 r = samv_efc_perform_command(target, SAMV_EFC_FCMD_SLB, pg, &status);
266 if (r != ERROR_OK)
267 return r;
268 start_sector++;
269 }
270 return ERROR_OK;
271 }
272
273 static int samv_protect_check(struct flash_bank *bank)
274 {
275 int r;
276 uint32_t v[4] = {0};
277
278 r = samv_efc_perform_command(bank->target, SAMV_EFC_FCMD_GLB, 0, NULL);
279 if (r == ERROR_OK) {
280 samv_efc_get_result(bank->target, &v[0]);
281 samv_efc_get_result(bank->target, &v[1]);
282 samv_efc_get_result(bank->target, &v[2]);
283 r = samv_efc_get_result(bank->target, &v[3]);
284 }
285 if (r != ERROR_OK)
286 return r;
287
288 for (unsigned int x = 0; x < bank->num_sectors; x++)
289 bank->sectors[x].is_protected = (!!(v[x >> 5] & (1 << (x % 32))));
290 return ERROR_OK;
291 }
292
293 FLASH_BANK_COMMAND_HANDLER(samv_flash_bank_command)
294 {
295 LOG_INFO("flash bank command");
296 struct samv_flash_bank *samv_info;
297 samv_info = calloc(1, sizeof(struct samv_flash_bank));
298 bank->driver_priv = samv_info;
299 return ERROR_OK;
300 }
301
302 static int samv_get_device_id(struct flash_bank *bank, uint32_t *device_id)
303 {
304 return target_read_u32(bank->target, SAMV_CHIPID_CIDR, device_id);
305 }
306
307 static int samv_probe(struct flash_bank *bank)
308 {
309 uint32_t device_id;
310 int r = samv_get_device_id(bank, &device_id);
311 if (r != ERROR_OK)
312 return r;
313 LOG_INFO("device id = 0x%08" PRIx32 "", device_id);
314
315 uint8_t eproc = (device_id >> 5) & 0x7;
316 if (eproc != 0) {
317 LOG_ERROR("unexpected eproc code: %d was expecting 0 (Cortex-M7)", eproc);
318 return ERROR_FAIL;
319 }
320
321 uint8_t nvm_size_code = (device_id >> 8) & 0xf;
322 switch (nvm_size_code) {
323 case 10:
324 bank->size = 512 * 1024;
325 break;
326 case 12:
327 bank->size = 1024 * 1024;
328 break;
329 case 14:
330 bank->size = 2048 * 1024;
331 break;
332 default:
333 LOG_ERROR("unrecognized flash size code: %d", nvm_size_code);
334 return ERROR_FAIL;
335 }
336
337 struct samv_flash_bank *samv_info = bank->driver_priv;
338 samv_info->size_bytes = bank->size;
339 samv_info->probed = true;
340
341 bank->base = SAMV_FLASH_BASE;
342 bank->num_sectors = bank->size / SAMV_SECTOR_SIZE;
343 bank->sectors = calloc(bank->num_sectors, sizeof(struct flash_sector));
344 for (unsigned int s = 0; s < bank->num_sectors; s++) {
345 bank->sectors[s].size = SAMV_SECTOR_SIZE;
346 bank->sectors[s].offset = s * SAMV_SECTOR_SIZE;
347 bank->sectors[s].is_erased = -1;
348 bank->sectors[s].is_protected = -1;
349 }
350
351 r = samv_protect_check(bank);
352 if (r != ERROR_OK)
353 return r;
354
355 return ERROR_OK;
356 }
357
358 static int samv_auto_probe(struct flash_bank *bank)
359 {
360 struct samv_flash_bank *samv_info = bank->driver_priv;
361 if (samv_info->probed)
362 return ERROR_OK;
363 return samv_probe(bank);
364 }
365
366 static int samv_erase(struct flash_bank *bank, unsigned int first,
367 unsigned int last)
368 {
369 const int page_count = 32; /* 32 pages equals 16 KB lock region */
370
371 if (bank->target->state != TARGET_HALTED) {
372 LOG_ERROR("Target not halted");
373 return ERROR_TARGET_NOT_HALTED;
374 }
375
376 int r = samv_auto_probe(bank);
377 if (r != ERROR_OK)
378 return r;
379
380 /* easy case: we've been requested to erase the entire flash */
381 if ((first == 0) && ((last + 1) == bank->num_sectors))
382 return samv_efc_perform_command(bank->target, SAMV_EFC_FCMD_EA, 0, NULL);
383
384 LOG_INFO("erasing lock regions %u-%u...", first, last);
385
386 for (unsigned int i = first; i <= last; i++) {
387 uint32_t status;
388 r = samv_erase_pages(bank->target, (i * page_count), page_count, &status);
389 LOG_INFO("erasing lock region %u", i);
390 if (r != ERROR_OK)
391 LOG_ERROR("error performing erase page @ lock region number %u", i);
392 if (status & (1 << 2)) {
393 LOG_ERROR("lock region %u is locked", i);
394 return ERROR_FAIL;
395 }
396 if (status & (1 << 1)) {
397 LOG_ERROR("flash command error @lock region %u", i);
398 return ERROR_FAIL;
399 }
400 }
401 return ERROR_OK;
402 }
403
404 static int samv_protect(struct flash_bank *bank, int set, unsigned int first,
405 unsigned int last)
406 {
407 if (bank->target->state != TARGET_HALTED) {
408 LOG_ERROR("Target not halted");
409 return ERROR_TARGET_NOT_HALTED;
410 }
411
412 int r;
413 if (set)
414 r = samv_flash_lock(bank->target, first, last);
415 else
416 r = samv_flash_unlock(bank->target, first, last);
417
418 return r;
419 }
420
421 static int samv_page_read(struct target *target,
422 unsigned page_num, uint8_t *buf)
423 {
424 uint32_t addr = SAMV_FLASH_BASE + page_num * SAMV_PAGE_SIZE;
425 int r = target_read_memory(target, addr, 4, SAMV_PAGE_SIZE / 4, buf);
426 if (r != ERROR_OK)
427 LOG_ERROR("flash program failed to read page @ 0x%08x",
428 (unsigned int)(addr));
429 return r;
430 }
431
432 static int samv_page_write(struct target *target,
433 unsigned pagenum, const uint8_t *buf)
434 {
435 uint32_t status;
436 const uint32_t addr = SAMV_FLASH_BASE + pagenum * SAMV_PAGE_SIZE;
437 int r;
438
439 LOG_DEBUG("write page %u at address 0x%08x", pagenum, (unsigned int)addr);
440 r = target_write_memory(target, addr, 4, SAMV_PAGE_SIZE / 4, buf);
441 if (r != ERROR_OK) {
442 LOG_ERROR("failed to buffer page at 0x%08x", (unsigned int)addr);
443 return r;
444 }
445
446 r = samv_efc_perform_command(target, SAMV_EFC_FCMD_WP, pagenum, &status);
447 if (r != ERROR_OK)
448 LOG_ERROR("error performing write page at 0x%08x", (unsigned int)addr);
449 if (status & (1 << 2)) {
450 LOG_ERROR("page at 0x%08x is locked", (unsigned int)addr);
451 return ERROR_FAIL;
452 }
453 if (status & (1 << 1)) {
454 LOG_ERROR("flash command error at 0x%08x", (unsigned int)addr);
455 return ERROR_FAIL;
456 }
457 return ERROR_OK;
458 }
459
460 static int samv_write(struct flash_bank *bank, const uint8_t *buffer,
461 uint32_t offset, uint32_t count)
462 {
463 if (bank->target->state != TARGET_HALTED) {
464 LOG_ERROR("target not halted");
465 return ERROR_TARGET_NOT_HALTED;
466 }
467
468 if (count == 0)
469 return ERROR_OK;
470
471 if ((offset + count) > bank->size) {
472 LOG_ERROR("flash write error - past end of bank");
473 LOG_ERROR(" offset: 0x%08x, count 0x%08x, bank end: 0x%08x",
474 (unsigned int)(offset),
475 (unsigned int)(count),
476 (unsigned int)(bank->size));
477 return ERROR_FAIL;
478 }
479
480 uint8_t pagebuffer[SAMV_PAGE_SIZE] = {0};
481 uint32_t page_cur = offset / SAMV_PAGE_SIZE;
482 uint32_t page_end = (offset + count - 1) / SAMV_PAGE_SIZE;
483
484 LOG_DEBUG("offset: 0x%08x, count: 0x%08x",
485 (unsigned int)(offset), (unsigned int)(count));
486 LOG_DEBUG("page start: %d, page end: %d", (int)(page_cur), (int)(page_end));
487
488 /* Special case: all one page */
489 /* Otherwise: */
490 /* (1) non-aligned start */
491 /* (2) body pages */
492 /* (3) non-aligned end. */
493
494 int r;
495 uint32_t page_offset;
496
497 /* handle special case - all one page. */
498 if (page_cur == page_end) {
499 LOG_DEBUG("special case, all in one page");
500 r = samv_page_read(bank->target, page_cur, pagebuffer);
501 if (r != ERROR_OK)
502 return r;
503
504 page_offset = offset & (SAMV_PAGE_SIZE-1);
505 memcpy(pagebuffer + page_offset, buffer, count);
506
507 r = samv_page_write(bank->target, page_cur, pagebuffer);
508 if (r != ERROR_OK)
509 return r;
510 return ERROR_OK;
511 }
512
513 /* step 1) handle the non-aligned starting address */
514 page_offset = offset & (SAMV_PAGE_SIZE - 1);
515 if (page_offset) {
516 LOG_DEBUG("non-aligned start");
517 /* read the partial page */
518 r = samv_page_read(bank->target, page_cur, pagebuffer);
519 if (r != ERROR_OK)
520 return r;
521
522 /* over-write with new data */
523 uint32_t n = SAMV_PAGE_SIZE - page_offset;
524 memcpy(pagebuffer + page_offset, buffer, n);
525
526 r = samv_page_write(bank->target, page_cur, pagebuffer);
527 if (r != ERROR_OK)
528 return r;
529
530 count -= n;
531 offset += n;
532 buffer += n;
533 page_cur++;
534 }
535
536 /* By checking that offset is correct here, we also fix a clang warning */
537 assert(offset % SAMV_PAGE_SIZE == 0);
538
539 /* step 2) handle the full pages */
540 LOG_DEBUG("full page loop: cur=%d, end=%d, count = 0x%08x",
541 (int)page_cur, (int)page_end, (unsigned int)(count));
542
543 while ((page_cur < page_end) && (count >= SAMV_PAGE_SIZE)) {
544 r = samv_page_write(bank->target, page_cur, buffer);
545 if (r != ERROR_OK)
546 return r;
547 count -= SAMV_PAGE_SIZE;
548 buffer += SAMV_PAGE_SIZE;
549 page_cur += 1;
550 }
551
552 /* step 3) write final page, if it's partial (otherwise it's already done) */
553 if (count) {
554 LOG_DEBUG("final partial page, count = 0x%08x", (unsigned int)(count));
555 /* we have a partial page */
556 r = samv_page_read(bank->target, page_cur, pagebuffer);
557 if (r != ERROR_OK)
558 return r;
559 memcpy(pagebuffer, buffer, count); /* data goes at start of page */
560 r = samv_page_write(bank->target, page_cur, pagebuffer);
561 if (r != ERROR_OK)
562 return r;
563 }
564 return ERROR_OK;
565 }
566
567 static int samv_get_info(struct flash_bank *bank, struct command_invocation *cmd)
568 {
569 struct samv_flash_bank *samv_info = bank->driver_priv;
570 if (!samv_info->probed) {
571 int r = samv_probe(bank);
572 if (r != ERROR_OK)
573 return r;
574 }
575 command_print_sameline(cmd, "Cortex-M7 detected with %" PRIu32 " kB flash\n",
576 bank->size / 1024);
577 return ERROR_OK;
578 }
579
580 COMMAND_HANDLER(samv_handle_gpnvm_command)
581 {
582 struct flash_bank *bank = get_flash_bank_by_num_noprobe(0);
583 if (!bank)
584 return ERROR_FAIL;
585 struct samv_flash_bank *samv_info = bank->driver_priv;
586 struct target *target = bank->target;
587
588 if (target->state != TARGET_HALTED) {
589 LOG_ERROR("target not halted");
590 return ERROR_TARGET_NOT_HALTED;
591 }
592
593 int r;
594 if (!samv_info->probed) {
595 r = samv_auto_probe(bank);
596 if (r != ERROR_OK)
597 return r;
598 }
599
600 int who = 0;
601
602 switch (CMD_ARGC) {
603 case 0:
604 goto showall;
605 case 1:
606 who = -1;
607 break;
608 case 2:
609 if (!strcmp(CMD_ARGV[0], "show") && !strcmp(CMD_ARGV[1], "all"))
610 who = -1;
611 else {
612 uint32_t v32;
613 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], v32);
614 who = v32;
615 }
616 break;
617 default:
618 return ERROR_COMMAND_SYNTAX_ERROR;
619 }
620
621 unsigned v = 0;
622 if (!strcmp("show", CMD_ARGV[0])) {
623 if (who == -1) {
624 showall:
625 r = ERROR_OK;
626 for (int x = 0; x < SAMV_NUM_GPNVM_BITS; x++) {
627 r = samv_get_gpnvm(target, x, &v);
628 if (r != ERROR_OK)
629 break;
630 command_print(CMD, "samv-gpnvm%u: %u", x, v);
631 }
632 return r;
633 }
634 if ((who >= 0) && (((unsigned)who) < SAMV_NUM_GPNVM_BITS)) {
635 r = samv_get_gpnvm(target, who, &v);
636 if (r != ERROR_OK)
637 return r;
638
639 command_print(CMD, "samv-gpnvm%u: %u", who, v);
640 return r;
641 } else {
642 command_print(CMD, "invalid gpnvm: %u", who);
643 return ERROR_COMMAND_SYNTAX_ERROR;
644 }
645 }
646
647 if (who == -1) {
648 command_print(CMD, "missing gpnvm number");
649 return ERROR_COMMAND_SYNTAX_ERROR;
650 }
651
652 if (!strcmp("set", CMD_ARGV[0]))
653 r = samv_set_gpnvm(target, who);
654 else if (!strcmp("clr", CMD_ARGV[0]) || !strcmp("clear", CMD_ARGV[0]))
655 r = samv_clear_gpnvm(target, who);
656 else {
657 command_print(CMD, "unknown command: %s", CMD_ARGV[0]);
658 r = ERROR_COMMAND_SYNTAX_ERROR;
659 }
660 return r;
661 }
662
663 static const struct command_registration atsamv_exec_command_handlers[] = {
664 {
665 .name = "gpnvm",
666 .handler = samv_handle_gpnvm_command,
667 .mode = COMMAND_EXEC,
668 .usage = "[('clr'|'set'|'show') bitnum]",
669 .help = "Without arguments, shows all bits in the gpnvm "
670 "register. Otherwise, clears, sets, or shows one "
671 "General Purpose Non-Volatile Memory (gpnvm) bit.",
672 },
673 COMMAND_REGISTRATION_DONE
674 };
675
676 static const struct command_registration atsamv_command_handlers[] = {
677 {
678 .name = "atsamv",
679 .mode = COMMAND_ANY,
680 .help = "atsamv flash command group",
681 .usage = "",
682 .chain = atsamv_exec_command_handlers,
683 },
684 COMMAND_REGISTRATION_DONE
685 };
686
687 const struct flash_driver atsamv_flash = {
688 .name = "atsamv",
689 .commands = atsamv_command_handlers,
690 .flash_bank_command = samv_flash_bank_command,
691 .erase = samv_erase,
692 .protect = samv_protect,
693 .write = samv_write,
694 .read = default_flash_read,
695 .probe = samv_probe,
696 .auto_probe = samv_auto_probe,
697 .erase_check = default_flash_blank_check,
698 .protect_check = samv_protect_check,
699 .info = samv_get_info,
700 .free_driver_priv = default_flash_free_driver_priv,
701 };

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)