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