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