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