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