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