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 const 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 (unsigned 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
= 512 * 1024;
370 bank
->size
= 1024 * 1024;
373 bank
->size
= 2048 * 1024;
376 LOG_ERROR("unrecognized flash size code: %d", nvm_size_code
);
380 struct samv_flash_bank
*samv_info
= bank
->driver_priv
;
381 samv_info
->size_bytes
= bank
->size
;
382 samv_info
->probed
= true;
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;
394 r
= samv_protect_check(bank
);
401 static int samv_auto_probe(struct flash_bank
*bank
)
403 struct samv_flash_bank
*samv_info
= bank
->driver_priv
;
404 if (samv_info
->probed
)
406 return samv_probe(bank
);
409 static int samv_erase(struct flash_bank
*bank
, unsigned int first
,
412 const int page_count
= 32; /* 32 pages equals 16 KB lock region */
414 if (bank
->target
->state
!= TARGET_HALTED
) {
415 LOG_ERROR("Target not halted");
416 return ERROR_TARGET_NOT_HALTED
;
419 int r
= samv_auto_probe(bank
);
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
);
427 LOG_INFO("erasing lock regions %u-%u...", first
, last
);
429 for (unsigned int i
= first
; i
<= last
; i
++) {
431 r
= samv_erase_pages(bank
->target
, (i
* page_count
), page_count
, &status
);
432 LOG_INFO("erasing lock region %u", i
);
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
);
439 if (status
& (1 << 1)) {
440 LOG_ERROR("flash command error @lock region %u", i
);
447 static int samv_protect(struct flash_bank
*bank
, int set
, unsigned int first
,
450 if (bank
->target
->state
!= TARGET_HALTED
) {
451 LOG_ERROR("Target not halted");
452 return ERROR_TARGET_NOT_HALTED
;
457 r
= samv_flash_lock(bank
->target
, first
, last
);
459 r
= samv_flash_unlock(bank
->target
, first
, last
);
464 static int samv_page_read(struct target
*target
,
465 unsigned page_num
, uint8_t *buf
)
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
);
470 LOG_ERROR("flash program failed to read page @ 0x%08x",
471 (unsigned int)(addr
));
475 static int samv_page_write(struct target
*target
,
476 unsigned pagenum
, const uint8_t *buf
)
479 const uint32_t addr
= SAMV_FLASH_BASE
+ pagenum
* SAMV_PAGE_SIZE
;
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
);
485 LOG_ERROR("failed to buffer page at 0x%08x", (unsigned int)addr
);
489 r
= samv_efc_perform_command(target
, SAMV_EFC_FCMD_WP
, pagenum
, &status
);
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
);
496 if (status
& (1 << 1)) {
497 LOG_ERROR("flash command error at 0x%08x", (unsigned int)addr
);
503 static int samv_write(struct flash_bank
*bank
, const uint8_t *buffer
,
504 uint32_t offset
, uint32_t count
)
506 if (bank
->target
->state
!= TARGET_HALTED
) {
507 LOG_ERROR("target not halted");
508 return ERROR_TARGET_NOT_HALTED
;
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
));
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
;
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
));
531 /* Special case: all one page */
533 /* (1) non-aligned start */
535 /* (3) non-aligned end. */
538 uint32_t page_offset
;
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
);
547 page_offset
= offset
& (SAMV_PAGE_SIZE
-1);
548 memcpy(pagebuffer
+ page_offset
, buffer
, count
);
550 r
= samv_page_write(bank
->target
, page_cur
, pagebuffer
);
556 /* step 1) handle the non-aligned starting address */
557 page_offset
= offset
& (SAMV_PAGE_SIZE
- 1);
559 LOG_DEBUG("non-aligned start");
560 /* read the partial page */
561 r
= samv_page_read(bank
->target
, page_cur
, pagebuffer
);
565 /* over-write with new data */
566 uint32_t n
= SAMV_PAGE_SIZE
- page_offset
;
567 memcpy(pagebuffer
+ page_offset
, buffer
, n
);
569 r
= samv_page_write(bank
->target
, page_cur
, pagebuffer
);
579 /* By checking that offset is correct here, we also fix a clang warning */
580 assert(offset
% SAMV_PAGE_SIZE
== 0);
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
));
586 while ((page_cur
< page_end
) && (count
>= SAMV_PAGE_SIZE
)) {
587 r
= samv_page_write(bank
->target
, page_cur
, buffer
);
590 count
-= SAMV_PAGE_SIZE
;
591 buffer
+= SAMV_PAGE_SIZE
;
595 /* step 3) write final page, if it's partial (otherwise it's already done) */
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
);
602 memcpy(pagebuffer
, buffer
, count
); /* data goes at start of page */
603 r
= samv_page_write(bank
->target
, page_cur
, pagebuffer
);
610 static int samv_get_info(struct flash_bank
*bank
, char *buf
, int buf_size
)
612 struct samv_flash_bank
*samv_info
= bank
->driver_priv
;
613 if (!samv_info
->probed
) {
614 int r
= samv_probe(bank
);
618 snprintf(buf
, buf_size
, "Cortex-M7 detected with %d kB flash",
623 COMMAND_HANDLER(samv_handle_gpnvm_command
)
625 struct flash_bank
*bank
= get_flash_bank_by_num_noprobe(0);
628 struct samv_flash_bank
*samv_info
= bank
->driver_priv
;
629 struct target
*target
= bank
->target
;
631 if (target
->state
!= TARGET_HALTED
) {
632 LOG_ERROR("target not halted");
633 return ERROR_TARGET_NOT_HALTED
;
637 if (!samv_info
->probed
) {
638 r
= samv_auto_probe(bank
);
652 if (!strcmp(CMD_ARGV
[0], "show") && !strcmp(CMD_ARGV
[1], "all"))
656 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[1], v32
);
661 return ERROR_COMMAND_SYNTAX_ERROR
;
665 if (!strcmp("show", CMD_ARGV
[0])) {
669 for (int x
= 0; x
< SAMV_NUM_GPNVM_BITS
; x
++) {
670 r
= samv_get_gpnvm(target
, x
, &v
);
673 command_print(CMD
, "samv-gpnvm%u: %u", x
, v
);
677 if ((who
>= 0) && (((unsigned)who
) < SAMV_NUM_GPNVM_BITS
)) {
678 r
= samv_get_gpnvm(target
, who
, &v
);
679 command_print(CMD
, "samv-gpnvm%u: %u", who
, v
);
682 command_print(CMD
, "invalid gpnvm: %u", who
);
683 return ERROR_COMMAND_SYNTAX_ERROR
;
688 command_print(CMD
, "missing gpnvm number");
689 return ERROR_COMMAND_SYNTAX_ERROR
;
692 if (!strcmp("set", CMD_ARGV
[0]))
693 r
= samv_set_gpnvm(target
, who
);
694 else if (!strcmp("clr", CMD_ARGV
[0]) || !strcmp("clear", CMD_ARGV
[0]))
695 r
= samv_clear_gpnvm(target
, who
);
697 command_print(CMD
, "unknown command: %s", CMD_ARGV
[0]);
698 r
= ERROR_COMMAND_SYNTAX_ERROR
;
703 static const struct command_registration atsamv_exec_command_handlers
[] = {
706 .handler
= samv_handle_gpnvm_command
,
707 .mode
= COMMAND_EXEC
,
708 .usage
= "[('clr'|'set'|'show') bitnum]",
709 .help
= "Without arguments, shows all bits in the gpnvm "
710 "register. Otherwise, clears, sets, or shows one "
711 "General Purpose Non-Volatile Memory (gpnvm) bit.",
713 COMMAND_REGISTRATION_DONE
716 static const struct command_registration atsamv_command_handlers
[] = {
720 .help
= "atsamv flash command group",
722 .chain
= atsamv_exec_command_handlers
,
724 COMMAND_REGISTRATION_DONE
727 const struct flash_driver atsamv_flash
= {
729 .commands
= atsamv_command_handlers
,
730 .flash_bank_command
= samv_flash_bank_command
,
732 .protect
= samv_protect
,
734 .read
= default_flash_read
,
736 .auto_probe
= samv_auto_probe
,
737 .erase_check
= default_flash_blank_check
,
738 .protect_check
= samv_protect_check
,
739 .info
= samv_get_info
,
740 .free_driver_priv
= default_flash_free_driver_priv
,