str9xpec: -Wshadow warning fixes
[openocd.git] / src / flash / nor / str9xpec.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 * This program is free software; you can redistribute it and/or modify *
9 * it under the terms of the GNU General Public License as published by *
10 * the Free Software Foundation; either version 2 of the License, or *
11 * (at your option) any later version. *
12 * *
13 * This program is distributed in the hope that it will be useful, *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16 * GNU General Public License for more details. *
17 * *
18 * You should have received a copy of the GNU General Public License *
19 * along with this program; if not, write to the *
20 * Free Software Foundation, Inc., *
21 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
22 ***************************************************************************/
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26
27 #include "imp.h"
28 #include "str9xpec.h"
29 #include <target/arm7_9_common.h>
30
31
32 static int str9xpec_erase_area(struct flash_bank *bank, int first, int last);
33 static int str9xpec_set_address(struct flash_bank *bank, uint8_t sector);
34 static int str9xpec_write_options(struct flash_bank *bank);
35
36 static int str9xpec_set_instr(struct jtag_tap *tap, uint32_t new_instr, tap_state_t end_state)
37 {
38 if (tap == NULL) {
39 return ERROR_TARGET_INVALID;
40 }
41
42 if (buf_get_u32(tap->cur_instr, 0, tap->ir_length) != new_instr)
43 {
44 struct scan_field field;
45
46 field.num_bits = tap->ir_length;
47 void * t = calloc(DIV_ROUND_UP(field.num_bits, 8), 1);
48 field.out_value = t;
49 buf_set_u32(t, 0, field.num_bits, new_instr);
50 field.in_value = NULL;
51
52 jtag_add_ir_scan(tap, &field, end_state);
53
54 free(t);
55 }
56
57 return ERROR_OK;
58 }
59
60 static uint8_t str9xpec_isc_status(struct jtag_tap *tap)
61 {
62 struct scan_field field;
63 uint8_t status;
64
65 if (str9xpec_set_instr(tap, ISC_NOOP, TAP_IRPAUSE) != ERROR_OK)
66 return ISC_STATUS_ERROR;
67
68 field.num_bits = 8;
69 field.out_value = NULL;
70 field.in_value = &status;
71
72
73 jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);
74 jtag_execute_queue();
75
76 LOG_DEBUG("status: 0x%2.2x", status);
77
78 if (status & ISC_STATUS_SECURITY)
79 LOG_INFO("Device Security Bit Set");
80
81 return status;
82 }
83
84 static int str9xpec_isc_enable(struct flash_bank *bank)
85 {
86 uint8_t status;
87 struct jtag_tap *tap;
88 struct str9xpec_flash_controller *str9xpec_info = bank->driver_priv;
89
90 tap = str9xpec_info->tap;
91
92 if (str9xpec_info->isc_enable)
93 return ERROR_OK;
94
95 /* enter isc mode */
96 if (str9xpec_set_instr(tap, ISC_ENABLE, TAP_IDLE) != ERROR_OK)
97 return ERROR_TARGET_INVALID;
98
99 /* check ISC status */
100 status = str9xpec_isc_status(tap);
101 if (status & ISC_STATUS_MODE)
102 {
103 /* we have entered isc mode */
104 str9xpec_info->isc_enable = 1;
105 LOG_DEBUG("ISC_MODE Enabled");
106 }
107
108 return ERROR_OK;
109 }
110
111 static int str9xpec_isc_disable(struct flash_bank *bank)
112 {
113 uint8_t status;
114 struct jtag_tap *tap;
115 struct str9xpec_flash_controller *str9xpec_info = bank->driver_priv;
116
117 tap = str9xpec_info->tap;
118
119 if (!str9xpec_info->isc_enable)
120 return ERROR_OK;
121
122 if (str9xpec_set_instr(tap, ISC_DISABLE, TAP_IDLE) != ERROR_OK)
123 return ERROR_TARGET_INVALID;
124
125 /* delay to handle aborts */
126 jtag_add_sleep(50);
127
128 /* check ISC status */
129 status = str9xpec_isc_status(tap);
130 if (!(status & ISC_STATUS_MODE))
131 {
132 /* we have left isc mode */
133 str9xpec_info->isc_enable = 0;
134 LOG_DEBUG("ISC_MODE Disabled");
135 }
136
137 return ERROR_OK;
138 }
139
140 static int str9xpec_read_config(struct flash_bank *bank)
141 {
142 struct scan_field field;
143 uint8_t status;
144 struct jtag_tap *tap;
145
146 struct str9xpec_flash_controller *str9xpec_info = bank->driver_priv;
147
148 tap = str9xpec_info->tap;
149
150 LOG_DEBUG("ISC_CONFIGURATION");
151
152 /* execute ISC_CONFIGURATION command */
153 str9xpec_set_instr(tap, ISC_CONFIGURATION, TAP_IRPAUSE);
154
155 field.num_bits = 64;
156 field.out_value = NULL;
157 field.in_value = str9xpec_info->options;
158
159
160 jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);
161 jtag_execute_queue();
162
163 status = str9xpec_isc_status(tap);
164
165 return status;
166 }
167
168 static int str9xpec_build_block_list(struct flash_bank *bank)
169 {
170 struct str9xpec_flash_controller *str9xpec_info = bank->driver_priv;
171
172 int i;
173 int num_sectors;
174 int b0_sectors = 0, b1_sectors = 0;
175 uint32_t offset = 0;
176 int b1_size = 0x2000;
177
178 switch (bank->size)
179 {
180 case (256 * 1024):
181 b0_sectors = 4;
182 break;
183 case (512 * 1024):
184 b0_sectors = 8;
185 break;
186 case (1024 * 1024):
187 b0_sectors = 16;
188 break;
189 case (2048 * 1024):
190 b0_sectors = 32;
191 break;
192 case (128 * 1024):
193 b1_size = 0x4000;
194 b1_sectors = 8;
195 break;
196 case (32 * 1024):
197 b1_sectors = 4;
198 break;
199 default:
200 LOG_ERROR("BUG: unknown bank->size encountered");
201 exit(-1);
202 }
203
204 num_sectors = b0_sectors + b1_sectors;
205
206 bank->num_sectors = num_sectors;
207 bank->sectors = malloc(sizeof(struct flash_sector) * num_sectors);
208 str9xpec_info->sector_bits = malloc(sizeof(uint32_t) * num_sectors);
209
210 num_sectors = 0;
211
212 for (i = 0; i < b0_sectors; i++)
213 {
214 bank->sectors[num_sectors].offset = offset;
215 bank->sectors[num_sectors].size = 0x10000;
216 offset += bank->sectors[i].size;
217 bank->sectors[num_sectors].is_erased = -1;
218 bank->sectors[num_sectors].is_protected = 1;
219 str9xpec_info->sector_bits[num_sectors++] = i;
220 }
221
222 for (i = 0; i < b1_sectors; i++)
223 {
224 bank->sectors[num_sectors].offset = offset;
225 bank->sectors[num_sectors].size = b1_size;
226 offset += bank->sectors[i].size;
227 bank->sectors[num_sectors].is_erased = -1;
228 bank->sectors[num_sectors].is_protected = 1;
229 str9xpec_info->sector_bits[num_sectors++] = i + 32;
230 }
231
232 return ERROR_OK;
233 }
234
235 /* flash bank str9x <base> <size> 0 0 <target#>
236 */
237 FLASH_BANK_COMMAND_HANDLER(str9xpec_flash_bank_command)
238 {
239 struct str9xpec_flash_controller *str9xpec_info;
240 struct arm *armv4_5 = NULL;
241 struct arm7_9_common *arm7_9 = NULL;
242 struct arm_jtag *jtag_info = NULL;
243
244 if (CMD_ARGC < 6)
245 {
246 LOG_WARNING("incomplete flash_bank str9x configuration");
247 return ERROR_FLASH_BANK_INVALID;
248 }
249
250 str9xpec_info = malloc(sizeof(struct str9xpec_flash_controller));
251 bank->driver_priv = str9xpec_info;
252
253 /* REVISIT verify that the jtag position of flash controller is
254 * right after *THIS* core, which must be a STR9xx core ...
255 */
256 armv4_5 = bank->target->arch_info;
257 arm7_9 = armv4_5->arch_info;
258 jtag_info = &arm7_9->jtag_info;
259
260 str9xpec_info->tap = bank->target->tap;
261 str9xpec_info->isc_enable = 0;
262
263 str9xpec_build_block_list(bank);
264
265 /* clear option byte register */
266 buf_set_u32(str9xpec_info->options, 0, 64, 0);
267
268 return ERROR_OK;
269 }
270
271 static int str9xpec_blank_check(struct flash_bank *bank, int first, int last)
272 {
273 struct scan_field field;
274 uint8_t status;
275 struct jtag_tap *tap;
276 int i;
277 uint8_t *buffer = NULL;
278
279 struct str9xpec_flash_controller *str9xpec_info = bank->driver_priv;
280
281 tap = str9xpec_info->tap;
282
283 if (!str9xpec_info->isc_enable) {
284 str9xpec_isc_enable(bank);
285 }
286
287 if (!str9xpec_info->isc_enable) {
288 return ERROR_FLASH_OPERATION_FAILED;
289 }
290
291 buffer = calloc(DIV_ROUND_UP(64, 8), 1);
292
293 LOG_DEBUG("blank check: first_bank: %i, last_bank: %i", first, last);
294
295 for (i = first; i <= last; i++) {
296 buf_set_u32(buffer, str9xpec_info->sector_bits[i], 1, 1);
297 }
298
299 /* execute ISC_BLANK_CHECK command */
300 str9xpec_set_instr(tap, ISC_BLANK_CHECK, TAP_IRPAUSE);
301
302 field.num_bits = 64;
303 field.out_value = buffer;
304 field.in_value = NULL;
305
306 jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);
307 jtag_add_sleep(40000);
308
309 /* read blank check result */
310 field.num_bits = 64;
311 field.out_value = NULL;
312 field.in_value = buffer;
313
314 jtag_add_dr_scan(tap, 1, &field, TAP_IRPAUSE);
315 jtag_execute_queue();
316
317 status = str9xpec_isc_status(tap);
318
319 for (i = first; i <= last; i++)
320 {
321 if (buf_get_u32(buffer, str9xpec_info->sector_bits[i], 1))
322 bank->sectors[i].is_erased = 0;
323 else
324 bank->sectors[i].is_erased = 1;
325 }
326
327 free(buffer);
328
329 str9xpec_isc_disable(bank);
330
331 if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
332 return ERROR_FLASH_OPERATION_FAILED;
333 return ERROR_OK;
334 }
335
336 static int str9xpec_protect_check(struct flash_bank *bank)
337 {
338 uint8_t status;
339 int i;
340
341 struct str9xpec_flash_controller *str9xpec_info = bank->driver_priv;
342
343 status = str9xpec_read_config(bank);
344
345 for (i = 0; i < bank->num_sectors; i++)
346 {
347 if (buf_get_u32(str9xpec_info->options, str9xpec_info->sector_bits[i], 1))
348 bank->sectors[i].is_protected = 1;
349 else
350 bank->sectors[i].is_protected = 0;
351 }
352
353 if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
354 return ERROR_FLASH_OPERATION_FAILED;
355 return ERROR_OK;
356 }
357
358 static int str9xpec_erase_area(struct flash_bank *bank, int first, int last)
359 {
360 struct scan_field field;
361 uint8_t status;
362 struct jtag_tap *tap;
363 int i;
364 uint8_t *buffer = NULL;
365
366 struct str9xpec_flash_controller *str9xpec_info = bank->driver_priv;
367
368 tap = str9xpec_info->tap;
369
370 if (!str9xpec_info->isc_enable) {
371 str9xpec_isc_enable(bank);
372 }
373
374 if (!str9xpec_info->isc_enable) {
375 return ISC_STATUS_ERROR;
376 }
377
378 buffer = calloc(DIV_ROUND_UP(64, 8), 1);
379
380 LOG_DEBUG("erase: first_bank: %i, last_bank: %i", first, last);
381
382 /* last bank: 0xFF signals a full erase (unlock complete device) */
383 /* last bank: 0xFE signals a option byte erase */
384 if (last == 0xFF)
385 {
386 for (i = 0; i < 64; i++) {
387 buf_set_u32(buffer, i, 1, 1);
388 }
389 }
390 else if (last == 0xFE)
391 {
392 buf_set_u32(buffer, 49, 1, 1);
393 }
394 else
395 {
396 for (i = first; i <= last; i++) {
397 buf_set_u32(buffer, str9xpec_info->sector_bits[i], 1, 1);
398 }
399 }
400
401 LOG_DEBUG("ISC_ERASE");
402
403 /* execute ISC_ERASE command */
404 str9xpec_set_instr(tap, ISC_ERASE, TAP_IRPAUSE);
405
406 field.num_bits = 64;
407 field.out_value = buffer;
408 field.in_value = NULL;
409
410 jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);
411 jtag_execute_queue();
412
413 jtag_add_sleep(10);
414
415 /* wait for erase completion */
416 while (!((status = str9xpec_isc_status(tap)) & ISC_STATUS_BUSY)) {
417 alive_sleep(1);
418 }
419
420 free(buffer);
421
422 str9xpec_isc_disable(bank);
423
424 return status;
425 }
426
427 static int str9xpec_erase(struct flash_bank *bank, int first, int last)
428 {
429 int status;
430
431 status = str9xpec_erase_area(bank, first, last);
432
433 if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
434 return ERROR_FLASH_OPERATION_FAILED;
435
436 return ERROR_OK;
437 }
438
439 static int str9xpec_lock_device(struct flash_bank *bank)
440 {
441 struct scan_field field;
442 uint8_t status;
443 struct jtag_tap *tap;
444 struct str9xpec_flash_controller *str9xpec_info = NULL;
445
446 str9xpec_info = bank->driver_priv;
447 tap = str9xpec_info->tap;
448
449 if (!str9xpec_info->isc_enable) {
450 str9xpec_isc_enable(bank);
451 }
452
453 if (!str9xpec_info->isc_enable) {
454 return ISC_STATUS_ERROR;
455 }
456
457 /* set security address */
458 str9xpec_set_address(bank, 0x80);
459
460 /* execute ISC_PROGRAM command */
461 str9xpec_set_instr(tap, ISC_PROGRAM_SECURITY, TAP_IDLE);
462
463 str9xpec_set_instr(tap, ISC_NOOP, TAP_IRPAUSE);
464
465 do {
466 field.num_bits = 8;
467 field.out_value = NULL;
468 field.in_value = &status;
469
470 jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);
471 jtag_execute_queue();
472
473 } while (!(status & ISC_STATUS_BUSY));
474
475 str9xpec_isc_disable(bank);
476
477 return status;
478 }
479
480 static int str9xpec_unlock_device(struct flash_bank *bank)
481 {
482 uint8_t status;
483
484 status = str9xpec_erase_area(bank, 0, 255);
485
486 return status;
487 }
488
489 static int str9xpec_protect(struct flash_bank *bank, int set, int first, int last)
490 {
491 uint8_t status;
492 int i;
493
494 struct str9xpec_flash_controller *str9xpec_info = bank->driver_priv;
495
496 status = str9xpec_read_config(bank);
497
498 if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
499 return ERROR_FLASH_OPERATION_FAILED;
500
501 LOG_DEBUG("protect: first_bank: %i, last_bank: %i", first, last);
502
503 /* last bank: 0xFF signals a full device protect */
504 if (last == 0xFF)
505 {
506 if (set)
507 {
508 status = str9xpec_lock_device(bank);
509 }
510 else
511 {
512 /* perform full erase to unlock device */
513 status = str9xpec_unlock_device(bank);
514 }
515 }
516 else
517 {
518 for (i = first; i <= last; i++)
519 {
520 if (set)
521 buf_set_u32(str9xpec_info->options, str9xpec_info->sector_bits[i], 1, 1);
522 else
523 buf_set_u32(str9xpec_info->options, str9xpec_info->sector_bits[i], 1, 0);
524 }
525
526 status = str9xpec_write_options(bank);
527 }
528
529 if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
530 return ERROR_FLASH_OPERATION_FAILED;
531
532 return ERROR_OK;
533 }
534
535 static int str9xpec_set_address(struct flash_bank *bank, uint8_t sector)
536 {
537 struct jtag_tap *tap;
538 struct scan_field field;
539 struct str9xpec_flash_controller *str9xpec_info = bank->driver_priv;
540
541 tap = str9xpec_info->tap;
542
543 /* set flash controller address */
544 str9xpec_set_instr(tap, ISC_ADDRESS_SHIFT, TAP_IRPAUSE);
545
546 field.num_bits = 8;
547 field.out_value = &sector;
548 field.in_value = NULL;
549
550 jtag_add_dr_scan(tap, 1, &field, TAP_IRPAUSE);
551
552 return ERROR_OK;
553 }
554
555 static int str9xpec_write(struct flash_bank *bank, uint8_t *buffer,
556 uint32_t offset, uint32_t count)
557 {
558 struct str9xpec_flash_controller *str9xpec_info = bank->driver_priv;
559 uint32_t dwords_remaining = (count / 8);
560 uint32_t bytes_remaining = (count & 0x00000007);
561 uint32_t bytes_written = 0;
562 uint8_t status;
563 uint32_t check_address = offset;
564 struct jtag_tap *tap;
565 struct scan_field field;
566 uint8_t *scanbuf;
567 int i;
568 int first_sector = 0;
569 int last_sector = 0;
570
571 tap = str9xpec_info->tap;
572
573 if (!str9xpec_info->isc_enable) {
574 str9xpec_isc_enable(bank);
575 }
576
577 if (!str9xpec_info->isc_enable) {
578 return ERROR_FLASH_OPERATION_FAILED;
579 }
580
581 if (offset & 0x7)
582 {
583 LOG_WARNING("offset 0x%" PRIx32 " breaks required 8-byte alignment", offset);
584 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
585 }
586
587 for (i = 0; i < bank->num_sectors; i++)
588 {
589 uint32_t sec_start = bank->sectors[i].offset;
590 uint32_t sec_end = sec_start + bank->sectors[i].size;
591
592 /* check if destination falls within the current sector */
593 if ((check_address >= sec_start) && (check_address < sec_end))
594 {
595 /* check if destination ends in the current sector */
596 if (offset + count < sec_end)
597 check_address = offset + count;
598 else
599 check_address = sec_end;
600 }
601
602 if ((offset >= sec_start) && (offset < sec_end)) {
603 first_sector = i;
604 }
605
606 if ((offset + count >= sec_start) && (offset + count < sec_end)) {
607 last_sector = i;
608 }
609 }
610
611 if (check_address != offset + count)
612 return ERROR_FLASH_DST_OUT_OF_BANK;
613
614 LOG_DEBUG("first_sector: %i, last_sector: %i", first_sector, last_sector);
615
616 scanbuf = calloc(DIV_ROUND_UP(64, 8), 1);
617
618 LOG_DEBUG("ISC_PROGRAM");
619
620 for (i = first_sector; i <= last_sector; i++)
621 {
622 str9xpec_set_address(bank, str9xpec_info->sector_bits[i]);
623
624 dwords_remaining = dwords_remaining < (bank->sectors[i].size/8)
625 ? dwords_remaining : (bank->sectors[i].size/8);
626
627 while (dwords_remaining > 0)
628 {
629 str9xpec_set_instr(tap, ISC_PROGRAM, TAP_IRPAUSE);
630
631 field.num_bits = 64;
632 field.out_value = (buffer + bytes_written);
633 field.in_value = NULL;
634
635 jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);
636
637 /* small delay before polling */
638 jtag_add_sleep(50);
639
640 str9xpec_set_instr(tap, ISC_NOOP, TAP_IRPAUSE);
641
642 do {
643 field.num_bits = 8;
644 field.out_value = NULL;
645 field.in_value = scanbuf;
646
647 jtag_add_dr_scan(tap, 1, &field, TAP_IRPAUSE);
648 jtag_execute_queue();
649
650 status = buf_get_u32(scanbuf, 0, 8);
651
652 } while (!(status & ISC_STATUS_BUSY));
653
654 if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
655 return ERROR_FLASH_OPERATION_FAILED;
656
657 /* if ((status & ISC_STATUS_INT_ERROR) != STR9XPEC_ISC_INTFAIL)
658 return ERROR_FLASH_OPERATION_FAILED; */
659
660 dwords_remaining--;
661 bytes_written += 8;
662 }
663 }
664
665 if (bytes_remaining)
666 {
667 uint8_t last_dword[8] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
668 i = 0;
669
670 while (bytes_remaining > 0)
671 {
672 last_dword[i++] = *(buffer + bytes_written);
673 bytes_remaining--;
674 bytes_written++;
675 }
676
677 str9xpec_set_instr(tap, ISC_PROGRAM, TAP_IRPAUSE);
678
679 field.num_bits = 64;
680 field.out_value = last_dword;
681 field.in_value = NULL;
682
683 jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);
684
685 /* small delay before polling */
686 jtag_add_sleep(50);
687
688 str9xpec_set_instr(tap, ISC_NOOP, TAP_IRPAUSE);
689
690 do {
691 field.num_bits = 8;
692 field.out_value = NULL;
693 field.in_value = scanbuf;
694
695 jtag_add_dr_scan(tap, 1, &field, TAP_IRPAUSE);
696 jtag_execute_queue();
697
698 status = buf_get_u32(scanbuf, 0, 8);
699
700 } while (!(status & ISC_STATUS_BUSY));
701
702 if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
703 return ERROR_FLASH_OPERATION_FAILED;
704
705 /* if ((status & ISC_STATUS_INT_ERROR) != STR9XPEC_ISC_INTFAIL)
706 return ERROR_FLASH_OPERATION_FAILED; */
707 }
708
709 free(scanbuf);
710
711 str9xpec_isc_disable(bank);
712
713 return ERROR_OK;
714 }
715
716 static int str9xpec_probe(struct flash_bank *bank)
717 {
718 return ERROR_OK;
719 }
720
721 COMMAND_HANDLER(str9xpec_handle_part_id_command)
722 {
723 struct scan_field field;
724 uint8_t *buffer = NULL;
725 struct jtag_tap *tap;
726 uint32_t idcode;
727 struct str9xpec_flash_controller *str9xpec_info = NULL;
728
729 if (CMD_ARGC < 1)
730 return ERROR_COMMAND_SYNTAX_ERROR;
731
732 struct flash_bank *bank;
733 int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
734 if (ERROR_OK != retval)
735 return retval;
736
737 str9xpec_info = bank->driver_priv;
738 tap = str9xpec_info->tap;
739
740 buffer = calloc(DIV_ROUND_UP(32, 8), 1);
741
742 str9xpec_set_instr(tap, ISC_IDCODE, TAP_IRPAUSE);
743
744 field.num_bits = 32;
745 field.out_value = NULL;
746 field.in_value = buffer;
747
748 jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);
749 jtag_execute_queue();
750
751 idcode = buf_get_u32(buffer, 0, 32);
752
753 command_print(CMD_CTX, "str9xpec part id: 0x%8.8" PRIx32 "", idcode);
754
755 free(buffer);
756
757 return ERROR_OK;
758 }
759
760 static int str9xpec_erase_check(struct flash_bank *bank)
761 {
762 return str9xpec_blank_check(bank, 0, bank->num_sectors - 1);
763 }
764
765 static int get_str9xpec_info(struct flash_bank *bank, char *buf, int buf_size)
766 {
767 snprintf(buf, buf_size, "str9xpec flash driver info");
768 return ERROR_OK;
769 }
770
771 COMMAND_HANDLER(str9xpec_handle_flash_options_read_command)
772 {
773 uint8_t status;
774 struct str9xpec_flash_controller *str9xpec_info = NULL;
775
776 if (CMD_ARGC < 1)
777 {
778 command_print(CMD_CTX, "str9xpec options_read <bank>");
779 return ERROR_OK;
780 }
781
782 struct flash_bank *bank;
783 int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
784 if (ERROR_OK != retval)
785 return retval;
786
787 str9xpec_info = bank->driver_priv;
788
789 status = str9xpec_read_config(bank);
790
791 if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
792 return ERROR_FLASH_OPERATION_FAILED;
793
794 /* boot bank */
795 if (buf_get_u32(str9xpec_info->options, STR9XPEC_OPT_CSMAPBIT, 1))
796 command_print(CMD_CTX, "CS Map: bank1");
797 else
798 command_print(CMD_CTX, "CS Map: bank0");
799
800 /* OTP lock */
801 if (buf_get_u32(str9xpec_info->options, STR9XPEC_OPT_OTPBIT, 1))
802 command_print(CMD_CTX, "OTP Lock: OTP Locked");
803 else
804 command_print(CMD_CTX, "OTP Lock: OTP Unlocked");
805
806 /* LVD Threshold */
807 if (buf_get_u32(str9xpec_info->options, STR9XPEC_OPT_LVDTHRESBIT, 1))
808 command_print(CMD_CTX, "LVD Threshold: 2.7v");
809 else
810 command_print(CMD_CTX, "LVD Threshold: 2.4v");
811
812 /* LVD reset warning */
813 if (buf_get_u32(str9xpec_info->options, STR9XPEC_OPT_LVDWARNBIT, 1))
814 command_print(CMD_CTX, "LVD Reset Warning: VDD or VDDQ Inputs");
815 else
816 command_print(CMD_CTX, "LVD Reset Warning: VDD Input Only");
817
818 /* LVD reset select */
819 if (buf_get_u32(str9xpec_info->options, STR9XPEC_OPT_LVDSELBIT, 1))
820 command_print(CMD_CTX, "LVD Reset Selection: VDD or VDDQ Inputs");
821 else
822 command_print(CMD_CTX, "LVD Reset Selection: VDD Input Only");
823
824 return ERROR_OK;
825 }
826
827 static int str9xpec_write_options(struct flash_bank *bank)
828 {
829 struct scan_field field;
830 uint8_t status;
831 struct jtag_tap *tap;
832 struct str9xpec_flash_controller *str9xpec_info = NULL;
833
834 str9xpec_info = bank->driver_priv;
835 tap = str9xpec_info->tap;
836
837 /* erase config options first */
838 status = str9xpec_erase_area(bank, 0xFE, 0xFE);
839
840 if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
841 return status;
842
843 if (!str9xpec_info->isc_enable) {
844 str9xpec_isc_enable(bank);
845 }
846
847 if (!str9xpec_info->isc_enable) {
848 return ISC_STATUS_ERROR;
849 }
850
851 /* according to data 64th bit has to be set */
852 buf_set_u32(str9xpec_info->options, 63, 1, 1);
853
854 /* set option byte address */
855 str9xpec_set_address(bank, 0x50);
856
857 /* execute ISC_PROGRAM command */
858 str9xpec_set_instr(tap, ISC_PROGRAM, TAP_IRPAUSE);
859
860 field.num_bits = 64;
861 field.out_value = str9xpec_info->options;
862 field.in_value = NULL;
863
864 jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);
865
866 /* small delay before polling */
867 jtag_add_sleep(50);
868
869 str9xpec_set_instr(tap, ISC_NOOP, TAP_IRPAUSE);
870
871 do {
872 field.num_bits = 8;
873 field.out_value = NULL;
874 field.in_value = &status;
875
876 jtag_add_dr_scan(tap, 1, &field, TAP_IRPAUSE);
877 jtag_execute_queue();
878
879 } while (!(status & ISC_STATUS_BUSY));
880
881 str9xpec_isc_disable(bank);
882
883 return status;
884 }
885
886 COMMAND_HANDLER(str9xpec_handle_flash_options_write_command)
887 {
888 uint8_t status;
889
890 if (CMD_ARGC < 1)
891 {
892 command_print(CMD_CTX, "str9xpec options_write <bank>");
893 return ERROR_OK;
894 }
895
896 struct flash_bank *bank;
897 int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
898 if (ERROR_OK != retval)
899 return retval;
900
901 status = str9xpec_write_options(bank);
902
903 if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
904 return ERROR_FLASH_OPERATION_FAILED;
905
906 command_print(CMD_CTX, "str9xpec write options complete.\n"
907 "INFO: a reset or power cycle is required "
908 "for the new settings to take effect.");
909
910 return ERROR_OK;
911 }
912
913 COMMAND_HANDLER(str9xpec_handle_flash_options_cmap_command)
914 {
915 struct str9xpec_flash_controller *str9xpec_info = NULL;
916
917 if (CMD_ARGC < 2)
918 {
919 command_print(CMD_CTX, "str9xpec options_cmap <bank> <bank0 | bank1>");
920 return ERROR_OK;
921 }
922
923 struct flash_bank *bank;
924 int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
925 if (ERROR_OK != retval)
926 return retval;
927
928 str9xpec_info = bank->driver_priv;
929
930 if (strcmp(CMD_ARGV[1], "bank1") == 0)
931 {
932 buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_CSMAPBIT, 1, 1);
933 }
934 else
935 {
936 buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_CSMAPBIT, 1, 0);
937 }
938
939 return ERROR_OK;
940 }
941
942 COMMAND_HANDLER(str9xpec_handle_flash_options_lvdthd_command)
943 {
944 struct str9xpec_flash_controller *str9xpec_info = NULL;
945
946 if (CMD_ARGC < 2)
947 {
948 command_print(CMD_CTX, "str9xpec options_lvdthd <bank> <2.4v | 2.7v>");
949 return ERROR_OK;
950 }
951
952 struct flash_bank *bank;
953 int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
954 if (ERROR_OK != retval)
955 return retval;
956
957 str9xpec_info = bank->driver_priv;
958
959 if (strcmp(CMD_ARGV[1], "2.7v") == 0)
960 {
961 buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDTHRESBIT, 1, 1);
962 }
963 else
964 {
965 buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDTHRESBIT, 1, 0);
966 }
967
968 return ERROR_OK;
969 }
970
971 COMMAND_HANDLER(str9xpec_handle_flash_options_lvdsel_command)
972 {
973 struct str9xpec_flash_controller *str9xpec_info = NULL;
974
975 if (CMD_ARGC < 2)
976 {
977 command_print(CMD_CTX, "str9xpec options_lvdsel <bank> <vdd | vdd_vddq>");
978 return ERROR_OK;
979 }
980
981 struct flash_bank *bank;
982 int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
983 if (ERROR_OK != retval)
984 return retval;
985
986 str9xpec_info = bank->driver_priv;
987
988 if (strcmp(CMD_ARGV[1], "vdd_vddq") == 0)
989 {
990 buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDSELBIT, 1, 1);
991 }
992 else
993 {
994 buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDSELBIT, 1, 0);
995 }
996
997 return ERROR_OK;
998 }
999
1000 COMMAND_HANDLER(str9xpec_handle_flash_options_lvdwarn_command)
1001 {
1002 struct str9xpec_flash_controller *str9xpec_info = NULL;
1003
1004 if (CMD_ARGC < 2)
1005 {
1006 command_print(CMD_CTX, "str9xpec options_lvdwarn <bank> <vdd | vdd_vddq>");
1007 return ERROR_OK;
1008 }
1009
1010 struct flash_bank *bank;
1011 int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
1012 if (ERROR_OK != retval)
1013 return retval;
1014
1015 str9xpec_info = bank->driver_priv;
1016
1017 if (strcmp(CMD_ARGV[1], "vdd_vddq") == 0)
1018 {
1019 buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDWARNBIT, 1, 1);
1020 }
1021 else
1022 {
1023 buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDWARNBIT, 1, 0);
1024 }
1025
1026 return ERROR_OK;
1027 }
1028
1029 COMMAND_HANDLER(str9xpec_handle_flash_lock_command)
1030 {
1031 uint8_t status;
1032
1033 if (CMD_ARGC < 1)
1034 {
1035 command_print(CMD_CTX, "str9xpec lock <bank>");
1036 return ERROR_OK;
1037 }
1038
1039 struct flash_bank *bank;
1040 int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
1041 if (ERROR_OK != retval)
1042 return retval;
1043
1044 status = str9xpec_lock_device(bank);
1045
1046 if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
1047 return ERROR_FLASH_OPERATION_FAILED;
1048
1049 return ERROR_OK;
1050 }
1051
1052 COMMAND_HANDLER(str9xpec_handle_flash_unlock_command)
1053 {
1054 uint8_t status;
1055
1056 if (CMD_ARGC < 1)
1057 {
1058 command_print(CMD_CTX, "str9xpec unlock <bank>");
1059 return ERROR_OK;
1060 }
1061
1062 struct flash_bank *bank;
1063 int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
1064 if (ERROR_OK != retval)
1065 return retval;
1066
1067 status = str9xpec_unlock_device(bank);
1068
1069 if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
1070 return ERROR_FLASH_OPERATION_FAILED;
1071
1072 command_print(CMD_CTX, "str9xpec unlocked.\n"
1073 "INFO: a reset or power cycle is required "
1074 "for the new settings to take effect.");
1075
1076 return ERROR_OK;
1077 }
1078
1079 COMMAND_HANDLER(str9xpec_handle_flash_enable_turbo_command)
1080 {
1081 struct jtag_tap *tap0;
1082 struct jtag_tap *tap1;
1083 struct jtag_tap *tap2;
1084 struct str9xpec_flash_controller *str9xpec_info = NULL;
1085
1086 if (CMD_ARGC < 1)
1087 {
1088 command_print(CMD_CTX, "str9xpec enable_turbo <bank>");
1089 return ERROR_OK;
1090 }
1091
1092 struct flash_bank *bank;
1093 int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
1094 if (ERROR_OK != retval)
1095 return retval;
1096
1097 str9xpec_info = bank->driver_priv;
1098
1099 tap0 = str9xpec_info->tap;
1100
1101 /* remove arm core from chain - enter turbo mode */
1102 tap1 = tap0->next_tap;
1103 if (tap1 == NULL)
1104 {
1105 /* things are *WRONG* */
1106 command_print(CMD_CTX,"**STR9FLASH** (tap1) invalid chain?");
1107 return ERROR_OK;
1108 }
1109 tap2 = tap1->next_tap;
1110 if (tap2 == NULL)
1111 {
1112 /* things are *WRONG* */
1113 command_print(CMD_CTX,"**STR9FLASH** (tap2) invalid chain?");
1114 return ERROR_OK;
1115 }
1116
1117 /* enable turbo mode - TURBO-PROG-ENABLE */
1118 str9xpec_set_instr(tap2, 0xD, TAP_IDLE);
1119 if ((retval = jtag_execute_queue()) != ERROR_OK)
1120 return retval;
1121
1122 /* modify scan chain - str9 core has been removed */
1123 tap1->enabled = 0;
1124
1125 return ERROR_OK;
1126 }
1127
1128 COMMAND_HANDLER(str9xpec_handle_flash_disable_turbo_command)
1129 {
1130 struct jtag_tap *tap;
1131 struct str9xpec_flash_controller *str9xpec_info = NULL;
1132
1133 if (CMD_ARGC < 1)
1134 {
1135 command_print(CMD_CTX, "str9xpec disable_turbo <bank>");
1136 return ERROR_OK;
1137 }
1138
1139 struct flash_bank *bank;
1140 int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
1141 if (ERROR_OK != retval)
1142 return retval;
1143
1144 str9xpec_info = bank->driver_priv;
1145 tap = str9xpec_info->tap;
1146
1147 if (tap == NULL)
1148 return ERROR_FAIL;
1149
1150 /* exit turbo mode via RESET */
1151 str9xpec_set_instr(tap, ISC_NOOP, TAP_IDLE);
1152 jtag_add_tlr();
1153 jtag_execute_queue();
1154
1155 /* restore previous scan chain */
1156 if (tap->next_tap) {
1157 tap->next_tap->enabled = 1;
1158 }
1159
1160 return ERROR_OK;
1161 }
1162
1163 static const struct command_registration str9xpec_config_command_handlers[] = {
1164 {
1165 .name = "enable_turbo",
1166 .handler = str9xpec_handle_flash_enable_turbo_command,
1167 .mode = COMMAND_EXEC,
1168 .help = "enable str9xpec turbo mode",
1169 },
1170 {
1171 .name = "disable_turbo",
1172 .handler = str9xpec_handle_flash_disable_turbo_command,
1173 .mode = COMMAND_EXEC,
1174 .help = "disable str9xpec turbo mode",
1175 },
1176 {
1177 .name = "options_cmap",
1178 .handler = str9xpec_handle_flash_options_cmap_command,
1179 .mode = COMMAND_EXEC,
1180 .help = "configure str9xpec boot sector",
1181 },
1182 {
1183 .name = "options_lvdthd",
1184 .handler = str9xpec_handle_flash_options_lvdthd_command,
1185 .mode = COMMAND_EXEC,
1186 .help = "configure str9xpec lvd threshold",
1187 },
1188 {
1189 .name = "options_lvdsel",
1190 .handler = str9xpec_handle_flash_options_lvdsel_command,
1191 .mode = COMMAND_EXEC,
1192 .help = "configure str9xpec lvd selection",
1193 },
1194 {
1195 .name = "options_lvdwarn",
1196 .handler = str9xpec_handle_flash_options_lvdwarn_command,
1197 .mode = COMMAND_EXEC,
1198 .help = "configure str9xpec lvd warning",
1199 },
1200 {
1201 .name = "options_read",
1202 .handler = str9xpec_handle_flash_options_read_command,
1203 .mode = COMMAND_EXEC,
1204 .help = "read str9xpec options",
1205 },
1206 {
1207 .name = "options_write",
1208 .handler = str9xpec_handle_flash_options_write_command,
1209 .mode = COMMAND_EXEC,
1210 .help = "write str9xpec options",
1211 },
1212 {
1213 .name = "lock",
1214 .handler = str9xpec_handle_flash_lock_command,
1215 .mode = COMMAND_EXEC,
1216 .help = "lock str9xpec device",
1217 },
1218 {
1219 .name = "unlock",
1220 .handler = str9xpec_handle_flash_unlock_command,
1221 .mode = COMMAND_EXEC,
1222 .help = "unlock str9xpec device",
1223 },
1224 {
1225 .name = "part_id",
1226 .handler = str9xpec_handle_part_id_command,
1227 .mode = COMMAND_EXEC,
1228 .help = "print part id of str9xpec flash bank <num>",
1229 },
1230 COMMAND_REGISTRATION_DONE
1231 };
1232
1233 static const struct command_registration str9xpec_command_handlers[] = {
1234 {
1235 .name = "str9xpec",
1236 .mode = COMMAND_ANY,
1237 .help = "str9xpec flash command group",
1238 .chain = str9xpec_config_command_handlers,
1239 },
1240 COMMAND_REGISTRATION_DONE
1241 };
1242
1243 struct flash_driver str9xpec_flash = {
1244 .name = "str9xpec",
1245 .commands = str9xpec_command_handlers,
1246 .flash_bank_command = str9xpec_flash_bank_command,
1247 .erase = str9xpec_erase,
1248 .protect = str9xpec_protect,
1249 .write = str9xpec_write,
1250 .read = default_flash_read,
1251 .probe = str9xpec_probe,
1252 .auto_probe = str9xpec_probe,
1253 .erase_check = str9xpec_erase_check,
1254 .protect_check = str9xpec_protect_check,
1255 .info = get_str9xpec_info,
1256 };