str9xpec: -Wshadow warning fixes
[fw/openocd] / 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 };