jtag: jtag_add_ir_scan() now takes a single field
[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 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, jtag_set_end_state(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, jtag_set_end_state(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, jtag_set_end_state(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, jtag_set_end_state(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, jtag_get_end_state());
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, jtag_get_end_state());
550
551         return ERROR_OK;
552 }
553
554 static int str9xpec_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, uint32_t count)
555 {
556         struct str9xpec_flash_controller *str9xpec_info = bank->driver_priv;
557         uint32_t dwords_remaining = (count / 8);
558         uint32_t bytes_remaining = (count & 0x00000007);
559         uint32_t bytes_written = 0;
560         uint8_t status;
561         uint32_t check_address = offset;
562         struct jtag_tap *tap;
563         struct scan_field field;
564         uint8_t *scanbuf;
565         int i;
566         int first_sector = 0;
567         int last_sector = 0;
568
569         tap = str9xpec_info->tap;
570
571         if (!str9xpec_info->isc_enable) {
572                 str9xpec_isc_enable(bank);
573         }
574
575         if (!str9xpec_info->isc_enable) {
576                 return ERROR_FLASH_OPERATION_FAILED;
577         }
578
579         if (offset & 0x7)
580         {
581                 LOG_WARNING("offset 0x%" PRIx32 " breaks required 8-byte alignment", offset);
582                 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
583         }
584
585         for (i = 0; i < bank->num_sectors; i++)
586         {
587                 uint32_t sec_start = bank->sectors[i].offset;
588                 uint32_t sec_end = sec_start + bank->sectors[i].size;
589
590                 /* check if destination falls within the current sector */
591                 if ((check_address >= sec_start) && (check_address < sec_end))
592                 {
593                         /* check if destination ends in the current sector */
594                         if (offset + count < sec_end)
595                                 check_address = offset + count;
596                         else
597                                 check_address = sec_end;
598                 }
599
600                 if ((offset >= sec_start) && (offset < sec_end)) {
601                         first_sector = i;
602                 }
603
604                 if ((offset + count >= sec_start) && (offset + count < sec_end)) {
605                         last_sector = i;
606                 }
607         }
608
609         if (check_address != offset + count)
610                 return ERROR_FLASH_DST_OUT_OF_BANK;
611
612         LOG_DEBUG("first_sector: %i, last_sector: %i", first_sector, last_sector);
613
614         scanbuf = calloc(DIV_ROUND_UP(64, 8), 1);
615
616         LOG_DEBUG("ISC_PROGRAM");
617
618         for (i = first_sector; i <= last_sector; i++)
619         {
620                 str9xpec_set_address(bank, str9xpec_info->sector_bits[i]);
621
622                 dwords_remaining = dwords_remaining < (bank->sectors[i].size/8) ? dwords_remaining : (bank->sectors[i].size/8);
623
624                 while (dwords_remaining > 0)
625                 {
626                         str9xpec_set_instr(tap, ISC_PROGRAM, TAP_IRPAUSE);
627
628                         field.num_bits = 64;
629                         field.out_value = (buffer + bytes_written);
630                         field.in_value = NULL;
631
632                         jtag_add_dr_scan(tap, 1, &field, jtag_set_end_state(TAP_IDLE));
633
634                         /* small delay before polling */
635                         jtag_add_sleep(50);
636
637                         str9xpec_set_instr(tap, ISC_NOOP, TAP_IRPAUSE);
638
639                         do {
640                                 field.num_bits = 8;
641                                 field.out_value = NULL;
642                                 field.in_value = scanbuf;
643
644                                 jtag_add_dr_scan(tap, 1, &field, jtag_get_end_state());
645                                 jtag_execute_queue();
646
647                                 status = buf_get_u32(scanbuf, 0, 8);
648
649                         } while (!(status & ISC_STATUS_BUSY));
650
651                         if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
652                                 return ERROR_FLASH_OPERATION_FAILED;
653
654                         /* if ((status & ISC_STATUS_INT_ERROR) != STR9XPEC_ISC_INTFAIL)
655                                 return ERROR_FLASH_OPERATION_FAILED; */
656
657                         dwords_remaining--;
658                         bytes_written += 8;
659                 }
660         }
661
662         if (bytes_remaining)
663         {
664                 uint8_t last_dword[8] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
665                 int i = 0;
666
667                 while (bytes_remaining > 0)
668                 {
669                         last_dword[i++] = *(buffer + bytes_written);
670                         bytes_remaining--;
671                         bytes_written++;
672                 }
673
674                 str9xpec_set_instr(tap, ISC_PROGRAM, TAP_IRPAUSE);
675
676                 field.num_bits = 64;
677                 field.out_value = last_dword;
678                 field.in_value = NULL;
679
680                 jtag_add_dr_scan(tap, 1, &field, jtag_set_end_state(TAP_IDLE));
681
682                 /* small delay before polling */
683                 jtag_add_sleep(50);
684
685                 str9xpec_set_instr(tap, ISC_NOOP, TAP_IRPAUSE);
686
687                 do {
688                         field.num_bits = 8;
689                         field.out_value = NULL;
690                         field.in_value = scanbuf;
691
692                         jtag_add_dr_scan(tap, 1, &field, jtag_get_end_state());
693                         jtag_execute_queue();
694
695                         status = buf_get_u32(scanbuf, 0, 8);
696
697                 } while (!(status & ISC_STATUS_BUSY));
698
699                 if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
700                         return ERROR_FLASH_OPERATION_FAILED;
701
702                 /* if ((status & ISC_STATUS_INT_ERROR) != STR9XPEC_ISC_INTFAIL)
703                         return ERROR_FLASH_OPERATION_FAILED; */
704         }
705
706         free(scanbuf);
707
708         str9xpec_isc_disable(bank);
709
710         return ERROR_OK;
711 }
712
713 static int str9xpec_probe(struct flash_bank *bank)
714 {
715         return ERROR_OK;
716 }
717
718 COMMAND_HANDLER(str9xpec_handle_part_id_command)
719 {
720         struct scan_field field;
721         uint8_t *buffer = NULL;
722         struct jtag_tap *tap;
723         uint32_t idcode;
724         struct str9xpec_flash_controller *str9xpec_info = NULL;
725
726         if (CMD_ARGC < 1)
727                 return ERROR_COMMAND_SYNTAX_ERROR;
728
729         struct flash_bank *bank;
730         int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
731         if (ERROR_OK != retval)
732                 return retval;
733
734         str9xpec_info = bank->driver_priv;
735         tap = str9xpec_info->tap;
736
737         buffer = calloc(DIV_ROUND_UP(32, 8), 1);
738
739         str9xpec_set_instr(tap, ISC_IDCODE, TAP_IRPAUSE);
740
741         field.num_bits = 32;
742         field.out_value = NULL;
743         field.in_value = buffer;
744
745         jtag_add_dr_scan(tap, 1, &field, jtag_set_end_state(TAP_IDLE));
746         jtag_execute_queue();
747
748         idcode = buf_get_u32(buffer, 0, 32);
749
750         command_print(CMD_CTX, "str9xpec part id: 0x%8.8" PRIx32 "", idcode);
751
752         free(buffer);
753
754         return ERROR_OK;
755 }
756
757 static int str9xpec_erase_check(struct flash_bank *bank)
758 {
759         return str9xpec_blank_check(bank, 0, bank->num_sectors - 1);
760 }
761
762 static int str9xpec_info(struct flash_bank *bank, char *buf, int buf_size)
763 {
764         snprintf(buf, buf_size, "str9xpec flash driver info");
765         return ERROR_OK;
766 }
767
768 COMMAND_HANDLER(str9xpec_handle_flash_options_read_command)
769 {
770         uint8_t status;
771         struct str9xpec_flash_controller *str9xpec_info = NULL;
772
773         if (CMD_ARGC < 1)
774         {
775                 command_print(CMD_CTX, "str9xpec options_read <bank>");
776                 return ERROR_OK;
777         }
778
779         struct flash_bank *bank;
780         int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
781         if (ERROR_OK != retval)
782                 return retval;
783
784         str9xpec_info = bank->driver_priv;
785
786         status = str9xpec_read_config(bank);
787
788         if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
789                 return ERROR_FLASH_OPERATION_FAILED;
790
791         /* boot bank */
792         if (buf_get_u32(str9xpec_info->options, STR9XPEC_OPT_CSMAPBIT, 1))
793                 command_print(CMD_CTX, "CS Map: bank1");
794         else
795                 command_print(CMD_CTX, "CS Map: bank0");
796
797         /* OTP lock */
798         if (buf_get_u32(str9xpec_info->options, STR9XPEC_OPT_OTPBIT, 1))
799                 command_print(CMD_CTX, "OTP Lock: OTP Locked");
800         else
801                 command_print(CMD_CTX, "OTP Lock: OTP Unlocked");
802
803         /* LVD Threshold */
804         if (buf_get_u32(str9xpec_info->options, STR9XPEC_OPT_LVDTHRESBIT, 1))
805                 command_print(CMD_CTX, "LVD Threshold: 2.7v");
806         else
807                 command_print(CMD_CTX, "LVD Threshold: 2.4v");
808
809         /* LVD reset warning */
810         if (buf_get_u32(str9xpec_info->options, STR9XPEC_OPT_LVDWARNBIT, 1))
811                 command_print(CMD_CTX, "LVD Reset Warning: VDD or VDDQ Inputs");
812         else
813                 command_print(CMD_CTX, "LVD Reset Warning: VDD Input Only");
814
815         /* LVD reset select */
816         if (buf_get_u32(str9xpec_info->options, STR9XPEC_OPT_LVDSELBIT, 1))
817                 command_print(CMD_CTX, "LVD Reset Selection: VDD or VDDQ Inputs");
818         else
819                 command_print(CMD_CTX, "LVD Reset Selection: VDD Input Only");
820
821         return ERROR_OK;
822 }
823
824 static int str9xpec_write_options(struct flash_bank *bank)
825 {
826         struct scan_field field;
827         uint8_t status;
828         struct jtag_tap *tap;
829         struct str9xpec_flash_controller *str9xpec_info = NULL;
830
831         str9xpec_info = bank->driver_priv;
832         tap = str9xpec_info->tap;
833
834         /* erase config options first */
835         status = str9xpec_erase_area(bank, 0xFE, 0xFE);
836
837         if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
838                 return status;
839
840         if (!str9xpec_info->isc_enable) {
841                 str9xpec_isc_enable(bank);
842         }
843
844         if (!str9xpec_info->isc_enable) {
845                 return ISC_STATUS_ERROR;
846         }
847
848         /* according to data 64th bit has to be set */
849         buf_set_u32(str9xpec_info->options, 63, 1, 1);
850
851         /* set option byte address */
852         str9xpec_set_address(bank, 0x50);
853
854         /* execute ISC_PROGRAM command */
855         str9xpec_set_instr(tap, ISC_PROGRAM, TAP_IRPAUSE);
856
857         field.num_bits = 64;
858         field.out_value = str9xpec_info->options;
859         field.in_value = NULL;
860
861         jtag_add_dr_scan(tap, 1, &field, jtag_set_end_state(TAP_IDLE));
862
863         /* small delay before polling */
864         jtag_add_sleep(50);
865
866         str9xpec_set_instr(tap, ISC_NOOP, TAP_IRPAUSE);
867
868         do {
869                 field.num_bits = 8;
870                 field.out_value = NULL;
871                 field.in_value = &status;
872
873                 jtag_add_dr_scan(tap, 1, &field, jtag_get_end_state());
874                 jtag_execute_queue();
875
876         } while (!(status & ISC_STATUS_BUSY));
877
878         str9xpec_isc_disable(bank);
879
880         return status;
881 }
882
883 COMMAND_HANDLER(str9xpec_handle_flash_options_write_command)
884 {
885         uint8_t status;
886
887         if (CMD_ARGC < 1)
888         {
889                 command_print(CMD_CTX, "str9xpec options_write <bank>");
890                 return ERROR_OK;
891         }
892
893         struct flash_bank *bank;
894         int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
895         if (ERROR_OK != retval)
896                 return retval;
897
898         status = str9xpec_write_options(bank);
899
900         if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
901                 return ERROR_FLASH_OPERATION_FAILED;
902
903         command_print(CMD_CTX, "str9xpec write options complete.\n"
904                         "INFO: a reset or power cycle is required "
905                         "for the new settings to take effect.");
906
907         return ERROR_OK;
908 }
909
910 COMMAND_HANDLER(str9xpec_handle_flash_options_cmap_command)
911 {
912         struct str9xpec_flash_controller *str9xpec_info = NULL;
913
914         if (CMD_ARGC < 2)
915         {
916                 command_print(CMD_CTX, "str9xpec options_cmap <bank> <bank0 | bank1>");
917                 return ERROR_OK;
918         }
919
920         struct flash_bank *bank;
921         int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
922         if (ERROR_OK != retval)
923                 return retval;
924
925         str9xpec_info = bank->driver_priv;
926
927         if (strcmp(CMD_ARGV[1], "bank1") == 0)
928         {
929                 buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_CSMAPBIT, 1, 1);
930         }
931         else
932         {
933                 buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_CSMAPBIT, 1, 0);
934         }
935
936         return ERROR_OK;
937 }
938
939 COMMAND_HANDLER(str9xpec_handle_flash_options_lvdthd_command)
940 {
941         struct str9xpec_flash_controller *str9xpec_info = NULL;
942
943         if (CMD_ARGC < 2)
944         {
945                 command_print(CMD_CTX, "str9xpec options_lvdthd <bank> <2.4v | 2.7v>");
946                 return ERROR_OK;
947         }
948
949         struct flash_bank *bank;
950         int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
951         if (ERROR_OK != retval)
952                 return retval;
953
954         str9xpec_info = bank->driver_priv;
955
956         if (strcmp(CMD_ARGV[1], "2.7v") == 0)
957         {
958                 buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDTHRESBIT, 1, 1);
959         }
960         else
961         {
962                 buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDTHRESBIT, 1, 0);
963         }
964
965         return ERROR_OK;
966 }
967
968 COMMAND_HANDLER(str9xpec_handle_flash_options_lvdsel_command)
969 {
970         struct str9xpec_flash_controller *str9xpec_info = NULL;
971
972         if (CMD_ARGC < 2)
973         {
974                 command_print(CMD_CTX, "str9xpec options_lvdsel <bank> <vdd | vdd_vddq>");
975                 return ERROR_OK;
976         }
977
978         struct flash_bank *bank;
979         int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
980         if (ERROR_OK != retval)
981                 return retval;
982
983         str9xpec_info = bank->driver_priv;
984
985         if (strcmp(CMD_ARGV[1], "vdd_vddq") == 0)
986         {
987                 buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDSELBIT, 1, 1);
988         }
989         else
990         {
991                 buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDSELBIT, 1, 0);
992         }
993
994         return ERROR_OK;
995 }
996
997 COMMAND_HANDLER(str9xpec_handle_flash_options_lvdwarn_command)
998 {
999         struct str9xpec_flash_controller *str9xpec_info = NULL;
1000
1001         if (CMD_ARGC < 2)
1002         {
1003                 command_print(CMD_CTX, "str9xpec options_lvdwarn <bank> <vdd | vdd_vddq>");
1004                 return ERROR_OK;
1005         }
1006
1007         struct flash_bank *bank;
1008         int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
1009         if (ERROR_OK != retval)
1010                 return retval;
1011
1012         str9xpec_info = bank->driver_priv;
1013
1014         if (strcmp(CMD_ARGV[1], "vdd_vddq") == 0)
1015         {
1016                 buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDWARNBIT, 1, 1);
1017         }
1018         else
1019         {
1020                 buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDWARNBIT, 1, 0);
1021         }
1022
1023         return ERROR_OK;
1024 }
1025
1026 COMMAND_HANDLER(str9xpec_handle_flash_lock_command)
1027 {
1028         uint8_t status;
1029
1030         if (CMD_ARGC < 1)
1031         {
1032                 command_print(CMD_CTX, "str9xpec lock <bank>");
1033                 return ERROR_OK;
1034         }
1035
1036         struct flash_bank *bank;
1037         int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
1038         if (ERROR_OK != retval)
1039                 return retval;
1040
1041         status = str9xpec_lock_device(bank);
1042
1043         if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
1044                 return ERROR_FLASH_OPERATION_FAILED;
1045
1046         return ERROR_OK;
1047 }
1048
1049 COMMAND_HANDLER(str9xpec_handle_flash_unlock_command)
1050 {
1051         uint8_t status;
1052
1053         if (CMD_ARGC < 1)
1054         {
1055                 command_print(CMD_CTX, "str9xpec unlock <bank>");
1056                 return ERROR_OK;
1057         }
1058
1059         struct flash_bank *bank;
1060         int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
1061         if (ERROR_OK != retval)
1062                 return retval;
1063
1064         status = str9xpec_unlock_device(bank);
1065
1066         if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
1067                 return ERROR_FLASH_OPERATION_FAILED;
1068
1069         command_print(CMD_CTX, "str9xpec unlocked.\n"
1070                         "INFO: a reset or power cycle is required "
1071                         "for the new settings to take effect.");
1072
1073         return ERROR_OK;
1074 }
1075
1076 COMMAND_HANDLER(str9xpec_handle_flash_enable_turbo_command)
1077 {
1078         struct jtag_tap *tap0;
1079         struct jtag_tap *tap1;
1080         struct jtag_tap *tap2;
1081         struct str9xpec_flash_controller *str9xpec_info = NULL;
1082
1083         if (CMD_ARGC < 1)
1084         {
1085                 command_print(CMD_CTX, "str9xpec enable_turbo <bank>");
1086                 return ERROR_OK;
1087         }
1088
1089         struct flash_bank *bank;
1090         int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
1091         if (ERROR_OK != retval)
1092                 return retval;
1093
1094         str9xpec_info = bank->driver_priv;
1095
1096         tap0 = str9xpec_info->tap;
1097
1098         /* remove arm core from chain - enter turbo mode */
1099         tap1 = tap0->next_tap;
1100         if (tap1 == NULL)
1101         {
1102                 /* things are *WRONG* */
1103                 command_print(CMD_CTX,"**STR9FLASH** (tap1) invalid chain?");
1104                 return ERROR_OK;
1105         }
1106         tap2 = tap1->next_tap;
1107         if (tap2 == NULL)
1108         {
1109                 /* things are *WRONG* */
1110                 command_print(CMD_CTX,"**STR9FLASH** (tap2) invalid chain?");
1111                 return ERROR_OK;
1112         }
1113
1114         /* enable turbo mode - TURBO-PROG-ENABLE */
1115         str9xpec_set_instr(tap2, 0xD, TAP_IDLE);
1116         if ((retval = jtag_execute_queue()) != ERROR_OK)
1117                 return retval;
1118
1119         /* modify scan chain - str9 core has been removed */
1120         tap1->enabled = 0;
1121
1122         return ERROR_OK;
1123 }
1124
1125 COMMAND_HANDLER(str9xpec_handle_flash_disable_turbo_command)
1126 {
1127         struct jtag_tap *tap;
1128         struct str9xpec_flash_controller *str9xpec_info = NULL;
1129
1130         if (CMD_ARGC < 1)
1131         {
1132                 command_print(CMD_CTX, "str9xpec disable_turbo <bank>");
1133                 return ERROR_OK;
1134         }
1135
1136         struct flash_bank *bank;
1137         int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
1138         if (ERROR_OK != retval)
1139                 return retval;
1140
1141         str9xpec_info = bank->driver_priv;
1142         tap = str9xpec_info->tap;
1143
1144         if (tap == NULL)
1145                 return ERROR_FAIL;
1146
1147         /* exit turbo mode via RESET */
1148         str9xpec_set_instr(tap, ISC_NOOP, TAP_IDLE);
1149         jtag_add_tlr();
1150         jtag_execute_queue();
1151
1152         /* restore previous scan chain */
1153         if (tap->next_tap) {
1154                 tap->next_tap->enabled = 1;
1155         }
1156
1157         return ERROR_OK;
1158 }
1159
1160 static const struct command_registration str9xpec_config_command_handlers[] = {
1161         {
1162                 .name = "enable_turbo",
1163                 .handler = str9xpec_handle_flash_enable_turbo_command,
1164                 .mode = COMMAND_EXEC,
1165                 .help = "enable str9xpec turbo mode",
1166         },
1167         {
1168                 .name = "disable_turbo",
1169                 .handler = str9xpec_handle_flash_disable_turbo_command,
1170                 .mode = COMMAND_EXEC,
1171                 .help = "disable str9xpec turbo mode",
1172         },
1173         {
1174                 .name = "options_cmap",
1175                 .handler = str9xpec_handle_flash_options_cmap_command,
1176                 .mode = COMMAND_EXEC,
1177                 .help = "configure str9xpec boot sector",
1178         },
1179         {
1180                 .name = "options_lvdthd",
1181                 .handler = str9xpec_handle_flash_options_lvdthd_command,
1182                 .mode = COMMAND_EXEC,
1183                 .help = "configure str9xpec lvd threshold",
1184         },
1185         {
1186                 .name = "options_lvdsel",
1187                 .handler = str9xpec_handle_flash_options_lvdsel_command,
1188                 .mode = COMMAND_EXEC,
1189                 .help = "configure str9xpec lvd selection",
1190         },
1191         {
1192                 .name = "options_lvdwarn",
1193                 .handler = str9xpec_handle_flash_options_lvdwarn_command,
1194                 .mode = COMMAND_EXEC,
1195                 .help = "configure str9xpec lvd warning",
1196         },
1197         {
1198                 .name = "options_read",
1199                 .handler = str9xpec_handle_flash_options_read_command,
1200                 .mode = COMMAND_EXEC,
1201                 .help = "read str9xpec options",
1202         },
1203         {
1204                 .name = "options_write",
1205                 .handler = str9xpec_handle_flash_options_write_command,
1206                 .mode = COMMAND_EXEC,
1207                 .help = "write str9xpec options",
1208         },
1209         {
1210                 .name = "lock",
1211                 .handler = str9xpec_handle_flash_lock_command,
1212                 .mode = COMMAND_EXEC,
1213                 .help = "lock str9xpec device",
1214         },
1215         {
1216                 .name = "unlock",
1217                 .handler = str9xpec_handle_flash_unlock_command,
1218                 .mode = COMMAND_EXEC,
1219                 .help = "unlock str9xpec device",
1220         },
1221         {
1222                 .name = "part_id",
1223                 .handler = str9xpec_handle_part_id_command,
1224                 .mode = COMMAND_EXEC,
1225                 .help = "print part id of str9xpec flash bank <num>",
1226         },
1227         COMMAND_REGISTRATION_DONE
1228 };
1229 static const struct command_registration str9xpec_command_handlers[] = {
1230         {
1231                 .name = "str9xpec",
1232                 .mode = COMMAND_ANY,
1233                 .help = "str9xpec flash command group",
1234                 .chain = str9xpec_config_command_handlers,
1235         },
1236         COMMAND_REGISTRATION_DONE
1237 };
1238
1239 struct flash_driver str9xpec_flash = {
1240         .name = "str9xpec",
1241         .commands = str9xpec_command_handlers,
1242         .flash_bank_command = str9xpec_flash_bank_command,
1243         .erase = str9xpec_erase,
1244         .protect = str9xpec_protect,
1245         .write = str9xpec_write,
1246         .probe = str9xpec_probe,
1247         .auto_probe = str9xpec_probe,
1248         .erase_check = str9xpec_erase_check,
1249         .protect_check = str9xpec_protect_check,
1250         .info = str9xpec_info,
1251 };