src: add loader src description
[fw/openocd] / src / flash / nor / str7x.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  *   Copyright (C) 2010 Ã˜yvind Harboe                                      *
9  *   oyvind.harboe@zylin.com                                               *
10  *                                                                         *
11  *   This program is free software; you can redistribute it and/or modify  *
12  *   it under the terms of the GNU General Public License as published by  *
13  *   the Free Software Foundation; either version 2 of the License, or     *
14  *   (at your option) any later version.                                   *
15  *                                                                         *
16  *   This program is distributed in the hope that it will be useful,       *
17  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
18  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
19  *   GNU General Public License for more details.                          *
20  *                                                                         *
21  *   You should have received a copy of the GNU General Public License     *
22  *   along with this program; if not, write to the                         *
23  *   Free Software Foundation, Inc.,                                       *
24  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
25  ***************************************************************************/
26 #ifdef HAVE_CONFIG_H
27 #include "config.h"
28 #endif
29
30 #include "imp.h"
31 #include "str7x.h"
32 #include <target/arm.h>
33 #include <helper/binarybuffer.h>
34 #include <target/algorithm.h>
35
36
37 static struct str7x_mem_layout mem_layout_str7bank0[] = {
38         {0x00000000, 0x02000, 0x01},
39         {0x00002000, 0x02000, 0x02},
40         {0x00004000, 0x02000, 0x04},
41         {0x00006000, 0x02000, 0x08},
42         {0x00008000, 0x08000, 0x10},
43         {0x00010000, 0x10000, 0x20},
44         {0x00020000, 0x10000, 0x40},
45         {0x00030000, 0x10000, 0x80}
46 };
47
48 static struct str7x_mem_layout mem_layout_str7bank1[] = {
49         {0x00000000, 0x02000, 0x10000},
50         {0x00002000, 0x02000, 0x20000}
51 };
52
53 static int str7x_get_flash_adr(struct flash_bank *bank, uint32_t reg)
54 {
55         struct str7x_flash_bank *str7x_info = bank->driver_priv;
56         return (str7x_info->register_base | reg);
57 }
58
59 static int str7x_build_block_list(struct flash_bank *bank)
60 {
61         struct str7x_flash_bank *str7x_info = bank->driver_priv;
62
63         int i;
64         int num_sectors;
65         int b0_sectors = 0, b1_sectors = 0;
66
67         switch (bank->size)
68         {
69                 case 16 * 1024:
70                         b1_sectors = 2;
71                         break;
72                 case 64 * 1024:
73                         b0_sectors = 5;
74                         break;
75                 case 128 * 1024:
76                         b0_sectors = 6;
77                         break;
78                 case 256 * 1024:
79                         b0_sectors = 8;
80                         break;
81                 default:
82                         LOG_ERROR("BUG: unknown bank->size encountered");
83                         exit(-1);
84         }
85
86         num_sectors = b0_sectors + b1_sectors;
87
88         bank->num_sectors = num_sectors;
89         bank->sectors = malloc(sizeof(struct flash_sector) * num_sectors);
90         str7x_info->sector_bits = malloc(sizeof(uint32_t) * num_sectors);
91
92         num_sectors = 0;
93
94         for (i = 0; i < b0_sectors; i++)
95         {
96                 bank->sectors[num_sectors].offset = mem_layout_str7bank0[i].sector_start;
97                 bank->sectors[num_sectors].size = mem_layout_str7bank0[i].sector_size;
98                 bank->sectors[num_sectors].is_erased = -1;
99                 /* the reset_init handler marks all the sectors unprotected,
100                  * matching hardware after reset; keep the driver in sync
101                  */
102                 bank->sectors[num_sectors].is_protected = 0;
103                 str7x_info->sector_bits[num_sectors++] = mem_layout_str7bank0[i].sector_bit;
104         }
105
106         for (i = 0; i < b1_sectors; i++)
107         {
108                 bank->sectors[num_sectors].offset = mem_layout_str7bank1[i].sector_start;
109                 bank->sectors[num_sectors].size = mem_layout_str7bank1[i].sector_size;
110                 bank->sectors[num_sectors].is_erased = -1;
111                 /* the reset_init handler marks all the sectors unprotected,
112                  * matching hardware after reset; keep the driver in sync
113                  */
114                 bank->sectors[num_sectors].is_protected = 0;
115                 str7x_info->sector_bits[num_sectors++] = mem_layout_str7bank1[i].sector_bit;
116         }
117
118         return ERROR_OK;
119 }
120
121 /* flash bank str7x <base> <size> 0 0 <target#> <str71_variant>
122  */
123 FLASH_BANK_COMMAND_HANDLER(str7x_flash_bank_command)
124 {
125         struct str7x_flash_bank *str7x_info;
126
127         if (CMD_ARGC < 7)
128         {
129                 LOG_WARNING("incomplete flash_bank str7x configuration");
130                 return ERROR_FLASH_BANK_INVALID;
131         }
132
133         str7x_info = malloc(sizeof(struct str7x_flash_bank));
134         bank->driver_priv = str7x_info;
135
136         /* set default bits for str71x flash */
137         str7x_info->busy_bits = (FLASH_LOCK | FLASH_BSYA1 | FLASH_BSYA0);
138         str7x_info->disable_bit = (1 << 1);
139
140         if (strcmp(CMD_ARGV[6], "STR71x") == 0)
141         {
142                 str7x_info->register_base = 0x40100000;
143         }
144         else if (strcmp(CMD_ARGV[6], "STR73x") == 0)
145         {
146                 str7x_info->register_base = 0x80100000;
147                 str7x_info->busy_bits = (FLASH_LOCK | FLASH_BSYA0);
148         }
149         else if (strcmp(CMD_ARGV[6], "STR75x") == 0)
150         {
151                 str7x_info->register_base = 0x20100000;
152                 str7x_info->disable_bit = (1 << 0);
153         }
154         else
155         {
156                 LOG_ERROR("unknown STR7x variant: '%s'", CMD_ARGV[6]);
157                 free(str7x_info);
158                 return ERROR_FLASH_BANK_INVALID;
159         }
160
161         str7x_build_block_list(bank);
162
163         str7x_info->write_algorithm = NULL;
164
165         return ERROR_OK;
166 }
167
168 /* wait for flash to become idle or report errors.
169
170    FIX!!! what's the maximum timeout??? The documentation doesn't
171    state any maximum time.... by inspection it seems > 1000ms is to be
172    expected.
173
174    10000ms is long enough that it should cover anything, yet not
175    quite be equivalent to an infinite loop.
176
177  */
178 static int str7x_waitbusy(struct flash_bank *bank)
179 {
180         int err;
181         int i;
182         struct target *target = bank->target;
183         struct str7x_flash_bank *str7x_info = bank->driver_priv;
184
185         for (i = 0 ; i < 10000; i++)
186         {
187                 uint32_t retval;
188                 err = target_read_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), &retval);
189                 if (err != ERROR_OK)
190                         return err;
191
192                 if ((retval & str7x_info->busy_bits) == 0)
193                         return ERROR_OK;
194
195                 alive_sleep(1);
196         }
197         LOG_ERROR("Timed out waiting for str7x flash");
198         return ERROR_FAIL;
199 }
200
201
202 static int str7x_result(struct flash_bank *bank)
203 {
204         struct target *target = bank->target;
205         uint32_t retval;
206
207         int err;
208         err = target_read_u32(target, str7x_get_flash_adr(bank, FLASH_ER), &retval);
209         if (err != ERROR_OK)
210                 return err;
211
212         if (retval & FLASH_WPF)
213         {
214                 LOG_ERROR("str7x hw write protection set");
215                 err = ERROR_FAIL;
216         }
217         if (retval & FLASH_RESER)
218         {
219                 LOG_ERROR("str7x suspended program erase not resumed");
220                 err = ERROR_FAIL;
221         }
222         if (retval & FLASH_10ER)
223         {
224                 LOG_ERROR("str7x trying to set bit to 1 when it is already 0");
225                 err = ERROR_FAIL;
226         }
227         if (retval & FLASH_PGER)
228         {
229                 LOG_ERROR("str7x program error");
230                 err = ERROR_FAIL;
231         }
232         if (retval & FLASH_ERER)
233         {
234                 LOG_ERROR("str7x erase error");
235                 err = ERROR_FAIL;
236         }
237         if (err == ERROR_OK)
238         {
239                 if (retval & FLASH_ERR)
240                 {
241                         /* this should always be set if one of the others are set... */
242                         LOG_ERROR("str7x write operation failed / bad setup");
243                         err = ERROR_FAIL;
244                 }
245         }
246         if (err != ERROR_OK)
247         {
248                 LOG_ERROR("FLASH_ER register contents: 0x%" PRIx32, retval);
249         }
250
251         return retval;
252 }
253
254 static int str7x_protect_check(struct flash_bank *bank)
255 {
256         struct str7x_flash_bank *str7x_info = bank->driver_priv;
257         struct target *target = bank->target;
258
259         int i;
260         uint32_t retval;
261
262         if (bank->target->state != TARGET_HALTED)
263         {
264                 LOG_ERROR("Target not halted");
265                 return ERROR_TARGET_NOT_HALTED;
266         }
267
268         target_read_u32(target, str7x_get_flash_adr(bank, FLASH_NVWPAR), &retval);
269
270         for (i = 0; i < bank->num_sectors; i++)
271         {
272                 if (retval & str7x_info->sector_bits[i])
273                         bank->sectors[i].is_protected = 0;
274                 else
275                         bank->sectors[i].is_protected = 1;
276         }
277
278         return ERROR_OK;
279 }
280
281 static int str7x_erase(struct flash_bank *bank, int first, int last)
282 {
283         struct str7x_flash_bank *str7x_info = bank->driver_priv;
284         struct target *target = bank->target;
285
286         int i;
287         uint32_t cmd;
288         uint32_t sectors = 0;
289         int err;
290
291         if (bank->target->state != TARGET_HALTED)
292         {
293                 LOG_ERROR("Target not halted");
294                 return ERROR_TARGET_NOT_HALTED;
295         }
296
297         for (i = first; i <= last; i++)
298         {
299                 sectors |= str7x_info->sector_bits[i];
300         }
301
302         LOG_DEBUG("sectors: 0x%" PRIx32 "", sectors);
303
304         /* clear FLASH_ER register */
305         err = target_write_u32(target, str7x_get_flash_adr(bank, FLASH_ER), 0x0);
306         if (err != ERROR_OK)
307                 return err;
308
309         cmd = FLASH_SER;
310         err = target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), cmd);
311         if (err != ERROR_OK)
312                 return err;
313
314         cmd = sectors;
315         err = target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR1), cmd);
316         if (err != ERROR_OK)
317                 return err;
318
319         cmd = FLASH_SER | FLASH_WMS;
320         err = target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), cmd);
321         if (err != ERROR_OK)
322                 return err;
323
324         err = str7x_waitbusy(bank);
325         if (err != ERROR_OK)
326                 return err;
327
328         err = str7x_result(bank);
329         if (err != ERROR_OK)
330                 return err;
331
332         for (i = first; i <= last; i++)
333                 bank->sectors[i].is_erased = 1;
334
335         return ERROR_OK;
336 }
337
338 static int str7x_protect(struct flash_bank *bank, int set, int first, int last)
339 {
340         struct str7x_flash_bank *str7x_info = bank->driver_priv;
341         struct target *target = bank->target;
342         int i;
343         uint32_t cmd;
344         uint32_t protect_blocks;
345
346         if (bank->target->state != TARGET_HALTED)
347         {
348                 LOG_ERROR("Target not halted");
349                 return ERROR_TARGET_NOT_HALTED;
350         }
351
352         protect_blocks = 0xFFFFFFFF;
353
354         if (set)
355         {
356                 for (i = first; i <= last; i++)
357                         protect_blocks &= ~(str7x_info->sector_bits[i]);
358         }
359
360         /* clear FLASH_ER register */
361         int err;
362         err = target_write_u32(target, str7x_get_flash_adr(bank, FLASH_ER), 0x0);
363         if (err != ERROR_OK)
364                 return err;
365
366         cmd = FLASH_SPR;
367         err = target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), cmd);
368         if (err != ERROR_OK)
369                 return err;
370
371         cmd = str7x_get_flash_adr(bank, FLASH_NVWPAR);
372         err = target_write_u32(target, str7x_get_flash_adr(bank, FLASH_AR), cmd);
373         if (err != ERROR_OK)
374                 return err;
375
376         cmd = protect_blocks;
377         err = target_write_u32(target, str7x_get_flash_adr(bank, FLASH_DR0), cmd);
378         if (err != ERROR_OK)
379                 return err;
380
381         cmd = FLASH_SPR | FLASH_WMS;
382         err = target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), cmd);
383         if (err != ERROR_OK)
384                 return err;
385
386         err = str7x_waitbusy(bank);
387         if (err != ERROR_OK)
388                 return err;
389
390         err = str7x_result(bank);
391         if (err != ERROR_OK)
392                 return err;
393
394         return ERROR_OK;
395 }
396
397 static int str7x_write_block(struct flash_bank *bank, uint8_t *buffer,
398                 uint32_t offset, uint32_t count)
399 {
400         struct str7x_flash_bank *str7x_info = bank->driver_priv;
401         struct target *target = bank->target;
402         uint32_t buffer_size = 32768;
403         struct working_area *source;
404         uint32_t address = bank->base + offset;
405         struct reg_param reg_params[6];
406         struct arm_algorithm armv4_5_info;
407         int retval = ERROR_OK;
408
409         /* see contib/loaders/flash/str7x.s for src */
410
411         static const uint32_t str7x_flash_write_code[] = {
412                                         /* write:                               */
413                 0xe3a04201, /*  mov r4, #0x10000000     */
414                 0xe5824000, /*  str r4, [r2, #0x0]      */
415                 0xe5821010, /*  str r1, [r2, #0x10]     */
416                 0xe4904004, /*  ldr r4, [r0], #4        */
417                 0xe5824008, /*  str r4, [r2, #0x8]      */
418                 0xe4904004, /*  ldr r4, [r0], #4        */
419                 0xe582400c, /*  str r4, [r2, #0xc]      */
420                 0xe3a04209, /*  mov r4, #0x90000000     */
421                 0xe5824000, /*  str r4, [r2, #0x0]      */
422                             /* busy:                            */
423                 0xe5924000, /*  ldr r4, [r2, #0x0]      */
424                 0xe1140005,     /*      tst r4, r5                      */
425                 0x1afffffc, /*  bne busy                        */
426                 0xe5924014, /*  ldr r4, [r2, #0x14]     */
427                 0xe31400ff, /*  tst r4, #0xff           */
428                 0x03140c01, /*  tsteq r4, #0x100        */
429                 0x1a000002, /*  bne exit                        */
430                 0xe2811008, /*  add r1, r1, #0x8        */
431                 0xe2533001, /*  subs r3, r3, #1         */
432                 0x1affffec, /*  bne write                       */
433                                         /* exit:                                */
434                 0xeafffffe, /*  b exit                          */
435         };
436
437         /* flash write code */
438         if (target_alloc_working_area_try(target, sizeof(str7x_flash_write_code),
439                         &str7x_info->write_algorithm) != ERROR_OK)
440         {
441                 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
442         };
443
444         target_write_buffer(target, str7x_info->write_algorithm->address,
445                         sizeof(str7x_flash_write_code),
446                         (uint8_t*)str7x_flash_write_code);
447
448         /* memory buffer */
449         while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK)
450         {
451                 buffer_size /= 2;
452                 if (buffer_size <= 256)
453                 {
454                         /* if we already allocated the writing code, but failed to get a
455                          * buffer, free the algorithm */
456                         if (str7x_info->write_algorithm)
457                                 target_free_working_area(target, str7x_info->write_algorithm);
458
459                         LOG_WARNING("no large enough working area available, can't do block memory writes");
460                         return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
461                 }
462         }
463
464         armv4_5_info.common_magic = ARM_COMMON_MAGIC;
465         armv4_5_info.core_mode = ARM_MODE_SVC;
466         armv4_5_info.core_state = ARM_STATE_ARM;
467
468         init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);
469         init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
470         init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT);
471         init_reg_param(&reg_params[3], "r3", 32, PARAM_OUT);
472         init_reg_param(&reg_params[4], "r4", 32, PARAM_IN);
473         init_reg_param(&reg_params[5], "r5", 32, PARAM_OUT);
474
475         while (count > 0)
476         {
477                 uint32_t thisrun_count = (count > (buffer_size / 8)) ? (buffer_size / 8) : count;
478
479                 target_write_buffer(target, source->address, thisrun_count * 8, buffer);
480
481                 buf_set_u32(reg_params[0].value, 0, 32, source->address);
482                 buf_set_u32(reg_params[1].value, 0, 32, address);
483                 buf_set_u32(reg_params[2].value, 0, 32, str7x_get_flash_adr(bank, FLASH_CR0));
484                 buf_set_u32(reg_params[3].value, 0, 32, thisrun_count);
485                 buf_set_u32(reg_params[5].value, 0, 32, str7x_info->busy_bits);
486
487                 if ((retval = target_run_algorithm(target, 0, NULL, 6, reg_params,
488                                 str7x_info->write_algorithm->address,
489                                 str7x_info->write_algorithm->address + (sizeof(str7x_flash_write_code) - 4),
490                                 10000, &armv4_5_info)) != ERROR_OK)
491                 {
492                         break;
493                 }
494
495                 if (buf_get_u32(reg_params[4].value, 0, 32) != 0x00)
496                 {
497                         retval = str7x_result(bank);
498                         break;
499                 }
500
501                 buffer += thisrun_count * 8;
502                 address += thisrun_count * 8;
503                 count -= thisrun_count;
504         }
505
506         target_free_working_area(target, source);
507         target_free_working_area(target, str7x_info->write_algorithm);
508
509         destroy_reg_param(&reg_params[0]);
510         destroy_reg_param(&reg_params[1]);
511         destroy_reg_param(&reg_params[2]);
512         destroy_reg_param(&reg_params[3]);
513         destroy_reg_param(&reg_params[4]);
514         destroy_reg_param(&reg_params[5]);
515
516         return retval;
517 }
518
519 static int str7x_write(struct flash_bank *bank, uint8_t *buffer,
520                 uint32_t offset, uint32_t count)
521 {
522         struct target *target = bank->target;
523         uint32_t dwords_remaining = (count / 8);
524         uint32_t bytes_remaining = (count & 0x00000007);
525         uint32_t address = bank->base + offset;
526         uint32_t bytes_written = 0;
527         uint32_t cmd;
528         int retval;
529         uint32_t check_address = offset;
530         int i;
531
532         if (bank->target->state != TARGET_HALTED)
533         {
534                 LOG_ERROR("Target not halted");
535                 return ERROR_TARGET_NOT_HALTED;
536         }
537
538         if (offset & 0x7)
539         {
540                 LOG_WARNING("offset 0x%" PRIx32 " breaks required 8-byte alignment", offset);
541                 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
542         }
543
544         for (i = 0; i < bank->num_sectors; i++)
545         {
546                 uint32_t sec_start = bank->sectors[i].offset;
547                 uint32_t sec_end = sec_start + bank->sectors[i].size;
548
549                 /* check if destination falls within the current sector */
550                 if ((check_address >= sec_start) && (check_address < sec_end))
551                 {
552                         /* check if destination ends in the current sector */
553                         if (offset + count < sec_end)
554                                 check_address = offset + count;
555                         else
556                                 check_address = sec_end;
557                 }
558         }
559
560         if (check_address != offset + count)
561                 return ERROR_FLASH_DST_OUT_OF_BANK;
562
563         /* clear FLASH_ER register */
564         target_write_u32(target, str7x_get_flash_adr(bank, FLASH_ER), 0x0);
565
566         /* multiple dwords (8-byte) to be programmed? */
567         if (dwords_remaining > 0)
568         {
569                 /* try using a block write */
570                 if ((retval = str7x_write_block(bank, buffer, offset,
571                                 dwords_remaining)) != ERROR_OK)
572                 {
573                         if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE)
574                         {
575                                 /* if block write failed (no sufficient working area),
576                                  * we use normal (slow) single dword accesses */
577                                 LOG_WARNING("couldn't use block writes, falling back to single memory accesses");
578                         } else
579                         {
580                                 return retval;
581                         }
582                 }
583                 else
584                 {
585                         buffer += dwords_remaining * 8;
586                         address += dwords_remaining * 8;
587                         dwords_remaining = 0;
588                 }
589         }
590
591         while (dwords_remaining > 0)
592         {
593                 /* command */
594                 cmd = FLASH_DWPG;
595                 target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), cmd);
596
597                 /* address */
598                 target_write_u32(target, str7x_get_flash_adr(bank, FLASH_AR), address);
599
600                 /* data word 1 */
601                 target_write_memory(target, str7x_get_flash_adr(bank, FLASH_DR0),
602                                 4, 1, buffer + bytes_written);
603                 bytes_written += 4;
604
605                 /* data word 2 */
606                 target_write_memory(target, str7x_get_flash_adr(bank, FLASH_DR1),
607                                 4, 1, buffer + bytes_written);
608                 bytes_written += 4;
609
610                 /* start programming cycle */
611                 cmd = FLASH_DWPG | FLASH_WMS;
612                 target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), cmd);
613
614                 int err;
615                 err = str7x_waitbusy(bank);
616                 if (err != ERROR_OK)
617                         return err;
618
619                 err = str7x_result(bank);
620                 if (err != ERROR_OK)
621                         return err;
622
623                 dwords_remaining--;
624                 address += 8;
625         }
626
627         if (bytes_remaining)
628         {
629                 uint8_t last_dword[8] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
630                 i = 0;
631
632                 while (bytes_remaining > 0)
633                 {
634                         last_dword[i++] = *(buffer + bytes_written);
635                         bytes_remaining--;
636                         bytes_written++;
637                 }
638
639                 /* command */
640                 cmd = FLASH_DWPG;
641                 target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), cmd);
642
643                 /* address */
644                 target_write_u32(target, str7x_get_flash_adr(bank, FLASH_AR), address);
645
646                 /* data word 1 */
647                 target_write_memory(target, str7x_get_flash_adr(bank, FLASH_DR0),
648                                 4, 1, last_dword);
649                 bytes_written += 4;
650
651                 /* data word 2 */
652                 target_write_memory(target, str7x_get_flash_adr(bank, FLASH_DR1),
653                                 4, 1, last_dword + 4);
654                 bytes_written += 4;
655
656                 /* start programming cycle */
657                 cmd = FLASH_DWPG | FLASH_WMS;
658                 target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), cmd);
659
660                 int err;
661                 err = str7x_waitbusy(bank);
662                 if (err != ERROR_OK)
663                         return err;
664
665                 err = str7x_result(bank);
666                 if (err != ERROR_OK)
667                         return err;
668         }
669
670         return ERROR_OK;
671 }
672
673 static int str7x_probe(struct flash_bank *bank)
674 {
675         return ERROR_OK;
676 }
677
678 #if 0
679 COMMAND_HANDLER(str7x_handle_part_id_command)
680 {
681         return ERROR_OK;
682 }
683 #endif
684
685 static int get_str7x_info(struct flash_bank *bank, char *buf, int buf_size)
686 {
687         snprintf(buf, buf_size, "str7x flash driver info");
688         /* STR7x flash doesn't support sector protection interrogation.
689          * FLASH_NVWPAR acts as a write only register; its read value
690          * doesn't reflect the actual protection state of the sectors.
691          */
692         LOG_WARNING("STR7x flash lock information might not be correct "
693                         "due to hardware limitations.");
694         return ERROR_OK;
695 }
696
697 COMMAND_HANDLER(str7x_handle_disable_jtag_command)
698 {
699         struct target *target = NULL;
700         struct str7x_flash_bank *str7x_info = NULL;
701
702         uint32_t flash_cmd;
703         uint16_t ProtectionLevel = 0;
704         uint16_t ProtectionRegs;
705
706         if (CMD_ARGC < 1)
707         {
708                 command_print(CMD_CTX, "str7x disable_jtag <bank>");
709                 return ERROR_OK;
710         }
711
712         struct flash_bank *bank;
713         int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
714         if (ERROR_OK != retval)
715                 return retval;
716
717         str7x_info = bank->driver_priv;
718
719         target = bank->target;
720
721         if (target->state != TARGET_HALTED)
722         {
723                 LOG_ERROR("Target not halted");
724                 return ERROR_TARGET_NOT_HALTED;
725         }
726
727         /* first we get protection status */
728         uint32_t reg;
729         target_read_u32(target, str7x_get_flash_adr(bank, FLASH_NVAPR0), &reg);
730
731         if (!(reg & str7x_info->disable_bit))
732         {
733                 ProtectionLevel = 1;
734         }
735
736         target_read_u32(target, str7x_get_flash_adr(bank, FLASH_NVAPR1), &reg);
737         ProtectionRegs = ~(reg >> 16);
738
739         while (((ProtectionRegs) != 0) && (ProtectionLevel < 16))
740         {
741                 ProtectionRegs >>= 1;
742                 ProtectionLevel++;
743         }
744
745         if (ProtectionLevel == 0)
746         {
747                 flash_cmd = FLASH_SPR;
748                 target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), flash_cmd);
749                 target_write_u32(target, str7x_get_flash_adr(bank, FLASH_AR), 0x4010DFB8);
750                 target_write_u32(target, str7x_get_flash_adr(bank, FLASH_DR0), 0xFFFFFFFD);
751                 flash_cmd = FLASH_SPR | FLASH_WMS;
752                 target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), flash_cmd);
753         }
754         else
755         {
756                 flash_cmd = FLASH_SPR;
757                 target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), flash_cmd);
758                 target_write_u32(target, str7x_get_flash_adr(bank, FLASH_AR), 0x4010DFBC);
759                 target_write_u32(target, str7x_get_flash_adr(bank, FLASH_DR0),
760                                 ~(1 << (15 + ProtectionLevel)));
761                 flash_cmd = FLASH_SPR | FLASH_WMS;
762                 target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), flash_cmd);
763         }
764
765         return ERROR_OK;
766 }
767
768 static const struct command_registration str7x_exec_command_handlers[] = {
769         {
770                 .name = "disable_jtag",
771                 .handler = str7x_handle_disable_jtag_command,
772                 .mode = COMMAND_EXEC,
773                 .help = "disable jtag access",
774         },
775         COMMAND_REGISTRATION_DONE
776 };
777
778 static const struct command_registration str7x_command_handlers[] = {
779         {
780                 .name = "str7x",
781                 .mode = COMMAND_ANY,
782                 .help = "str7x flash command group",
783                 .chain = str7x_exec_command_handlers,
784         },
785         COMMAND_REGISTRATION_DONE
786 };
787
788 struct flash_driver str7x_flash = {
789         .name = "str7x",
790         .commands = str7x_command_handlers,
791         .flash_bank_command = str7x_flash_bank_command,
792         .erase = str7x_erase,
793         .protect = str7x_protect,
794         .write = str7x_write,
795         .read = default_flash_read,
796         .probe = str7x_probe,
797         .auto_probe = str7x_probe,
798         .erase_check = default_flash_blank_check,
799         .protect_check = str7x_protect_check,
800         .info = get_str7x_info,
801 };