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