NOR: cleanup driver decls
[openocd.git] / src / flash / nor / str9x.c
1 /***************************************************************************
2 * Copyright (C) 2005 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
4 * *
5 * Copyright (C) 2008 by Spencer Oliver *
6 * spen@spen-soft.co.uk *
7 *
8 * Copyright (C) 2008 by Oyvind Harboe *
9 * oyvind.harboe@zylin.com *
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 * This program is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
19 * GNU General Public License for more details. *
20 * *
21 * You should have received a copy of the GNU General Public License *
22 * along with this program; if not, write to the *
23 * Free Software Foundation, Inc., *
24 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
25 ***************************************************************************/
26 #ifdef HAVE_CONFIG_H
27 #include "config.h"
28 #endif
29
30 #include "imp.h"
31 #include "str9x.h"
32 #include <target/arm966e.h>
33 #include <target/algorithm.h>
34
35
36 static uint32_t bank1start = 0x00080000;
37
38 static int str9x_build_block_list(struct flash_bank *bank)
39 {
40 struct str9x_flash_bank *str9x_info = bank->driver_priv;
41
42 int i;
43 int num_sectors;
44 int b0_sectors = 0, b1_sectors = 0;
45 uint32_t offset = 0;
46
47 /* set if we have large flash str9 */
48 str9x_info->variant = 0;
49 str9x_info->bank1 = 0;
50
51 switch (bank->size)
52 {
53 case (256 * 1024):
54 b0_sectors = 4;
55 break;
56 case (512 * 1024):
57 b0_sectors = 8;
58 break;
59 case (1024 * 1024):
60 bank1start = 0x00100000;
61 str9x_info->variant = 1;
62 b0_sectors = 16;
63 break;
64 case (2048 * 1024):
65 bank1start = 0x00200000;
66 str9x_info->variant = 1;
67 b0_sectors = 32;
68 break;
69 case (128 * 1024):
70 str9x_info->variant = 1;
71 str9x_info->bank1 = 1;
72 b1_sectors = 8;
73 bank1start = bank->base;
74 break;
75 case (32 * 1024):
76 str9x_info->bank1 = 1;
77 b1_sectors = 4;
78 bank1start = bank->base;
79 break;
80 default:
81 LOG_ERROR("BUG: unknown bank->size encountered");
82 exit(-1);
83 }
84
85 num_sectors = b0_sectors + b1_sectors;
86
87 bank->num_sectors = num_sectors;
88 bank->sectors = malloc(sizeof(struct flash_sector) * num_sectors);
89 str9x_info->sector_bits = malloc(sizeof(uint32_t) * num_sectors);
90
91 num_sectors = 0;
92
93 for (i = 0; i < b0_sectors; i++)
94 {
95 bank->sectors[num_sectors].offset = offset;
96 bank->sectors[num_sectors].size = 0x10000;
97 offset += bank->sectors[i].size;
98 bank->sectors[num_sectors].is_erased = -1;
99 bank->sectors[num_sectors].is_protected = 1;
100 str9x_info->sector_bits[num_sectors++] = (1 << i);
101 }
102
103 for (i = 0; i < b1_sectors; i++)
104 {
105 bank->sectors[num_sectors].offset = offset;
106 bank->sectors[num_sectors].size = str9x_info->variant == 0 ? 0x2000 : 0x4000;
107 offset += bank->sectors[i].size;
108 bank->sectors[num_sectors].is_erased = -1;
109 bank->sectors[num_sectors].is_protected = 1;
110 if (str9x_info->variant)
111 str9x_info->sector_bits[num_sectors++] = (1 << i);
112 else
113 str9x_info->sector_bits[num_sectors++] = (1 << (i + 8));
114 }
115
116 return ERROR_OK;
117 }
118
119 /* flash bank str9x <base> <size> 0 0 <target#>
120 */
121 FLASH_BANK_COMMAND_HANDLER(str9x_flash_bank_command)
122 {
123 struct str9x_flash_bank *str9x_info;
124
125 if (CMD_ARGC < 6)
126 {
127 LOG_WARNING("incomplete flash_bank str9x configuration");
128 return ERROR_FLASH_BANK_INVALID;
129 }
130
131 str9x_info = malloc(sizeof(struct str9x_flash_bank));
132 bank->driver_priv = str9x_info;
133
134 str9x_build_block_list(bank);
135
136 str9x_info->write_algorithm = NULL;
137
138 return ERROR_OK;
139 }
140
141 static int str9x_protect_check(struct flash_bank *bank)
142 {
143 int retval;
144 struct str9x_flash_bank *str9x_info = bank->driver_priv;
145 struct target *target = bank->target;
146
147 int i;
148 uint32_t adr;
149 uint32_t status = 0;
150 uint16_t hstatus = 0;
151
152 if (bank->target->state != TARGET_HALTED)
153 {
154 LOG_ERROR("Target not halted");
155 return ERROR_TARGET_NOT_HALTED;
156 }
157
158 /* read level one protection */
159
160 if (str9x_info->variant)
161 {
162 if (str9x_info->bank1)
163 {
164 adr = bank1start + 0x18;
165 if ((retval = target_write_u16(target, adr, 0x90)) != ERROR_OK)
166 {
167 return retval;
168 }
169 if ((retval = target_read_u16(target, adr, &hstatus)) != ERROR_OK)
170 {
171 return retval;
172 }
173 status = hstatus;
174 }
175 else
176 {
177 adr = bank1start + 0x14;
178 if ((retval = target_write_u16(target, adr, 0x90)) != ERROR_OK)
179 {
180 return retval;
181 }
182 if ((retval = target_read_u32(target, adr, &status)) != ERROR_OK)
183 {
184 return retval;
185 }
186 }
187 }
188 else
189 {
190 adr = bank1start + 0x10;
191 if ((retval = target_write_u16(target, adr, 0x90)) != ERROR_OK)
192 {
193 return retval;
194 }
195 if ((retval = target_read_u16(target, adr, &hstatus)) != ERROR_OK)
196 {
197 return retval;
198 }
199 status = hstatus;
200 }
201
202 /* read array command */
203 if ((retval = target_write_u16(target, adr, 0xFF)) != ERROR_OK)
204 {
205 return retval;
206 }
207
208 for (i = 0; i < bank->num_sectors; i++)
209 {
210 if (status & str9x_info->sector_bits[i])
211 bank->sectors[i].is_protected = 1;
212 else
213 bank->sectors[i].is_protected = 0;
214 }
215
216 return ERROR_OK;
217 }
218
219 static int str9x_erase(struct flash_bank *bank, int first, int last)
220 {
221 struct target *target = bank->target;
222 int i;
223 uint32_t adr;
224 uint8_t status;
225 uint8_t erase_cmd;
226
227 if (bank->target->state != TARGET_HALTED)
228 {
229 LOG_ERROR("Target not halted");
230 return ERROR_TARGET_NOT_HALTED;
231 }
232
233 /*A slower but stable way of erasing*/
234 /* Erase sector command */
235 erase_cmd = 0x20;
236
237 for (i = first; i <= last; i++)
238 {
239 int retval;
240 adr = bank->base + bank->sectors[i].offset;
241
242 /* erase sectors */
243 if ((retval = target_write_u16(target, adr, erase_cmd)) != ERROR_OK)
244 {
245 return retval;
246 }
247 if ((retval = target_write_u16(target, adr, 0xD0)) != ERROR_OK)
248 {
249 return retval;
250 }
251
252 /* get status */
253 if ((retval = target_write_u16(target, adr, 0x70)) != ERROR_OK)
254 {
255 return retval;
256 }
257
258 int timeout;
259 for (timeout = 0; timeout < 1000; timeout++) {
260 if ((retval = target_read_u8(target, adr, &status)) != ERROR_OK)
261 {
262 return retval;
263 }
264 if (status & 0x80)
265 break;
266 alive_sleep(1);
267 }
268 if (timeout == 1000)
269 {
270 LOG_ERROR("erase timed out");
271 return ERROR_FAIL;
272 }
273
274 /* clear status, also clear read array */
275 if ((retval = target_write_u16(target, adr, 0x50)) != ERROR_OK)
276 {
277 return retval;
278 }
279
280 /* read array command */
281 if ((retval = target_write_u16(target, adr, 0xFF)) != ERROR_OK)
282 {
283 return retval;
284 }
285
286 if (status & 0x22)
287 {
288 LOG_ERROR("error erasing flash bank, status: 0x%x", status);
289 return ERROR_FLASH_OPERATION_FAILED;
290 }
291 }
292
293 for (i = first; i <= last; i++)
294 bank->sectors[i].is_erased = 1;
295
296 return ERROR_OK;
297 }
298
299 static int str9x_protect(struct flash_bank *bank,
300 int set, int first, int last)
301 {
302 struct target *target = bank->target;
303 int i;
304 uint32_t adr;
305 uint8_t status;
306
307 if (bank->target->state != TARGET_HALTED)
308 {
309 LOG_ERROR("Target not halted");
310 return ERROR_TARGET_NOT_HALTED;
311 }
312
313 for (i = first; i <= last; i++)
314 {
315 /* Level One Protection */
316
317 adr = bank->base + bank->sectors[i].offset;
318
319 target_write_u16(target, adr, 0x60);
320 if (set)
321 target_write_u16(target, adr, 0x01);
322 else
323 target_write_u16(target, adr, 0xD0);
324
325 /* query status */
326 target_read_u8(target, adr, &status);
327
328 /* clear status, also clear read array */
329 target_write_u16(target, adr, 0x50);
330
331 /* read array command */
332 target_write_u16(target, adr, 0xFF);
333 }
334
335 return ERROR_OK;
336 }
337
338 static int str9x_write_block(struct flash_bank *bank,
339 uint8_t *buffer, uint32_t offset, uint32_t count)
340 {
341 struct str9x_flash_bank *str9x_info = bank->driver_priv;
342 struct target *target = bank->target;
343 uint32_t buffer_size = 8192;
344 struct working_area *source;
345 uint32_t address = bank->base + offset;
346 struct reg_param reg_params[4];
347 struct arm_algorithm armv4_5_info;
348 int retval = ERROR_OK;
349
350 uint32_t str9x_flash_write_code[] = {
351 /* write: */
352 0xe3c14003, /* bic r4, r1, #3 */
353 0xe3a03040, /* mov r3, #0x40 */
354 0xe1c430b0, /* strh r3, [r4, #0] */
355 0xe0d030b2, /* ldrh r3, [r0], #2 */
356 0xe0c130b2, /* strh r3, [r1], #2 */
357 0xe3a03070, /* mov r3, #0x70 */
358 0xe1c430b0, /* strh r3, [r4, #0] */
359 /* busy: */
360 0xe5d43000, /* ldrb r3, [r4, #0] */
361 0xe3130080, /* tst r3, #0x80 */
362 0x0afffffc, /* beq busy */
363 0xe3a05050, /* mov r5, #0x50 */
364 0xe1c450b0, /* strh r5, [r4, #0] */
365 0xe3a050ff, /* mov r5, #0xFF */
366 0xe1c450b0, /* strh r5, [r4, #0] */
367 0xe3130012, /* tst r3, #0x12 */
368 0x1a000001, /* bne exit */
369 0xe2522001, /* subs r2, r2, #1 */
370 0x1affffed, /* bne write */
371 /* exit: */
372 0xeafffffe, /* b exit */
373 };
374
375 /* flash write code */
376 if (target_alloc_working_area(target, 4 * 19, &str9x_info->write_algorithm) != ERROR_OK)
377 {
378 LOG_WARNING("no working area available, can't do block memory writes");
379 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
380 };
381
382 target_write_buffer(target, str9x_info->write_algorithm->address, 19 * 4, (uint8_t*)str9x_flash_write_code);
383
384 /* memory buffer */
385 while (target_alloc_working_area(target, buffer_size, &source) != ERROR_OK)
386 {
387 buffer_size /= 2;
388 if (buffer_size <= 256)
389 {
390 /* if we already allocated the writing code, but failed to get a buffer, free the algorithm */
391 if (str9x_info->write_algorithm)
392 target_free_working_area(target, str9x_info->write_algorithm);
393
394 LOG_WARNING("no large enough working area available, can't do block memory writes");
395 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
396 }
397 }
398
399 armv4_5_info.common_magic = ARM_COMMON_MAGIC;
400 armv4_5_info.core_mode = ARM_MODE_SVC;
401 armv4_5_info.core_state = ARM_STATE_ARM;
402
403 init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);
404 init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
405 init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT);
406 init_reg_param(&reg_params[3], "r3", 32, PARAM_IN);
407
408 while (count > 0)
409 {
410 uint32_t thisrun_count = (count > (buffer_size / 2)) ? (buffer_size / 2) : count;
411
412 target_write_buffer(target, source->address, thisrun_count * 2, buffer);
413
414 buf_set_u32(reg_params[0].value, 0, 32, source->address);
415 buf_set_u32(reg_params[1].value, 0, 32, address);
416 buf_set_u32(reg_params[2].value, 0, 32, thisrun_count);
417
418 if ((retval = target_run_algorithm(target, 0, NULL, 4, reg_params, str9x_info->write_algorithm->address, str9x_info->write_algorithm->address + (18 * 4), 10000, &armv4_5_info)) != ERROR_OK)
419 {
420 LOG_ERROR("error executing str9x flash write algorithm");
421 retval = ERROR_FLASH_OPERATION_FAILED;
422 break;
423 }
424
425 if (buf_get_u32(reg_params[3].value, 0, 32) != 0x80)
426 {
427 retval = ERROR_FLASH_OPERATION_FAILED;
428 break;
429 }
430
431 buffer += thisrun_count * 2;
432 address += thisrun_count * 2;
433 count -= thisrun_count;
434 }
435
436 target_free_working_area(target, source);
437 target_free_working_area(target, str9x_info->write_algorithm);
438
439 destroy_reg_param(&reg_params[0]);
440 destroy_reg_param(&reg_params[1]);
441 destroy_reg_param(&reg_params[2]);
442 destroy_reg_param(&reg_params[3]);
443
444 return retval;
445 }
446
447 static int str9x_write(struct flash_bank *bank,
448 uint8_t *buffer, uint32_t offset, uint32_t count)
449 {
450 struct target *target = bank->target;
451 uint32_t words_remaining = (count / 2);
452 uint32_t bytes_remaining = (count & 0x00000001);
453 uint32_t address = bank->base + offset;
454 uint32_t bytes_written = 0;
455 uint8_t status;
456 int retval;
457 uint32_t check_address = offset;
458 uint32_t bank_adr;
459 int i;
460
461 if (bank->target->state != TARGET_HALTED)
462 {
463 LOG_ERROR("Target not halted");
464 return ERROR_TARGET_NOT_HALTED;
465 }
466
467 if (offset & 0x1)
468 {
469 LOG_WARNING("offset 0x%" PRIx32 " breaks required 2-byte alignment", offset);
470 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
471 }
472
473 for (i = 0; i < bank->num_sectors; i++)
474 {
475 uint32_t sec_start = bank->sectors[i].offset;
476 uint32_t sec_end = sec_start + bank->sectors[i].size;
477
478 /* check if destination falls within the current sector */
479 if ((check_address >= sec_start) && (check_address < sec_end))
480 {
481 /* check if destination ends in the current sector */
482 if (offset + count < sec_end)
483 check_address = offset + count;
484 else
485 check_address = sec_end;
486 }
487 }
488
489 if (check_address != offset + count)
490 return ERROR_FLASH_DST_OUT_OF_BANK;
491
492 /* multiple half words (2-byte) to be programmed? */
493 if (words_remaining > 0)
494 {
495 /* try using a block write */
496 if ((retval = str9x_write_block(bank, buffer, offset, words_remaining)) != ERROR_OK)
497 {
498 if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE)
499 {
500 /* if block write failed (no sufficient working area),
501 * we use normal (slow) single dword accesses */
502 LOG_WARNING("couldn't use block writes, falling back to single memory accesses");
503 }
504 else if (retval == ERROR_FLASH_OPERATION_FAILED)
505 {
506 LOG_ERROR("flash writing failed with error code: 0x%x", retval);
507 return ERROR_FLASH_OPERATION_FAILED;
508 }
509 }
510 else
511 {
512 buffer += words_remaining * 2;
513 address += words_remaining * 2;
514 words_remaining = 0;
515 }
516 }
517
518 while (words_remaining > 0)
519 {
520 bank_adr = address & ~0x03;
521
522 /* write data command */
523 target_write_u16(target, bank_adr, 0x40);
524 target_write_memory(target, address, 2, 1, buffer + bytes_written);
525
526 /* get status command */
527 target_write_u16(target, bank_adr, 0x70);
528
529 int timeout;
530 for (timeout = 0; timeout < 1000; timeout++)
531 {
532 target_read_u8(target, bank_adr, &status);
533 if (status & 0x80)
534 break;
535 alive_sleep(1);
536 }
537 if (timeout == 1000)
538 {
539 LOG_ERROR("write timed out");
540 return ERROR_FAIL;
541 }
542
543 /* clear status reg and read array */
544 target_write_u16(target, bank_adr, 0x50);
545 target_write_u16(target, bank_adr, 0xFF);
546
547 if (status & 0x10)
548 return ERROR_FLASH_OPERATION_FAILED;
549 else if (status & 0x02)
550 return ERROR_FLASH_OPERATION_FAILED;
551
552 bytes_written += 2;
553 words_remaining--;
554 address += 2;
555 }
556
557 if (bytes_remaining)
558 {
559 uint8_t last_halfword[2] = {0xff, 0xff};
560 int i = 0;
561
562 while (bytes_remaining > 0)
563 {
564 last_halfword[i++] = *(buffer + bytes_written);
565 bytes_remaining--;
566 bytes_written++;
567 }
568
569 bank_adr = address & ~0x03;
570
571 /* write data command */
572 target_write_u16(target, bank_adr, 0x40);
573 target_write_memory(target, address, 2, 1, last_halfword);
574
575 /* query status command */
576 target_write_u16(target, bank_adr, 0x70);
577
578 int timeout;
579 for (timeout = 0; timeout < 1000; timeout++)
580 {
581 target_read_u8(target, bank_adr, &status);
582 if (status & 0x80)
583 break;
584 alive_sleep(1);
585 }
586 if (timeout == 1000)
587 {
588 LOG_ERROR("write timed out");
589 return ERROR_FAIL;
590 }
591
592 /* clear status reg and read array */
593 target_write_u16(target, bank_adr, 0x50);
594 target_write_u16(target, bank_adr, 0xFF);
595
596 if (status & 0x10)
597 return ERROR_FLASH_OPERATION_FAILED;
598 else if (status & 0x02)
599 return ERROR_FLASH_OPERATION_FAILED;
600 }
601
602 return ERROR_OK;
603 }
604
605 static int str9x_probe(struct flash_bank *bank)
606 {
607 return ERROR_OK;
608 }
609
610 #if 0
611 COMMAND_HANDLER(str9x_handle_part_id_command)
612 {
613 return ERROR_OK;
614 }
615 #endif
616
617 static int str9x_info(struct flash_bank *bank, char *buf, int buf_size)
618 {
619 snprintf(buf, buf_size, "str9x flash driver info");
620 return ERROR_OK;
621 }
622
623 COMMAND_HANDLER(str9x_handle_flash_config_command)
624 {
625 struct str9x_flash_bank *str9x_info;
626 struct target *target = NULL;
627
628 if (CMD_ARGC < 5)
629 {
630 return ERROR_COMMAND_SYNTAX_ERROR;
631 }
632
633 struct flash_bank *bank;
634 int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
635 if (ERROR_OK != retval)
636 return retval;
637
638 uint32_t bbsr, nbbsr, bbadr, nbbadr;
639 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], bbsr);
640 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], nbbsr);
641 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[3], bbadr);
642 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[4], nbbadr);
643
644 str9x_info = bank->driver_priv;
645
646 target = bank->target;
647
648 if (bank->target->state != TARGET_HALTED)
649 {
650 LOG_ERROR("Target not halted");
651 return ERROR_TARGET_NOT_HALTED;
652 }
653
654 /* config flash controller */
655 target_write_u32(target, FLASH_BBSR, bbsr);
656 target_write_u32(target, FLASH_NBBSR, nbbsr);
657 target_write_u32(target, FLASH_BBADR, bbadr >> 2);
658 target_write_u32(target, FLASH_NBBADR, nbbadr >> 2);
659
660 /* set bit 18 instruction TCM order as per flash programming manual */
661 arm966e_write_cp15(target, 62, 0x40000);
662
663 /* enable flash bank 1 */
664 target_write_u32(target, FLASH_CR, 0x18);
665 return ERROR_OK;
666 }
667
668 static const struct command_registration str9x_config_command_handlers[] = {
669 {
670 .name = "flash_config",
671 .handler = str9x_handle_flash_config_command,
672 .mode = COMMAND_EXEC,
673 .help = "Configure str9x flash controller, prior to "
674 "programming the flash.",
675 .usage = "bank_id BBSR NBBSR BBADR NBBADR",
676 },
677 COMMAND_REGISTRATION_DONE
678 };
679 static const struct command_registration str9x_command_handlers[] = {
680 {
681 .name = "str9x",
682 .mode = COMMAND_ANY,
683 .help = "str9x flash command group",
684 .chain = str9x_config_command_handlers,
685 },
686 COMMAND_REGISTRATION_DONE
687 };
688
689 struct flash_driver str9x_flash = {
690 .name = "str9x",
691 .commands = str9x_command_handlers,
692 .flash_bank_command = str9x_flash_bank_command,
693 .erase = str9x_erase,
694 .protect = str9x_protect,
695 .write = str9x_write,
696 .probe = str9x_probe,
697 .auto_probe = str9x_probe,
698 .erase_check = default_flash_blank_check,
699 .protect_check = str9x_protect_check,
700 .info = str9x_info,
701 };

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)