NOR: add read() callback to struct flash_driver
[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 = 32768;
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 static const 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, sizeof(str9x_flash_write_code),
377 &str9x_info->write_algorithm) != ERROR_OK)
378 {
379 LOG_WARNING("no working area available, can't do block memory writes");
380 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
381 };
382
383 target_write_buffer(target, str9x_info->write_algorithm->address,
384 sizeof(str9x_flash_write_code),
385 (uint8_t*)str9x_flash_write_code);
386
387 /* memory buffer */
388 while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK)
389 {
390 buffer_size /= 2;
391 if (buffer_size <= 256)
392 {
393 /* if we already allocated the writing code, but failed to get a
394 * buffer, free the algorithm */
395 if (str9x_info->write_algorithm)
396 target_free_working_area(target, str9x_info->write_algorithm);
397
398 LOG_WARNING("no large enough working area available, can't do block memory writes");
399 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
400 }
401 }
402
403 armv4_5_info.common_magic = ARM_COMMON_MAGIC;
404 armv4_5_info.core_mode = ARM_MODE_SVC;
405 armv4_5_info.core_state = ARM_STATE_ARM;
406
407 init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);
408 init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
409 init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT);
410 init_reg_param(&reg_params[3], "r3", 32, PARAM_IN);
411
412 while (count > 0)
413 {
414 uint32_t thisrun_count = (count > (buffer_size / 2)) ? (buffer_size / 2) : count;
415
416 target_write_buffer(target, source->address, thisrun_count * 2, buffer);
417
418 buf_set_u32(reg_params[0].value, 0, 32, source->address);
419 buf_set_u32(reg_params[1].value, 0, 32, address);
420 buf_set_u32(reg_params[2].value, 0, 32, thisrun_count);
421
422 if ((retval = target_run_algorithm(target, 0, NULL, 4, reg_params,
423 str9x_info->write_algorithm->address,
424 str9x_info->write_algorithm->address + (sizeof(str9x_flash_write_code) - 4),
425 10000, &armv4_5_info)) != ERROR_OK)
426 {
427 LOG_ERROR("error executing str9x flash write algorithm");
428 retval = ERROR_FLASH_OPERATION_FAILED;
429 break;
430 }
431
432 if (buf_get_u32(reg_params[3].value, 0, 32) != 0x80)
433 {
434 retval = ERROR_FLASH_OPERATION_FAILED;
435 break;
436 }
437
438 buffer += thisrun_count * 2;
439 address += thisrun_count * 2;
440 count -= thisrun_count;
441 }
442
443 target_free_working_area(target, source);
444 target_free_working_area(target, str9x_info->write_algorithm);
445
446 destroy_reg_param(&reg_params[0]);
447 destroy_reg_param(&reg_params[1]);
448 destroy_reg_param(&reg_params[2]);
449 destroy_reg_param(&reg_params[3]);
450
451 return retval;
452 }
453
454 static int str9x_write(struct flash_bank *bank,
455 uint8_t *buffer, uint32_t offset, uint32_t count)
456 {
457 struct target *target = bank->target;
458 uint32_t words_remaining = (count / 2);
459 uint32_t bytes_remaining = (count & 0x00000001);
460 uint32_t address = bank->base + offset;
461 uint32_t bytes_written = 0;
462 uint8_t status;
463 int retval;
464 uint32_t check_address = offset;
465 uint32_t bank_adr;
466 int i;
467
468 if (bank->target->state != TARGET_HALTED)
469 {
470 LOG_ERROR("Target not halted");
471 return ERROR_TARGET_NOT_HALTED;
472 }
473
474 if (offset & 0x1)
475 {
476 LOG_WARNING("offset 0x%" PRIx32 " breaks required 2-byte alignment", offset);
477 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
478 }
479
480 for (i = 0; i < bank->num_sectors; i++)
481 {
482 uint32_t sec_start = bank->sectors[i].offset;
483 uint32_t sec_end = sec_start + bank->sectors[i].size;
484
485 /* check if destination falls within the current sector */
486 if ((check_address >= sec_start) && (check_address < sec_end))
487 {
488 /* check if destination ends in the current sector */
489 if (offset + count < sec_end)
490 check_address = offset + count;
491 else
492 check_address = sec_end;
493 }
494 }
495
496 if (check_address != offset + count)
497 return ERROR_FLASH_DST_OUT_OF_BANK;
498
499 /* multiple half words (2-byte) to be programmed? */
500 if (words_remaining > 0)
501 {
502 /* try using a block write */
503 if ((retval = str9x_write_block(bank, buffer, offset, words_remaining)) != ERROR_OK)
504 {
505 if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE)
506 {
507 /* if block write failed (no sufficient working area),
508 * we use normal (slow) single dword accesses */
509 LOG_WARNING("couldn't use block writes, falling back to single memory accesses");
510 }
511 else if (retval == ERROR_FLASH_OPERATION_FAILED)
512 {
513 LOG_ERROR("flash writing failed with error code: 0x%x", retval);
514 return ERROR_FLASH_OPERATION_FAILED;
515 }
516 }
517 else
518 {
519 buffer += words_remaining * 2;
520 address += words_remaining * 2;
521 words_remaining = 0;
522 }
523 }
524
525 while (words_remaining > 0)
526 {
527 bank_adr = address & ~0x03;
528
529 /* write data command */
530 target_write_u16(target, bank_adr, 0x40);
531 target_write_memory(target, address, 2, 1, buffer + bytes_written);
532
533 /* get status command */
534 target_write_u16(target, bank_adr, 0x70);
535
536 int timeout;
537 for (timeout = 0; timeout < 1000; timeout++)
538 {
539 target_read_u8(target, bank_adr, &status);
540 if (status & 0x80)
541 break;
542 alive_sleep(1);
543 }
544 if (timeout == 1000)
545 {
546 LOG_ERROR("write timed out");
547 return ERROR_FAIL;
548 }
549
550 /* clear status reg and read array */
551 target_write_u16(target, bank_adr, 0x50);
552 target_write_u16(target, bank_adr, 0xFF);
553
554 if (status & 0x10)
555 return ERROR_FLASH_OPERATION_FAILED;
556 else if (status & 0x02)
557 return ERROR_FLASH_OPERATION_FAILED;
558
559 bytes_written += 2;
560 words_remaining--;
561 address += 2;
562 }
563
564 if (bytes_remaining)
565 {
566 uint8_t last_halfword[2] = {0xff, 0xff};
567 int i = 0;
568
569 while (bytes_remaining > 0)
570 {
571 last_halfword[i++] = *(buffer + bytes_written);
572 bytes_remaining--;
573 bytes_written++;
574 }
575
576 bank_adr = address & ~0x03;
577
578 /* write data command */
579 target_write_u16(target, bank_adr, 0x40);
580 target_write_memory(target, address, 2, 1, last_halfword);
581
582 /* query status command */
583 target_write_u16(target, bank_adr, 0x70);
584
585 int timeout;
586 for (timeout = 0; timeout < 1000; timeout++)
587 {
588 target_read_u8(target, bank_adr, &status);
589 if (status & 0x80)
590 break;
591 alive_sleep(1);
592 }
593 if (timeout == 1000)
594 {
595 LOG_ERROR("write timed out");
596 return ERROR_FAIL;
597 }
598
599 /* clear status reg and read array */
600 target_write_u16(target, bank_adr, 0x50);
601 target_write_u16(target, bank_adr, 0xFF);
602
603 if (status & 0x10)
604 return ERROR_FLASH_OPERATION_FAILED;
605 else if (status & 0x02)
606 return ERROR_FLASH_OPERATION_FAILED;
607 }
608
609 return ERROR_OK;
610 }
611
612 static int str9x_probe(struct flash_bank *bank)
613 {
614 return ERROR_OK;
615 }
616
617 #if 0
618 COMMAND_HANDLER(str9x_handle_part_id_command)
619 {
620 return ERROR_OK;
621 }
622 #endif
623
624 static int str9x_info(struct flash_bank *bank, char *buf, int buf_size)
625 {
626 snprintf(buf, buf_size, "str9x flash driver info");
627 return ERROR_OK;
628 }
629
630 COMMAND_HANDLER(str9x_handle_flash_config_command)
631 {
632 struct str9x_flash_bank *str9x_info;
633 struct target *target = NULL;
634
635 if (CMD_ARGC < 5)
636 {
637 return ERROR_COMMAND_SYNTAX_ERROR;
638 }
639
640 struct flash_bank *bank;
641 int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
642 if (ERROR_OK != retval)
643 return retval;
644
645 uint32_t bbsr, nbbsr, bbadr, nbbadr;
646 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], bbsr);
647 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], nbbsr);
648 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[3], bbadr);
649 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[4], nbbadr);
650
651 str9x_info = bank->driver_priv;
652
653 target = bank->target;
654
655 if (bank->target->state != TARGET_HALTED)
656 {
657 LOG_ERROR("Target not halted");
658 return ERROR_TARGET_NOT_HALTED;
659 }
660
661 /* config flash controller */
662 target_write_u32(target, FLASH_BBSR, bbsr);
663 target_write_u32(target, FLASH_NBBSR, nbbsr);
664 target_write_u32(target, FLASH_BBADR, bbadr >> 2);
665 target_write_u32(target, FLASH_NBBADR, nbbadr >> 2);
666
667 /* set bit 18 instruction TCM order as per flash programming manual */
668 arm966e_write_cp15(target, 62, 0x40000);
669
670 /* enable flash bank 1 */
671 target_write_u32(target, FLASH_CR, 0x18);
672 return ERROR_OK;
673 }
674
675 static const struct command_registration str9x_config_command_handlers[] = {
676 {
677 .name = "flash_config",
678 .handler = str9x_handle_flash_config_command,
679 .mode = COMMAND_EXEC,
680 .help = "Configure str9x flash controller, prior to "
681 "programming the flash.",
682 .usage = "bank_id BBSR NBBSR BBADR NBBADR",
683 },
684 COMMAND_REGISTRATION_DONE
685 };
686
687 static const struct command_registration str9x_command_handlers[] = {
688 {
689 .name = "str9x",
690 .mode = COMMAND_ANY,
691 .help = "str9x flash command group",
692 .chain = str9x_config_command_handlers,
693 },
694 COMMAND_REGISTRATION_DONE
695 };
696
697 struct flash_driver str9x_flash = {
698 .name = "str9x",
699 .commands = str9x_command_handlers,
700 .flash_bank_command = str9x_flash_bank_command,
701 .erase = str9x_erase,
702 .protect = str9x_protect,
703 .write = str9x_write,
704 .read = default_flash_read,
705 .probe = str9x_probe,
706 .auto_probe = str9x_probe,
707 .erase_check = default_flash_blank_check,
708 .protect_check = str9x_protect_check,
709 .info = str9x_info,
710 };

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)