1 /***************************************************************************
2 * Copyright (C) 2009 by Duane Ellis *
3 * openocd@duaneellis.com *
5 * Copyright (C) 2010 by Olaf Lüke (at91sam3s* support) *
6 * olaf@uni-paderborn.de *
8 * Copyright (C) 2011 by Olivier Schonken, Jim Norris *
9 * (at91sam3x* & at91sam4 support)* *
11 * Copyright (C) 2015 Morgan Quigley *
12 * (atsamv, atsams, and atsame support) *
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. *
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. *
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 ***************************************************************************/
28 /* Some of the the lower level code was based on code supplied by
29 * ATMEL under this copyright. */
31 /* BEGIN ATMEL COPYRIGHT */
32 /* ----------------------------------------------------------------------------
33 * ATMEL Microcontroller Software Support
34 * ----------------------------------------------------------------------------
35 * Copyright (c) 2009, Atmel Corporation
37 * All rights reserved.
39 * Redistribution and use in source and binary forms, with or without
40 * modification, are permitted provided that the following conditions are met:
42 * - Redistributions of source code must retain the above copyright notice,
43 * this list of conditions and the disclaimer below.
45 * Atmel's name may not be used to endorse or promote products derived from
46 * this software without specific prior written permission.
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 * ----------------------------------------------------------------------------
60 /* END ATMEL COPYRIGHT */
67 #include <helper/time_support.h>
69 #define REG_NAME_WIDTH (12)
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 */
85 #define OFFSET_EFC_FMR 0
86 #define OFFSET_EFC_FCR 4
87 #define OFFSET_EFC_FSR 8
88 #define OFFSET_EFC_FRR 12
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
97 extern struct flash_driver atsamv_flash
;
99 struct samv_flash_bank
{
102 unsigned gpnvm
[SAMV_NUM_GPNVM_BITS
];
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 */
112 static int samv_efc_get_status(struct target
*target
, uint32_t *v
)
114 int r
= target_read_u32(target
, SAMV_CONTROLLER_ADDR
+ OFFSET_EFC_FSR
, v
);
118 static int samv_efc_get_result(struct target
*target
, uint32_t *v
)
121 int r
= target_read_u32(target
, SAMV_CONTROLLER_ADDR
+ OFFSET_EFC_FRR
, &rv
);
127 static int samv_efc_start_command(struct target
*target
,
128 unsigned command
, unsigned argument
)
131 samv_efc_get_status(target
, &v
);
133 LOG_ERROR("flash controller is not ready");
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
);
141 LOG_DEBUG("write failed");
145 static int samv_efc_perform_command(struct target
*target
,
146 unsigned command
, unsigned argument
, uint32_t *status
)
150 int64_t ms_now
, ms_end
;
155 r
= samv_efc_start_command(target
, command
, argument
);
159 ms_end
= 10000 + timeval_ms();
162 r
= samv_efc_get_status(target
, &v
);
165 ms_now
= timeval_ms();
166 if (ms_now
> ms_end
) {
168 LOG_ERROR("Command timeout");
171 } while ((v
& 1) == 0);
173 /* if requested, copy the flash controller error bits back to the caller */
179 static int samv_erase_pages(struct target
*target
,
180 int first_page
, int num_pages
, uint32_t *status
)
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...
208 return samv_efc_perform_command(target
, SAMV_EFC_FCMD_EPA
,
209 first_page
| erase_pages
, status
);
212 static int samv_get_gpnvm(struct target
*target
, unsigned gpnvm
, unsigned *out
)
217 if (gpnvm
>= SAMV_NUM_GPNVM_BITS
) {
218 LOG_ERROR("invalid gpnvm %d, max: %d", gpnvm
, SAMV_NUM_GPNVM_BITS
);
222 r
= samv_efc_perform_command(target
, SAMV_EFC_FCMD_GFB
, 0, NULL
);
224 LOG_ERROR("samv_get_gpnvm failed");
228 r
= samv_efc_get_result(target
, &v
);
231 *out
= (v
>> gpnvm
) & 1;
236 static int samv_clear_gpnvm(struct target
*target
, unsigned gpnvm
)
241 if (gpnvm
>= SAMV_NUM_GPNVM_BITS
) {
242 LOG_ERROR("invalid gpnvm %d, max: %d", gpnvm
, SAMV_NUM_GPNVM_BITS
);
245 r
= samv_get_gpnvm(target
, gpnvm
, &v
);
247 LOG_DEBUG("get gpnvm failed: %d", r
);
250 r
= samv_efc_perform_command(target
, SAMV_EFC_FCMD_CFB
, gpnvm
, NULL
);
251 LOG_DEBUG("clear gpnvm result: %d", r
);
255 static int samv_set_gpnvm(struct target
*target
, unsigned gpnvm
)
259 if (gpnvm
>= SAMV_NUM_GPNVM_BITS
) {
260 LOG_ERROR("invalid gpnvm %d, max: %d", gpnvm
, SAMV_NUM_GPNVM_BITS
);
264 r
= samv_get_gpnvm(target
, gpnvm
, &v
);
268 r
= ERROR_OK
; /* the gpnvm bit is already set */
270 /* we need to set it */
271 r
= samv_efc_perform_command(target
, SAMV_EFC_FCMD_SFB
, gpnvm
, NULL
);
276 static int samv_flash_unlock(struct target
*target
,
277 unsigned start_sector
, unsigned end_sector
)
282 uint32_t pages_per_sector
;
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
);
296 static int samv_flash_lock(struct target
*target
,
297 unsigned start_sector
, unsigned end_sector
)
301 uint32_t pages_per_sector
;
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
);
316 static int samv_protect_check(struct flash_bank
*bank
)
321 r
= samv_efc_perform_command(bank
->target
, SAMV_EFC_FCMD_GLB
, 0, NULL
);
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]);
331 for (int x
= 0; x
< bank
->num_sectors
; x
++)
332 bank
->sectors
[x
].is_protected
= (!!(v
[x
>> 5] & (1 << (x
% 32))));
336 FLASH_BANK_COMMAND_HANDLER(samv_flash_bank_command
)
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
;
345 static int samv_get_device_id(struct flash_bank
*bank
, uint32_t *device_id
)
347 return target_read_u32(bank
->target
, SAMV_CHIPID_CIDR
, device_id
);
350 static int samv_probe(struct flash_bank
*bank
)
353 int r
= samv_get_device_id(bank
, &device_id
);
356 LOG_INFO("device id = 0x%08" PRIx32
"", device_id
);
358 uint8_t eproc
= (device_id
>> 5) & 0x7;
360 LOG_ERROR("unexpected eproc code: %d was expecting 0 (Cortex-M7)", eproc
);
364 uint8_t nvm_size_code
= (device_id
>> 8) & 0xf;
365 switch (nvm_size_code
) {
367 bank
->size
= 1024 * 1024;
370 bank
->size
= 2048 * 1024;
373 LOG_ERROR("unrecognized flash size code: %d", nvm_size_code
);
378 struct samv_flash_bank
*samv_info
= bank
->driver_priv
;
379 samv_info
->size_bytes
= bank
->size
;
380 samv_info
->probed
= 1;
382 bank
->base
= SAMV_FLASH_BASE
;
383 bank
->num_sectors
= bank
->size
/ SAMV_SECTOR_SIZE
;
384 bank
->sectors
= calloc(bank
->num_sectors
, sizeof(struct flash_sector
));
385 for (int s
= 0; s
< (int)bank
->num_sectors
; s
++) {
386 bank
->sectors
[s
].size
= SAMV_SECTOR_SIZE
;
387 bank
->sectors
[s
].offset
= s
* SAMV_SECTOR_SIZE
;
388 bank
->sectors
[s
].is_erased
= -1;
389 bank
->sectors
[s
].is_protected
= -1;
392 r
= samv_protect_check(bank
);
399 static int samv_auto_probe(struct flash_bank
*bank
)
401 struct samv_flash_bank
*samv_info
= bank
->driver_priv
;
402 if (samv_info
->probed
)
404 return samv_probe(bank
);
407 static int samv_erase(struct flash_bank
*bank
, int first
, int last
)
409 const int page_count
= 32; /* 32 pages equals 16 KB lock region */
411 if (bank
->target
->state
!= TARGET_HALTED
) {
412 LOG_ERROR("Target not halted");
413 return ERROR_TARGET_NOT_HALTED
;
416 int r
= samv_auto_probe(bank
);
420 /* easy case: we've been requested to erase the entire flash */
421 if ((first
== 0) && ((last
+ 1) == (int)(bank
->num_sectors
)))
422 return samv_efc_perform_command(bank
->target
, SAMV_EFC_FCMD_EA
, 0, NULL
);
424 LOG_INFO("erasing lock regions %d-%d...", first
, last
);
426 for (int i
= first
; i
<= last
; i
++) {
428 r
= samv_erase_pages(bank
->target
, (i
* page_count
), page_count
, &status
);
429 LOG_INFO("erasing lock region %d", i
);
431 LOG_ERROR("error performing erase page @ lock region number %d",
433 if (status
& (1 << 2)) {
434 LOG_ERROR("lock region %d is locked", (unsigned int)(i
));
437 if (status
& (1 << 1)) {
438 LOG_ERROR("flash command error @lock region %d", (unsigned int)(i
));
445 static int samv_protect(struct flash_bank
*bank
, int set
, int first
, int last
)
447 if (bank
->target
->state
!= TARGET_HALTED
) {
448 LOG_ERROR("Target not halted");
449 return ERROR_TARGET_NOT_HALTED
;
454 r
= samv_flash_lock(bank
->target
, (unsigned)(first
), (unsigned)(last
));
456 r
= samv_flash_unlock(bank
->target
, (unsigned)(first
), (unsigned)(last
));
461 static int samv_page_read(struct target
*target
,
462 unsigned page_num
, uint8_t *buf
)
464 uint32_t addr
= SAMV_FLASH_BASE
+ page_num
* SAMV_PAGE_SIZE
;
465 int r
= target_read_memory(target
, addr
, 4, SAMV_PAGE_SIZE
/ 4, buf
);
467 LOG_ERROR("flash program failed to read page @ 0x%08x",
468 (unsigned int)(addr
));
472 static int samv_page_write(struct target
*target
,
473 unsigned pagenum
, const uint8_t *buf
)
476 const uint32_t addr
= SAMV_FLASH_BASE
+ pagenum
* SAMV_PAGE_SIZE
;
479 LOG_DEBUG("write page %u at address 0x%08x", pagenum
, (unsigned int)addr
);
480 r
= target_write_memory(target
, addr
, 4, SAMV_PAGE_SIZE
/ 4, buf
);
482 LOG_ERROR("failed to buffer page at 0x%08x", (unsigned int)addr
);
486 r
= samv_efc_perform_command(target
, SAMV_EFC_FCMD_WP
, pagenum
, &status
);
488 LOG_ERROR("error performing write page at 0x%08x", (unsigned int)addr
);
489 if (status
& (1 << 2)) {
490 LOG_ERROR("page at 0x%08x is locked", (unsigned int)addr
);
493 if (status
& (1 << 1)) {
494 LOG_ERROR("flash command error at 0x%08x", (unsigned int)addr
);
500 static int samv_write(struct flash_bank
*bank
, const uint8_t *buffer
,
501 uint32_t offset
, uint32_t count
)
503 if (bank
->target
->state
!= TARGET_HALTED
) {
504 LOG_ERROR("target not halted");
505 return ERROR_TARGET_NOT_HALTED
;
511 if ((offset
+ count
) > bank
->size
) {
512 LOG_ERROR("flash write error - past end of bank");
513 LOG_ERROR(" offset: 0x%08x, count 0x%08x, bank end: 0x%08x",
514 (unsigned int)(offset
),
515 (unsigned int)(count
),
516 (unsigned int)(bank
->size
));
520 uint8_t pagebuffer
[SAMV_PAGE_SIZE
] = {0};
521 uint32_t page_cur
= offset
/ SAMV_PAGE_SIZE
;
522 uint32_t page_end
= (offset
+ count
- 1) / SAMV_PAGE_SIZE
;
524 LOG_DEBUG("offset: 0x%08x, count: 0x%08x",
525 (unsigned int)(offset
), (unsigned int)(count
));
526 LOG_DEBUG("page start: %d, page end: %d", (int)(page_cur
), (int)(page_end
));
528 /* Special case: all one page */
530 /* (1) non-aligned start */
532 /* (3) non-aligned end. */
535 uint32_t page_offset
;
537 /* handle special case - all one page. */
538 if (page_cur
== page_end
) {
539 LOG_DEBUG("special case, all in one page");
540 r
= samv_page_read(bank
->target
, page_cur
, pagebuffer
);
544 page_offset
= offset
& (SAMV_PAGE_SIZE
-1);
545 memcpy(pagebuffer
+ page_offset
, buffer
, count
);
547 r
= samv_page_write(bank
->target
, page_cur
, pagebuffer
);
553 /* step 1) handle the non-aligned starting address */
554 page_offset
= offset
& (SAMV_PAGE_SIZE
- 1);
556 LOG_DEBUG("non-aligned start");
557 /* read the partial page */
558 r
= samv_page_read(bank
->target
, page_cur
, pagebuffer
);
562 /* over-write with new data */
563 uint32_t n
= SAMV_PAGE_SIZE
- page_offset
;
564 memcpy(pagebuffer
+ page_offset
, buffer
, n
);
566 r
= samv_page_write(bank
->target
, page_cur
, pagebuffer
);
576 /* By checking that offset is correct here, we also fix a clang warning */
577 assert(offset
% SAMV_PAGE_SIZE
== 0);
579 /* step 2) handle the full pages */
580 LOG_DEBUG("full page loop: cur=%d, end=%d, count = 0x%08x",
581 (int)page_cur
, (int)page_end
, (unsigned int)(count
));
583 while ((page_cur
< page_end
) && (count
>= SAMV_PAGE_SIZE
)) {
584 r
= samv_page_write(bank
->target
, page_cur
, buffer
);
587 count
-= SAMV_PAGE_SIZE
;
588 buffer
+= SAMV_PAGE_SIZE
;
592 /* step 3) write final page, if it's partial (otherwise it's already done) */
594 LOG_DEBUG("final partial page, count = 0x%08x", (unsigned int)(count
));
595 /* we have a partial page */
596 r
= samv_page_read(bank
->target
, page_cur
, pagebuffer
);
599 memcpy(pagebuffer
, buffer
, count
); /* data goes at start of page */
600 r
= samv_page_write(bank
->target
, page_cur
, pagebuffer
);
607 static int samv_get_info(struct flash_bank
*bank
, char *buf
, int buf_size
)
609 struct samv_flash_bank
*samv_info
= bank
->driver_priv
;
610 if (!samv_info
->probed
) {
611 int r
= samv_probe(bank
);
615 snprintf(buf
, buf_size
, "Cortex-M7 detected with %d kB flash",
620 COMMAND_HANDLER(samv_handle_gpnvm_command
)
622 struct flash_bank
*bank
= get_flash_bank_by_num_noprobe(0);
625 struct samv_flash_bank
*samv_info
= bank
->driver_priv
;
626 struct target
*target
= bank
->target
;
628 if (target
->state
!= TARGET_HALTED
) {
629 LOG_ERROR("target not halted");
630 return ERROR_TARGET_NOT_HALTED
;
634 if (!samv_info
->probed
) {
635 r
= samv_auto_probe(bank
);
650 if (!strcmp(CMD_ARGV
[0], "show") && !strcmp(CMD_ARGV
[1], "all"))
654 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[1], v32
);
659 return ERROR_COMMAND_SYNTAX_ERROR
;
664 if (!strcmp("show", CMD_ARGV
[0])) {
668 for (int x
= 0; x
< SAMV_NUM_GPNVM_BITS
; x
++) {
669 r
= samv_get_gpnvm(target
, x
, &v
);
672 command_print(CMD_CTX
, "samv-gpnvm%u: %u", x
, v
);
676 if ((who
>= 0) && (((unsigned)who
) < SAMV_NUM_GPNVM_BITS
)) {
677 r
= samv_get_gpnvm(target
, who
, &v
);
678 command_print(CMD_CTX
, "samv-gpnvm%u: %u", who
, v
);
681 command_print(CMD_CTX
, "invalid gpnvm: %u", who
);
682 return ERROR_COMMAND_SYNTAX_ERROR
;
687 command_print(CMD_CTX
, "missing gpnvm number");
688 return ERROR_COMMAND_SYNTAX_ERROR
;
691 if (!strcmp("set", CMD_ARGV
[0]))
692 r
= samv_set_gpnvm(target
, who
);
693 else if (!strcmp("clr", CMD_ARGV
[0]) || !strcmp("clear", CMD_ARGV
[0]))
694 r
= samv_clear_gpnvm(target
, who
);
696 command_print(CMD_CTX
, "unknown command: %s", CMD_ARGV
[0]);
697 r
= ERROR_COMMAND_SYNTAX_ERROR
;
702 static const struct command_registration atsamv_exec_command_handlers
[] = {
705 .handler
= samv_handle_gpnvm_command
,
706 .mode
= COMMAND_EXEC
,
707 .usage
= "[('clr'|'set'|'show') bitnum]",
708 .help
= "Without arguments, shows all bits in the gpnvm "
709 "register. Otherwise, clears, sets, or shows one "
710 "General Purpose Non-Volatile Memory (gpnvm) bit.",
712 COMMAND_REGISTRATION_DONE
715 static const struct command_registration atsamv_command_handlers
[] = {
719 .help
= "atsamv flash command group",
721 .chain
= atsamv_exec_command_handlers
,
723 COMMAND_REGISTRATION_DONE
726 struct flash_driver atsamv_flash
= {
728 .commands
= atsamv_command_handlers
,
729 .flash_bank_command
= samv_flash_bank_command
,
731 .protect
= samv_protect
,
733 .read
= default_flash_read
,
735 .auto_probe
= samv_auto_probe
,
736 .erase_check
= default_flash_blank_check
,
737 .protect_check
= samv_protect_check
,
738 .info
= samv_get_info
,