907302eb2b75f15de3b56ffbe219b326f592e4ca
[openocd.git] / src / flash / at91sam7.c
1 /***************************************************************************
2 * Copyright (C) 2006 by Magnus Lundin *
3 * lundin@mlu.mine.nu *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
20
21 /***************************************************************************
22 There are some things to notice
23
24 * AT91SAM7S64 is tested
25 * All AT91SAM7Sxx and AT91SAM7Xxx should work but is not tested
26 * All parameters are identified from onchip configuartion registers
27 *
28 * The flash controller handles erases automatically on a page (128/265 byte) basis
29 * Only an EraseAll command is supported by the controller
30 * Partial erases can be implemented in software by writing one 0xFFFFFFFF word to
31 * some location in every page in the region to be erased
32 *
33 * Lock regions (sectors) are 32 or 64 pages
34 *
35 ***************************************************************************/
36 #ifdef HAVE_CONFIG_H
37 #include "config.h"
38 #endif
39
40 #include "replacements.h"
41
42 #include "at91sam7.h"
43
44 #include "flash.h"
45 #include "target.h"
46 #include "log.h"
47 #include "binarybuffer.h"
48 #include "types.h"
49
50 #include <stdlib.h>
51 #include <string.h>
52 #include <unistd.h>
53
54 int at91sam7_register_commands(struct command_context_s *cmd_ctx);
55 int at91sam7_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank);
56 int at91sam7_erase(struct flash_bank_s *bank, int first, int last);
57 int at91sam7_protect(struct flash_bank_s *bank, int set, int first, int last);
58 int at91sam7_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count);
59 int at91sam7_probe(struct flash_bank_s *bank);
60 int at91sam7_erase_check(struct flash_bank_s *bank);
61 int at91sam7_protect_check(struct flash_bank_s *bank);
62 int at91sam7_info(struct flash_bank_s *bank, char *buf, int buf_size);
63
64 u32 at91sam7_get_flash_status(flash_bank_t *bank, u8 flashplane);
65 void at91sam7_set_flash_mode(flash_bank_t *bank, u8 flashplane, int mode);
66 u32 at91sam7_wait_status_busy(flash_bank_t *bank, u8 flashplane, u32 waitbits, int timeout);
67 int at91sam7_flash_command(struct flash_bank_s *bank, u8 flashplane, u8 cmd, u16 pagen);
68 int at91sam7_handle_gpnvm_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
69
70 flash_driver_t at91sam7_flash =
71 {
72 .name = "at91sam7",
73 .register_commands = at91sam7_register_commands,
74 .flash_bank_command = at91sam7_flash_bank_command,
75 .erase = at91sam7_erase,
76 .protect = at91sam7_protect,
77 .write = at91sam7_write,
78 .probe = at91sam7_probe,
79 .erase_check = at91sam7_erase_check,
80 .protect_check = at91sam7_protect_check,
81 .info = at91sam7_info
82 };
83
84 u32 MC_FMR[4] = { 0xFFFFFF60, 0xFFFFFF70, 0xFFFFFF80, 0xFFFFFF90 };
85 u32 MC_FCR[4] = { 0xFFFFFF64, 0xFFFFFF74, 0xFFFFFF84, 0xFFFFFF94 };
86 u32 MC_FSR[4] = { 0xFFFFFF68, 0xFFFFFF78, 0xFFFFFF88, 0xFFFFFF98 };
87
88 char * EPROC[8]= {"Unknown","ARM946-E","ARM7TDMI","Unknown","ARM920T","ARM926EJ-S","Unknown","Unknown"};
89 long NVPSIZ[16] = {
90 0,
91 0x2000, /* 8K */
92 0x4000, /* 16K */
93 0x8000, /* 32K */
94 -1,
95 0x10000, /* 64K */
96 -1,
97 0x20000, /* 128K */
98 -1,
99 0x40000, /* 256K */
100 0x80000, /* 512K */
101 -1,
102 0x100000, /* 1024K */
103 -1,
104 0x200000, /* 2048K */
105 -1
106 };
107
108 long SRAMSIZ[16] = {
109 -1,
110 0x0400, /* 1K */
111 0x0800, /* 2K */
112 -1,
113 0x1c000, /* 112K */
114 0x1000, /* 4K */
115 0x14000, /* 80K */
116 0x28000, /* 160K */
117 0x2000, /* 8K */
118 0x4000, /* 16K */
119 0x8000, /* 32K */
120 0x10000, /* 64K */
121 0x20000, /* 128K */
122 0x40000, /* 256K */
123 0x18000, /* 96K */
124 0x80000, /* 512K */
125 };
126
127 int at91sam7_register_commands(struct command_context_s *cmd_ctx)
128 {
129 command_t *at91sam7_cmd = register_command(cmd_ctx, NULL, "at91sam7", NULL, COMMAND_ANY, NULL);
130 register_command(cmd_ctx, at91sam7_cmd, "gpnvm", at91sam7_handle_gpnvm_command, COMMAND_EXEC,
131 "at91sam7 gpnvm <num> <bit> set|clear, set or clear at91sam7 gpnvm bit");
132
133 return ERROR_OK;
134 }
135
136 u32 at91sam7_get_flash_status(flash_bank_t *bank, u8 flashplane)
137 {
138 target_t *target = bank->target;
139 u32 fsr;
140
141 target_read_u32(target, MC_FSR[flashplane], &fsr);
142
143 return fsr;
144 }
145
146 /** Read clock configuration and set at91sam7_info->usec_clocks*/
147 void at91sam7_read_clock_info(flash_bank_t *bank)
148 {
149 at91sam7_flash_bank_t *at91sam7_info = bank->driver_priv;
150 target_t *target = bank->target;
151 u32 mckr, mcfr, pllr;
152 unsigned long tmp = 0, mainfreq;
153 int flashplane;
154
155 /* Read main clock freqency register */
156 target_read_u32(target, CKGR_MCFR, &mcfr);
157 /* Read master clock register */
158 target_read_u32(target, PMC_MCKR, &mckr);
159 /* Read Clock Generator PLL Register */
160 target_read_u32(target, CKGR_PLLR, &pllr);
161
162 at91sam7_info->mck_valid = 0;
163 switch (mckr & PMC_MCKR_CSS)
164 {
165 case 0: /* Slow Clock */
166 at91sam7_info->mck_valid = 1;
167 mainfreq = RC_FREQ / 16ul * (mcfr & 0xffff);
168 tmp = mainfreq;
169 break;
170 case 1: /* Main Clock */
171 if (mcfr & CKGR_MCFR_MAINRDY)
172 {
173 at91sam7_info->mck_valid = 1;
174 mainfreq = RC_FREQ / 16ul * (mcfr & 0xffff);
175 tmp = mainfreq;
176 }
177 break;
178
179 case 2: /* Reserved */
180 break;
181 case 3: /* PLL Clock */
182 if (mcfr & CKGR_MCFR_MAINRDY)
183 {
184 target_read_u32(target, CKGR_PLLR, &pllr);
185 if (!(pllr & CKGR_PLLR_DIV))
186 break; /* 0 Hz */
187 at91sam7_info->mck_valid = 1;
188 mainfreq = RC_FREQ / 16ul * (mcfr & 0xffff);
189 /* Integer arithmetic should have sufficient precision
190 as long as PLL is properly configured. */
191 tmp = mainfreq / (pllr & CKGR_PLLR_DIV) *
192 (((pllr & CKGR_PLLR_MUL) >> 16) + 1);
193 }
194 break;
195 }
196
197 /* Prescaler adjust */
198 if (((mckr & PMC_MCKR_PRES) >> 2) == 7)
199 at91sam7_info->mck_valid = 0;
200 else
201 at91sam7_info->mck_freq = tmp >> ((mckr & PMC_MCKR_PRES) >> 2);
202
203 /* Forget old flash timing */
204 for (flashplane = 0; flashplane<at91sam7_info->num_planes; flashplane++)
205 {
206 at91sam7_set_flash_mode(bank, flashplane, FMR_TIMING_NONE);
207 }
208 }
209
210 /* Setup the timimg registers for nvbits or normal flash */
211 void at91sam7_set_flash_mode(flash_bank_t *bank, u8 flashplane, int mode)
212 {
213 u32 fmr, fmcn = 0, fws = 0;
214 at91sam7_flash_bank_t *at91sam7_info = bank->driver_priv;
215 target_t *target = bank->target;
216
217 if (mode && (mode != at91sam7_info->flashmode[flashplane]))
218 {
219 /* Always round up (ceil) */
220 if (mode==FMR_TIMING_NVBITS)
221 {
222 if (at91sam7_info->cidr_arch == 0x60)
223 {
224 /* AT91SAM7A3 uses master clocks in 100 ns */
225 fmcn = (at91sam7_info->mck_freq/10000000ul)+1;
226 }
227 else
228 {
229 /* master clocks in 1uS for ARCH 0x7 types */
230 fmcn = (at91sam7_info->mck_freq/1000000ul)+1;
231 }
232 }
233 else if (mode==FMR_TIMING_FLASH)
234 /* main clocks in 1.5uS */
235 fmcn = (at91sam7_info->mck_freq/666666ul)+1;
236
237 /* Only allow fmcn=0 if clock period is > 30 us = 33kHz. */
238 if (at91sam7_info->mck_freq <= 33333ul)
239 fmcn = 0;
240 /* Only allow fws=0 if clock frequency is < 30 MHz. */
241 if (at91sam7_info->mck_freq > 30000000ul)
242 fws = 1;
243
244 DEBUG("fmcn[%i]: %i", flashplane, fmcn);
245 fmr = fmcn << 16 | fws << 8;
246 target_write_u32(target, MC_FMR[flashplane], fmr);
247 }
248
249 at91sam7_info->flashmode[flashplane] = mode;
250 }
251
252 u32 at91sam7_wait_status_busy(flash_bank_t *bank, u8 flashplane, u32 waitbits, int timeout)
253 {
254 u32 status;
255
256 while ((!((status = at91sam7_get_flash_status(bank,flashplane)) & waitbits)) && (timeout-- > 0))
257 {
258 DEBUG("status[%i]: 0x%x", flashplane, status);
259 usleep(1000);
260 }
261
262 DEBUG("status[%i]: 0x%x", flashplane, status);
263
264 if (status & 0x0C)
265 {
266 ERROR("status register: 0x%x", status);
267 if (status & 0x4)
268 ERROR("Lock Error Bit Detected, Operation Abort");
269 if (status & 0x8)
270 ERROR("Invalid command and/or bad keyword, Operation Abort");
271 if (status & 0x10)
272 ERROR("Security Bit Set, Operation Abort");
273 }
274
275 return status;
276 }
277
278
279 /* Send one command to the AT91SAM flash controller */
280 int at91sam7_flash_command(struct flash_bank_s *bank, u8 flashplane, u8 cmd, u16 pagen)
281 {
282 u32 fcr;
283 at91sam7_flash_bank_t *at91sam7_info = bank->driver_priv;
284 target_t *target = bank->target;
285
286 fcr = (0x5A<<24) | ((pagen&0x3FF)<<8) | cmd;
287 target_write_u32(target, MC_FCR[flashplane], fcr);
288 DEBUG("Flash command: 0x%x, flashplane: %i, pagenumber:%u", fcr, flashplane, pagen);
289
290 if ((at91sam7_info->cidr_arch == 0x60)&&((cmd==SLB)|(cmd==CLB)))
291 {
292 /* Lock bit manipulation on AT91SAM7A3 waits for FC_FSR bit 1, EOL */
293 if (at91sam7_wait_status_busy(bank, flashplane, MC_FSR_EOL, 10)&0x0C)
294 {
295 return ERROR_FLASH_OPERATION_FAILED;
296 }
297 return ERROR_OK;
298 }
299
300 if (at91sam7_wait_status_busy(bank, flashplane, MC_FSR_FRDY, 10)&0x0C)
301 {
302 return ERROR_FLASH_OPERATION_FAILED;
303 }
304 return ERROR_OK;
305 }
306
307 /* Read device id register, main clock frequency register and fill in driver info structure */
308 int at91sam7_read_part_info(struct flash_bank_s *bank)
309 {
310 at91sam7_flash_bank_t *at91sam7_info = bank->driver_priv;
311 target_t *target = bank->target;
312 u32 cidr, status;
313 int sectornum;
314
315 if (bank->target->state != TARGET_HALTED)
316 {
317 return ERROR_TARGET_NOT_HALTED;
318 }
319
320 /* Read and parse chip identification register */
321 target_read_u32(target, DBGU_CIDR, &cidr);
322
323 if (cidr == 0)
324 {
325 WARNING("Cannot identify target as an AT91SAM");
326 return ERROR_FLASH_OPERATION_FAILED;
327 }
328
329 at91sam7_info->cidr = cidr;
330 at91sam7_info->cidr_ext = (cidr>>31)&0x0001;
331 at91sam7_info->cidr_nvptyp = (cidr>>28)&0x0007;
332 at91sam7_info->cidr_arch = (cidr>>20)&0x00FF;
333 at91sam7_info->cidr_sramsiz = (cidr>>16)&0x000F;
334 at91sam7_info->cidr_nvpsiz2 = (cidr>>12)&0x000F;
335 at91sam7_info->cidr_nvpsiz = (cidr>>8)&0x000F;
336 at91sam7_info->cidr_eproc = (cidr>>5)&0x0007;
337 at91sam7_info->cidr_version = cidr&0x001F;
338 bank->size = NVPSIZ[at91sam7_info->cidr_nvpsiz];
339 at91sam7_info->target_name = "Unknown";
340
341 /* Support just for bulk erase of a single flash plane, whole device if flash size <= 256k */
342 if (NVPSIZ[at91sam7_info->cidr_nvpsiz]<0x80000) /* Flash size less than 512K, one flash plane */
343 {
344 bank->num_sectors = 1;
345 bank->sectors = malloc(sizeof(flash_sector_t));
346 bank->sectors[0].offset = 0;
347 bank->sectors[0].size = bank->size;
348 bank->sectors[0].is_erased = -1;
349 bank->sectors[0].is_protected = -1;
350 }
351 else /* Flash size 512K or larger, several flash planes */
352 {
353 bank->num_sectors = NVPSIZ[at91sam7_info->cidr_nvpsiz]/0x40000;
354 bank->sectors = malloc(bank->num_sectors*sizeof(flash_sector_t));
355 for (sectornum=0; sectornum<bank->num_sectors; sectornum++)
356 {
357 bank->sectors[sectornum].offset = sectornum*0x40000;
358 bank->sectors[sectornum].size = 0x40000;
359 bank->sectors[sectornum].is_erased = -1;
360 bank->sectors[sectornum].is_protected = -1;
361 }
362 }
363
364
365
366 DEBUG("nvptyp: 0x%3.3x, arch: 0x%4.4x", at91sam7_info->cidr_nvptyp, at91sam7_info->cidr_arch );
367
368 /* Read main and master clock freqency register */
369 at91sam7_read_clock_info(bank);
370
371 at91sam7_info->num_planes = 1;
372 status = at91sam7_get_flash_status(bank, 0);
373 at91sam7_info->securitybit = (status>>4)&0x01;
374 at91sam7_protect_check(bank); /* TODO Check the protect check */
375
376 if (at91sam7_info->cidr_arch == 0x70 )
377 {
378 at91sam7_info->num_nvmbits = 2;
379 at91sam7_info->nvmbits = (status>>8)&0x03;
380 bank->base = 0x100000;
381 bank->bus_width = 4;
382 if (bank->size==0x80000) /* AT91SAM7S512 */
383 {
384 at91sam7_info->target_name = "AT91SAM7S512";
385 at91sam7_info->num_planes = 2;
386 if (at91sam7_info->num_planes != bank->num_sectors)
387 WARNING("Internal error: Number of flash planes and erase sectors does not match, please report");;
388 at91sam7_info->num_lockbits = 2*16;
389 at91sam7_info->pagesize = 256;
390 at91sam7_info->pages_in_lockregion = 64;
391 at91sam7_info->num_pages = 2*16*64;
392 }
393 if (bank->size==0x40000) /* AT91SAM7S256 */
394 {
395 at91sam7_info->target_name = "AT91SAM7S256";
396 at91sam7_info->num_lockbits = 16;
397 at91sam7_info->pagesize = 256;
398 at91sam7_info->pages_in_lockregion = 64;
399 at91sam7_info->num_pages = 16*64;
400 }
401 if (bank->size==0x20000) /* AT91SAM7S128 */
402 {
403 at91sam7_info->target_name = "AT91SAM7S128";
404 at91sam7_info->num_lockbits = 8;
405 at91sam7_info->pagesize = 256;
406 at91sam7_info->pages_in_lockregion = 64;
407 at91sam7_info->num_pages = 8*64;
408 }
409 if (bank->size==0x10000) /* AT91SAM7S64 */
410 {
411 at91sam7_info->target_name = "AT91SAM7S64";
412 at91sam7_info->num_lockbits = 16;
413 at91sam7_info->pagesize = 128;
414 at91sam7_info->pages_in_lockregion = 32;
415 at91sam7_info->num_pages = 16*32;
416 }
417 if (bank->size==0x08000) /* AT91SAM7S321/32 */
418 {
419 at91sam7_info->target_name = "AT91SAM7S321/32";
420 at91sam7_info->num_lockbits = 8;
421 at91sam7_info->pagesize = 128;
422 at91sam7_info->pages_in_lockregion = 32;
423 at91sam7_info->num_pages = 8*32;
424 }
425
426 return ERROR_OK;
427 }
428
429 if (at91sam7_info->cidr_arch == 0x71 )
430 {
431 at91sam7_info->num_nvmbits = 3;
432 at91sam7_info->nvmbits = (status>>8)&0x07;
433 bank->base = 0x100000;
434 bank->bus_width = 4;
435 if (bank->size==0x80000) /* AT91SAM7XC512 */
436 {
437 at91sam7_info->target_name = "AT91SAM7XC512";
438 at91sam7_info->num_planes = 2;
439 if (at91sam7_info->num_planes != bank->num_sectors)
440 WARNING("Internal error: Number of flash planes and erase sectors does not match, please report");;
441 at91sam7_info->num_lockbits = 2*16;
442 at91sam7_info->pagesize = 256;
443 at91sam7_info->pages_in_lockregion = 64;
444 at91sam7_info->num_pages = 2*16*64;
445 }
446 if (bank->size==0x40000) /* AT91SAM7XC256 */
447 {
448 at91sam7_info->target_name = "AT91SAM7XC256";
449 at91sam7_info->num_lockbits = 16;
450 at91sam7_info->pagesize = 256;
451 at91sam7_info->pages_in_lockregion = 64;
452 at91sam7_info->num_pages = 16*64;
453 }
454 if (bank->size==0x20000) /* AT91SAM7XC128 */
455 {
456 at91sam7_info->target_name = "AT91SAM7XC128";
457 at91sam7_info->num_lockbits = 8;
458 at91sam7_info->pagesize = 256;
459 at91sam7_info->pages_in_lockregion = 64;
460 at91sam7_info->num_pages = 8*64;
461 }
462
463 return ERROR_OK;
464 }
465
466 if (at91sam7_info->cidr_arch == 0x72 )
467 {
468 at91sam7_info->num_nvmbits = 2;
469 at91sam7_info->nvmbits = (status>>8)&0x03;
470 bank->base = 0x100000;
471 bank->bus_width = 4;
472 if (bank->size==0x80000) /* AT91SAM7SE512 */
473 {
474 at91sam7_info->target_name = "AT91SAM7SE512";
475 at91sam7_info->num_planes = 2;
476 if (at91sam7_info->num_planes != bank->num_sectors)
477 WARNING("Internal error: Number of flash planes and erase sectors does not match, please report");;
478 at91sam7_info->num_lockbits = 32;
479 at91sam7_info->pagesize = 256;
480 at91sam7_info->pages_in_lockregion = 64;
481 at91sam7_info->num_pages = 32*64;
482 }
483 if (bank->size==0x40000)
484 {
485 at91sam7_info->target_name = "AT91SAM7SE256";
486 at91sam7_info->num_lockbits = 16;
487 at91sam7_info->pagesize = 256;
488 at91sam7_info->pages_in_lockregion = 64;
489 at91sam7_info->num_pages = 16*64;
490 }
491 if (bank->size==0x08000)
492 {
493 at91sam7_info->target_name = "AT91SAM7SE32";
494 at91sam7_info->num_lockbits = 8;
495 at91sam7_info->pagesize = 128;
496 at91sam7_info->pages_in_lockregion = 32;
497 at91sam7_info->num_pages = 8*32;
498 }
499
500 return ERROR_OK;
501 }
502
503 if (at91sam7_info->cidr_arch == 0x75 )
504 {
505 at91sam7_info->num_nvmbits = 3;
506 at91sam7_info->nvmbits = (status>>8)&0x07;
507 bank->base = 0x100000;
508 bank->bus_width = 4;
509 if (bank->size==0x80000) /* AT91SAM7X512 */
510 {
511 at91sam7_info->target_name = "AT91SAM7X512";
512 at91sam7_info->num_planes = 2;
513 if (at91sam7_info->num_planes != bank->num_sectors)
514 WARNING("Internal error: Number of flash planes and erase sectors does not match, please report");;
515 at91sam7_info->num_lockbits = 32;
516 at91sam7_info->pagesize = 256;
517 at91sam7_info->pages_in_lockregion = 64;
518 at91sam7_info->num_pages = 2*16*64;
519 DEBUG("Support for AT91SAM7X512 is experimental in this version!");
520 }
521 if (bank->size==0x40000) /* AT91SAM7X256 */
522 {
523 at91sam7_info->target_name = "AT91SAM7X256";
524 at91sam7_info->num_lockbits = 16;
525 at91sam7_info->pagesize = 256;
526 at91sam7_info->pages_in_lockregion = 64;
527 at91sam7_info->num_pages = 16*64;
528 }
529 if (bank->size==0x20000) /* AT91SAM7X128 */
530 {
531 at91sam7_info->target_name = "AT91SAM7X128";
532 at91sam7_info->num_lockbits = 8;
533 at91sam7_info->pagesize = 256;
534 at91sam7_info->pages_in_lockregion = 64;
535 at91sam7_info->num_pages = 8*64;
536 }
537
538 return ERROR_OK;
539 }
540
541 if (at91sam7_info->cidr_arch == 0x60 )
542 {
543 at91sam7_info->num_nvmbits = 3;
544 at91sam7_info->nvmbits = (status>>8)&0x07;
545 bank->base = 0x100000;
546 bank->bus_width = 4;
547
548 if (bank->size == 0x40000) /* AT91SAM7A3 */
549 {
550 at91sam7_info->target_name = "AT91SAM7A3";
551 at91sam7_info->num_lockbits = 16;
552 at91sam7_info->pagesize = 256;
553 at91sam7_info->pages_in_lockregion = 16;
554 at91sam7_info->num_pages = 16*64;
555 }
556 return ERROR_OK;
557 }
558
559 WARNING("at91sam7 flash only tested for AT91SAM7Sxx series");
560
561 return ERROR_OK;
562 }
563
564 int at91sam7_erase_check(struct flash_bank_s *bank)
565 {
566 at91sam7_flash_bank_t *at91sam7_info = bank->driver_priv;
567
568 if (!at91sam7_info->working_area_size)
569 {
570 }
571 else
572 {
573 }
574
575 return ERROR_OK;
576 }
577
578 int at91sam7_protect_check(struct flash_bank_s *bank)
579 {
580 u32 status;
581 int flashplane;
582
583 at91sam7_flash_bank_t *at91sam7_info = bank->driver_priv;
584
585 if (at91sam7_info->cidr == 0)
586 {
587 at91sam7_read_part_info(bank);
588 }
589
590 if (at91sam7_info->cidr == 0)
591 {
592 WARNING("Cannot identify target as an AT91SAM");
593 return ERROR_FLASH_OPERATION_FAILED;
594 }
595
596 for (flashplane=0;flashplane<at91sam7_info->num_planes;flashplane++)
597 {
598 status = at91sam7_get_flash_status(bank, flashplane);
599 at91sam7_info->lockbits[flashplane] = (status >> 16);
600 }
601
602 return ERROR_OK;
603 }
604
605 /* flash_bank at91sam7 0 0 0 0 <target#>
606 */
607 int at91sam7_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank)
608 {
609 at91sam7_flash_bank_t *at91sam7_info;
610 int i;
611
612 if (argc < 6)
613 {
614 WARNING("incomplete flash_bank at91sam7 configuration");
615 return ERROR_FLASH_BANK_INVALID;
616 }
617
618 at91sam7_info = malloc(sizeof(at91sam7_flash_bank_t));
619 bank->driver_priv = at91sam7_info;
620
621 /* part wasn't probed for info yet */
622 at91sam7_info->cidr = 0;
623 for (i=0;i<4;i++)
624 at91sam7_info->flashmode[i]=0;
625
626 return ERROR_OK;
627 }
628
629 int at91sam7_erase(struct flash_bank_s *bank, int first, int last)
630 {
631 at91sam7_flash_bank_t *at91sam7_info = bank->driver_priv;
632 u8 flashplane;
633
634 if (bank->target->state != TARGET_HALTED)
635 {
636 return ERROR_TARGET_NOT_HALTED;
637 }
638
639 if (at91sam7_info->cidr == 0)
640 {
641 at91sam7_read_part_info(bank);
642 }
643
644 if (at91sam7_info->cidr == 0)
645 {
646 WARNING("Cannot identify target as an AT91SAM");
647 return ERROR_FLASH_OPERATION_FAILED;
648 }
649
650 if ((first < 0) || (last < first) || (last >= bank->num_sectors))
651 {
652 if ((first == 0) && (last == (at91sam7_info->num_lockbits-1)))
653 {
654 WARNING("Sector numbers based on lockbit count, probably a deprecated script");
655 last = bank->num_sectors-1;
656 }
657 else return ERROR_FLASH_SECTOR_INVALID;
658 }
659
660 /* Configure the flash controller timing */
661 at91sam7_read_clock_info(bank);
662 for (flashplane = first; flashplane<=last; flashplane++)
663 {
664 /* Configure the flash controller timing */
665 at91sam7_set_flash_mode(bank, flashplane, FMR_TIMING_FLASH);
666 if (at91sam7_flash_command(bank, flashplane, EA, 0) != ERROR_OK)
667 {
668 return ERROR_FLASH_OPERATION_FAILED;
669 }
670 }
671 return ERROR_OK;
672
673 }
674
675 int at91sam7_protect(struct flash_bank_s *bank, int set, int first, int last)
676 {
677 u32 cmd, pagen;
678 u8 flashplane;
679 int lockregion;
680
681 at91sam7_flash_bank_t *at91sam7_info = bank->driver_priv;
682
683 if (bank->target->state != TARGET_HALTED)
684 {
685 return ERROR_TARGET_NOT_HALTED;
686 }
687
688 if ((first < 0) || (last < first) || (last >= at91sam7_info->num_lockbits))
689 {
690 return ERROR_FLASH_SECTOR_INVALID;
691 }
692
693 if (at91sam7_info->cidr == 0)
694 {
695 at91sam7_read_part_info(bank);
696 }
697
698 if (at91sam7_info->cidr == 0)
699 {
700 WARNING("Cannot identify target as an AT91SAM");
701 return ERROR_FLASH_OPERATION_FAILED;
702 }
703
704 at91sam7_read_clock_info(bank);
705
706 for (lockregion=first;lockregion<=last;lockregion++)
707 {
708 pagen = lockregion*at91sam7_info->pages_in_lockregion;
709 flashplane = (pagen>>10)&0x03;
710 /* Configure the flash controller timing */
711 at91sam7_set_flash_mode(bank, flashplane, FMR_TIMING_NVBITS);
712
713 if (set)
714 cmd = SLB;
715 else
716 cmd = CLB;
717
718 if (at91sam7_flash_command(bank, flashplane, cmd, pagen) != ERROR_OK)
719 {
720 return ERROR_FLASH_OPERATION_FAILED;
721 }
722 }
723
724 at91sam7_protect_check(bank);
725
726 return ERROR_OK;
727 }
728
729
730 int at91sam7_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count)
731 {
732 at91sam7_flash_bank_t *at91sam7_info = bank->driver_priv;
733 target_t *target = bank->target;
734 u32 dst_min_alignment, wcount, bytes_remaining = count;
735 u32 first_page, last_page, pagen, buffer_pos;
736 u8 flashplane;
737
738 if (bank->target->state != TARGET_HALTED)
739 {
740 return ERROR_TARGET_NOT_HALTED;
741 }
742
743 if (at91sam7_info->cidr == 0)
744 {
745 at91sam7_read_part_info(bank);
746 }
747
748 if (at91sam7_info->cidr == 0)
749 {
750 WARNING("Cannot identify target as an AT91SAM");
751 return ERROR_FLASH_OPERATION_FAILED;
752 }
753
754 if (offset + count > bank->size)
755 return ERROR_FLASH_DST_OUT_OF_BANK;
756
757 dst_min_alignment = at91sam7_info->pagesize;
758
759 if (offset % dst_min_alignment)
760 {
761 WARNING("offset 0x%x breaks required alignment 0x%x", offset, dst_min_alignment);
762 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
763 }
764
765 if (at91sam7_info->cidr_arch == 0)
766 return ERROR_FLASH_BANK_NOT_PROBED;
767
768 first_page = offset/dst_min_alignment;
769 last_page = CEIL(offset + count, dst_min_alignment);
770
771 DEBUG("first_page: %i, last_page: %i, count %i", first_page, last_page, count);
772
773 at91sam7_read_clock_info(bank);
774
775 for (pagen=first_page; pagen<last_page; pagen++)
776 {
777 if (bytes_remaining<dst_min_alignment)
778 count = bytes_remaining;
779 else
780 count = dst_min_alignment;
781 bytes_remaining -= count;
782
783 /* Write one block to the PageWriteBuffer */
784 buffer_pos = (pagen-first_page)*dst_min_alignment;
785 wcount = CEIL(count,4);
786 target->type->write_memory(target, bank->base+pagen*dst_min_alignment, 4, wcount, buffer+buffer_pos);
787 flashplane = (pagen>>10)&0x3;
788
789 /* Configure the flash controller timing */
790 at91sam7_set_flash_mode(bank, flashplane, FMR_TIMING_FLASH);
791 /* Send Write Page command to Flash Controller */
792 if (at91sam7_flash_command(bank, flashplane, WP, pagen) != ERROR_OK)
793 {
794 return ERROR_FLASH_OPERATION_FAILED;
795 }
796 DEBUG("Write flash plane:%i page number:%i", flashplane, pagen);
797 }
798
799 return ERROR_OK;
800 }
801
802
803 int at91sam7_probe(struct flash_bank_s *bank)
804 {
805 /* we can't probe on an at91sam7
806 * if this is an at91sam7, it has the configured flash
807 */
808 at91sam7_flash_bank_t *at91sam7_info = bank->driver_priv;
809
810 if (at91sam7_info->cidr == 0)
811 {
812 at91sam7_read_part_info(bank);
813 }
814
815 if (at91sam7_info->cidr == 0)
816 {
817 WARNING("Cannot identify target as an AT91SAM");
818 return ERROR_FLASH_OPERATION_FAILED;
819 }
820
821 return ERROR_OK;
822 }
823
824 int at91sam7_info(struct flash_bank_s *bank, char *buf, int buf_size)
825 {
826 int printed, flashplane;
827 at91sam7_flash_bank_t *at91sam7_info = bank->driver_priv;
828
829 at91sam7_read_part_info(bank);
830
831 if (at91sam7_info->cidr == 0)
832 {
833 printed = snprintf(buf, buf_size, "Cannot identify target as an AT91SAM\n");
834 buf += printed;
835 buf_size -= printed;
836 return ERROR_FLASH_OPERATION_FAILED;
837 }
838
839 printed = snprintf(buf, buf_size, "\nat91sam7 information: Chip is %s\n",at91sam7_info->target_name);
840 buf += printed;
841 buf_size -= printed;
842
843 printed = snprintf(buf, buf_size, "cidr: 0x%8.8x, arch: 0x%4.4x, eproc: %s, version:0x%3.3x, flashsize: 0x%8.8x\n",
844 at91sam7_info->cidr, at91sam7_info->cidr_arch, EPROC[at91sam7_info->cidr_eproc], at91sam7_info->cidr_version, bank->size);
845 buf += printed;
846 buf_size -= printed;
847
848 printed = snprintf(buf, buf_size, "master clock(estimated): %ikHz \n", at91sam7_info->mck_freq / 1000);
849 buf += printed;
850 buf_size -= printed;
851
852 if (at91sam7_info->num_planes>1) {
853 printed = snprintf(buf, buf_size, "flashplanes: %i, pagesize: %i, lock regions: %i, pages in lock region: %i \n",
854 at91sam7_info->num_planes, at91sam7_info->pagesize, at91sam7_info->num_lockbits, at91sam7_info->num_pages/at91sam7_info->num_lockbits);
855 buf += printed;
856 buf_size -= printed;
857 for (flashplane=0; flashplane<at91sam7_info->num_planes; flashplane++)
858 {
859 printed = snprintf(buf, buf_size, "lockbits[%i]: 0x%4.4x, ", flashplane, at91sam7_info->lockbits[flashplane]);
860 buf += printed;
861 buf_size -= printed;
862 }
863 }
864 else
865 if (at91sam7_info->num_lockbits>0) {
866 printed = snprintf(buf, buf_size, "pagesize: %i, lockbits: %i 0x%4.4x, pages in lock region: %i \n",
867 at91sam7_info->pagesize, at91sam7_info->num_lockbits, at91sam7_info->lockbits[0], at91sam7_info->num_pages/at91sam7_info->num_lockbits);
868 buf += printed;
869 buf_size -= printed;
870 }
871
872 printed = snprintf(buf, buf_size, "securitybit: %i, nvmbits: 0x%1.1x\n", at91sam7_info->securitybit, at91sam7_info->nvmbits);
873 buf += printed;
874 buf_size -= printed;
875
876 return ERROR_OK;
877 }
878
879 /*
880 * On AT91SAM7S: When the gpnmv bits are set with
881 * > at91sam7 gpnvm 0 bitnr set
882 * the changes are not visible in the flash controller status register MC_FSR
883 * until the processor has been reset.
884 * On the Olimex board this requires a power cycle.
885 * Note that the AT91SAM7S has the following errata (doc6175.pdf sec 14.1.3):
886 * The maximum number of write/erase cycles for Non Volatile Memory bits is 100. This includes
887 * Lock Bits (LOCKx), General Purpose NVM bits (GPNVMx) and the Security Bit.
888 */
889 int at91sam7_handle_gpnvm_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
890 {
891 flash_bank_t *bank;
892 int bit;
893 u8 flashcmd;
894 u32 status;
895 char *value;
896 at91sam7_flash_bank_t *at91sam7_info;
897
898 if (argc < 3)
899 {
900 command_print(cmd_ctx, "at91sam7 gpnvm <num> <bit> <set|clear>");
901 return ERROR_OK;
902 }
903
904 bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));
905 bit = atoi(args[1]);
906 value = args[2];
907
908 if (!bank)
909 {
910 command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);
911 return ERROR_OK;
912 }
913
914 at91sam7_info = bank->driver_priv;
915
916 if (bank->target->state != TARGET_HALTED)
917 {
918 return ERROR_TARGET_NOT_HALTED;
919 }
920
921 if (at91sam7_info->cidr == 0)
922 {
923 at91sam7_read_part_info(bank);
924 }
925
926 if (at91sam7_info->cidr == 0)
927 {
928 WARNING("Cannot identify target as an AT91SAM");
929 return ERROR_FLASH_OPERATION_FAILED;
930 }
931
932 if ((bit<0) || (at91sam7_info->num_nvmbits <= bit))
933 {
934 command_print(cmd_ctx, "gpnvm bit '#%s' is out of bounds for target %s", args[1],at91sam7_info->target_name);
935 return ERROR_OK;
936 }
937
938 if (strcmp(value, "set") == 0)
939 {
940 flashcmd = SGPB;
941 }
942 else if (strcmp(value, "clear") == 0)
943 {
944 flashcmd = CGPB;
945 }
946 else
947 {
948 command_print(cmd_ctx, "usage: at91sam7 gpnvm <num> <bit> <set|clear>");
949 return ERROR_OK;
950 }
951
952 /* Configure the flash controller timing */
953 at91sam7_read_clock_info(bank);
954 at91sam7_set_flash_mode(bank, 0, FMR_TIMING_NVBITS);
955
956 if (at91sam7_flash_command(bank, 0, flashcmd, (u16)(bit)) != ERROR_OK)
957 {
958 return ERROR_FLASH_OPERATION_FAILED;
959 }
960
961 status = at91sam7_get_flash_status(bank, 0);
962 DEBUG("at91sam7_handle_gpnvm_command: cmd 0x%x, value 0x%x, status 0x%x \n",flashcmd,bit,status);
963 at91sam7_info->nvmbits = (status>>8)&((1<<at91sam7_info->num_nvmbits)-1);
964
965 return ERROR_OK;
966 }

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)