efc242395f0a09639f1ddfb3424214d50a781495
[fw/openocd] / 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 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 const struct flash_driver atsamv_flash;
98
99 struct samv_flash_bank {
100         bool      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 (unsigned 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         }
379
380         struct samv_flash_bank *samv_info = bank->driver_priv;
381         samv_info->size_bytes = bank->size;
382         samv_info->probed = true;
383
384         bank->base = SAMV_FLASH_BASE;
385         bank->num_sectors = bank->size / SAMV_SECTOR_SIZE;
386         bank->sectors = calloc(bank->num_sectors, sizeof(struct flash_sector));
387         for (unsigned int s = 0; s < bank->num_sectors; s++) {
388                 bank->sectors[s].size = SAMV_SECTOR_SIZE;
389                 bank->sectors[s].offset = s * SAMV_SECTOR_SIZE;
390                 bank->sectors[s].is_erased = -1;
391                 bank->sectors[s].is_protected = -1;
392         }
393
394         r = samv_protect_check(bank);
395         if (r != ERROR_OK)
396                 return r;
397
398         return ERROR_OK;
399 }
400
401 static int samv_auto_probe(struct flash_bank *bank)
402 {
403         struct samv_flash_bank *samv_info = bank->driver_priv;
404         if (samv_info->probed)
405                 return ERROR_OK;
406         return samv_probe(bank);
407 }
408
409 static int samv_erase(struct flash_bank *bank, unsigned int first,
410                 unsigned 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) == bank->num_sectors))
425                 return samv_efc_perform_command(bank->target, SAMV_EFC_FCMD_EA, 0, NULL);
426
427         LOG_INFO("erasing lock regions %u-%u...", first, last);
428
429         for (unsigned 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 %u", i);
433                 if (r != ERROR_OK)
434                         LOG_ERROR("error performing erase page @ lock region number %u", i);
435                 if (status & (1 << 2)) {
436                         LOG_ERROR("lock region %u is locked", i);
437                         return ERROR_FAIL;
438                 }
439                 if (status & (1 << 1)) {
440                         LOG_ERROR("flash command error @lock region %u", i);
441                         return ERROR_FAIL;
442                 }
443         }
444         return ERROR_OK;
445 }
446
447 static int samv_protect(struct flash_bank *bank, int set, unsigned int first,
448                 unsigned 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, first, last);
458         else
459                 r = samv_flash_unlock(bank->target, first, 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, struct command_invocation *cmd)
611 {
612         struct samv_flash_bank *samv_info = bank->driver_priv;
613         if (!samv_info->probed) {
614                 int r = samv_probe(bank);
615                 if (r != ERROR_OK)
616                         return r;
617         }
618         command_print_sameline(cmd, "Cortex-M7 detected with %" PRIu32 " kB flash\n",
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                 case 1:
649                         who = -1;
650                         break;
651                 case 2:
652                         if (!strcmp(CMD_ARGV[0], "show") && !strcmp(CMD_ARGV[1], "all"))
653                                 who = -1;
654                         else {
655                                 uint32_t v32;
656                                 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], v32);
657                                 who = v32;
658                         }
659                         break;
660                 default:
661                         return ERROR_COMMAND_SYNTAX_ERROR;
662         }
663
664         unsigned v = 0;
665         if (!strcmp("show", CMD_ARGV[0])) {
666                 if (who == -1) {
667 showall:
668                         r = ERROR_OK;
669                         for (int x = 0; x < SAMV_NUM_GPNVM_BITS; x++) {
670                                 r = samv_get_gpnvm(target, x, &v);
671                                 if (r != ERROR_OK)
672                                         break;
673                                 command_print(CMD, "samv-gpnvm%u: %u", x, v);
674                         }
675                         return r;
676                 }
677                 if ((who >= 0) && (((unsigned)who) < SAMV_NUM_GPNVM_BITS)) {
678                         r = samv_get_gpnvm(target, who, &v);
679                         if (r != ERROR_OK)
680                                 return r;
681
682                         command_print(CMD, "samv-gpnvm%u: %u", who, v);
683                         return r;
684                 } else {
685                         command_print(CMD, "invalid gpnvm: %u", who);
686                         return ERROR_COMMAND_SYNTAX_ERROR;
687                 }
688         }
689
690         if (who == -1) {
691                 command_print(CMD, "missing gpnvm number");
692                 return ERROR_COMMAND_SYNTAX_ERROR;
693         }
694
695         if (!strcmp("set", CMD_ARGV[0]))
696                 r = samv_set_gpnvm(target, who);
697         else if (!strcmp("clr", CMD_ARGV[0]) || !strcmp("clear", CMD_ARGV[0]))
698                 r = samv_clear_gpnvm(target, who);
699         else {
700                 command_print(CMD, "unknown command: %s", CMD_ARGV[0]);
701                 r = ERROR_COMMAND_SYNTAX_ERROR;
702         }
703         return r;
704 }
705
706 static const struct command_registration atsamv_exec_command_handlers[] = {
707         {
708                 .name = "gpnvm",
709                 .handler = samv_handle_gpnvm_command,
710                 .mode = COMMAND_EXEC,
711                 .usage = "[('clr'|'set'|'show') bitnum]",
712                 .help = "Without arguments, shows all bits in the gpnvm "
713                         "register.  Otherwise, clears, sets, or shows one "
714                         "General Purpose Non-Volatile Memory (gpnvm) bit.",
715         },
716         COMMAND_REGISTRATION_DONE
717 };
718
719 static const struct command_registration atsamv_command_handlers[] = {
720         {
721                 .name = "atsamv",
722                 .mode = COMMAND_ANY,
723                 .help = "atsamv flash command group",
724                 .usage = "",
725                 .chain = atsamv_exec_command_handlers,
726         },
727         COMMAND_REGISTRATION_DONE
728 };
729
730 const struct flash_driver atsamv_flash = {
731         .name = "atsamv",
732         .commands = atsamv_command_handlers,
733         .flash_bank_command = samv_flash_bank_command,
734         .erase = samv_erase,
735         .protect = samv_protect,
736         .write = samv_write,
737         .read = default_flash_read,
738         .probe = samv_probe,
739         .auto_probe = samv_auto_probe,
740         .erase_check = default_flash_blank_check,
741         .protect_check = samv_protect_check,
742         .info = samv_get_info,
743         .free_driver_priv = default_flash_free_driver_priv,
744 };