b79dd17fde37fcb25c57cd97514a3c597b9c1e63
[fw/openocd] / src / flash / 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  *   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 "str7x.h"
28 #include "armv4_5.h"
29 #include "binarybuffer.h"
30 #include "algorithm.h"
31
32
33 struct str7x_mem_layout mem_layout_str7bank0[] = {
34         {0x00000000, 0x02000, 0x01},
35         {0x00002000, 0x02000, 0x02},
36         {0x00004000, 0x02000, 0x04},
37         {0x00006000, 0x02000, 0x08},
38         {0x00008000, 0x08000, 0x10},
39         {0x00010000, 0x10000, 0x20},
40         {0x00020000, 0x10000, 0x40},
41         {0x00030000, 0x10000, 0x80}
42 };
43
44 struct str7x_mem_layout mem_layout_str7bank1[] = {
45         {0x00000000, 0x02000, 0x10000},
46         {0x00002000, 0x02000, 0x20000}
47 };
48
49 static int str7x_get_flash_adr(struct flash_bank *bank, uint32_t reg)
50 {
51         struct str7x_flash_bank *str7x_info = bank->driver_priv;
52         return (str7x_info->register_base | reg);
53 }
54
55 static int str7x_build_block_list(struct flash_bank *bank)
56 {
57         struct str7x_flash_bank *str7x_info = bank->driver_priv;
58
59         int i;
60         int num_sectors;
61         int b0_sectors = 0, b1_sectors = 0;
62
63         switch (bank->size)
64         {
65                 case 16 * 1024:
66                         b1_sectors = 2;
67                         break;
68                 case 64 * 1024:
69                         b0_sectors = 5;
70                         break;
71                 case 128 * 1024:
72                         b0_sectors = 6;
73                         break;
74                 case 256 * 1024:
75                         b0_sectors = 8;
76                         break;
77                 default:
78                         LOG_ERROR("BUG: unknown bank->size encountered");
79                         exit(-1);
80         }
81
82         num_sectors = b0_sectors + b1_sectors;
83
84         bank->num_sectors = num_sectors;
85         bank->sectors = malloc(sizeof(struct flash_sector) * num_sectors);
86         str7x_info->sector_bits = malloc(sizeof(uint32_t) * num_sectors);
87
88         num_sectors = 0;
89
90         for (i = 0; i < b0_sectors; i++)
91         {
92                 bank->sectors[num_sectors].offset = mem_layout_str7bank0[i].sector_start;
93                 bank->sectors[num_sectors].size = mem_layout_str7bank0[i].sector_size;
94                 bank->sectors[num_sectors].is_erased = -1;
95                 bank->sectors[num_sectors].is_protected = 1;
96                 str7x_info->sector_bits[num_sectors++] = mem_layout_str7bank0[i].sector_bit;
97         }
98
99         for (i = 0; i < b1_sectors; i++)
100         {
101                 bank->sectors[num_sectors].offset = mem_layout_str7bank1[i].sector_start;
102                 bank->sectors[num_sectors].size = mem_layout_str7bank1[i].sector_size;
103                 bank->sectors[num_sectors].is_erased = -1;
104                 bank->sectors[num_sectors].is_protected = 1;
105                 str7x_info->sector_bits[num_sectors++] = mem_layout_str7bank1[i].sector_bit;
106         }
107
108         return ERROR_OK;
109 }
110
111 /* flash bank str7x <base> <size> 0 0 <target#> <str71_variant>
112  */
113 FLASH_BANK_COMMAND_HANDLER(str7x_flash_bank_command)
114 {
115         struct str7x_flash_bank *str7x_info;
116
117         if (CMD_ARGC < 7)
118         {
119                 LOG_WARNING("incomplete flash_bank str7x configuration");
120                 return ERROR_FLASH_BANK_INVALID;
121         }
122
123         str7x_info = malloc(sizeof(struct str7x_flash_bank));
124         bank->driver_priv = str7x_info;
125
126         /* set default bits for str71x flash */
127         str7x_info->busy_bits = (FLASH_LOCK | FLASH_BSYA1 | FLASH_BSYA0);
128         str7x_info->disable_bit = (1 << 1);
129
130         if (strcmp(CMD_ARGV[6], "STR71x") == 0)
131         {
132                 str7x_info->register_base = 0x40100000;
133         }
134         else if (strcmp(CMD_ARGV[6], "STR73x") == 0)
135         {
136                 str7x_info->register_base = 0x80100000;
137                 str7x_info->busy_bits = (FLASH_LOCK | FLASH_BSYA0);
138         }
139         else if (strcmp(CMD_ARGV[6], "STR75x") == 0)
140         {
141                 str7x_info->register_base = 0x20100000;
142                 str7x_info->disable_bit = (1 << 0);
143         }
144         else
145         {
146                 LOG_ERROR("unknown STR7x variant: '%s'", CMD_ARGV[6]);
147                 free(str7x_info);
148                 return ERROR_FLASH_BANK_INVALID;
149         }
150
151         str7x_build_block_list(bank);
152
153         str7x_info->write_algorithm = NULL;
154
155         return ERROR_OK;
156 }
157
158 static uint32_t str7x_status(struct flash_bank *bank)
159 {
160         struct target *target = bank->target;
161         uint32_t retval;
162
163         target_read_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), &retval);
164
165         return retval;
166 }
167
168 static uint32_t str7x_result(struct flash_bank *bank)
169 {
170         struct target *target = bank->target;
171         uint32_t retval;
172
173         target_read_u32(target, str7x_get_flash_adr(bank, FLASH_ER), &retval);
174
175         return retval;
176 }
177
178 static int str7x_protect_check(struct flash_bank *bank)
179 {
180         struct str7x_flash_bank *str7x_info = bank->driver_priv;
181         struct target *target = bank->target;
182
183         int i;
184         uint32_t retval;
185
186         if (bank->target->state != TARGET_HALTED)
187         {
188                 LOG_ERROR("Target not halted");
189                 return ERROR_TARGET_NOT_HALTED;
190         }
191
192         target_read_u32(target, str7x_get_flash_adr(bank, FLASH_NVWPAR), &retval);
193
194         for (i = 0; i < bank->num_sectors; i++)
195         {
196                 if (retval & str7x_info->sector_bits[i])
197                         bank->sectors[i].is_protected = 0;
198                 else
199                         bank->sectors[i].is_protected = 1;
200         }
201
202         return ERROR_OK;
203 }
204
205 static int str7x_erase(struct flash_bank *bank, int first, int last)
206 {
207         struct str7x_flash_bank *str7x_info = bank->driver_priv;
208         struct target *target = bank->target;
209
210         int i;
211         uint32_t cmd;
212         uint32_t retval;
213         uint32_t sectors = 0;
214
215         if (bank->target->state != TARGET_HALTED)
216         {
217                 LOG_ERROR("Target not halted");
218                 return ERROR_TARGET_NOT_HALTED;
219         }
220
221         for (i = first; i <= last; i++)
222         {
223                 sectors |= str7x_info->sector_bits[i];
224         }
225
226         LOG_DEBUG("sectors: 0x%" PRIx32 "", sectors);
227
228         /* clear FLASH_ER register */
229         target_write_u32(target, str7x_get_flash_adr(bank, FLASH_ER), 0x0);
230
231         cmd = FLASH_SER;
232         target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), cmd);
233
234         cmd = sectors;
235         target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR1), cmd);
236
237         cmd = FLASH_SER | FLASH_WMS;
238         target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), cmd);
239
240         while (((retval = str7x_status(bank)) & str7x_info->busy_bits)) {
241                 alive_sleep(1);
242         }
243
244         retval = str7x_result(bank);
245
246         if (retval)
247         {
248                 LOG_ERROR("error erasing flash bank, FLASH_ER: 0x%" PRIx32 "", retval);
249                 return ERROR_FLASH_OPERATION_FAILED;
250         }
251
252         for (i = first; i <= last; i++)
253                 bank->sectors[i].is_erased = 1;
254
255         return ERROR_OK;
256 }
257
258 static int str7x_protect(struct flash_bank *bank, int set, int first, int last)
259 {
260         struct str7x_flash_bank *str7x_info = bank->driver_priv;
261         struct target *target = bank->target;
262         int i;
263         uint32_t cmd;
264         uint32_t retval;
265         uint32_t protect_blocks;
266
267         if (bank->target->state != TARGET_HALTED)
268         {
269                 LOG_ERROR("Target not halted");
270                 return ERROR_TARGET_NOT_HALTED;
271         }
272
273         protect_blocks = 0xFFFFFFFF;
274
275         if (set)
276         {
277                 for (i = first; i <= last; i++)
278                         protect_blocks &= ~(str7x_info->sector_bits[i]);
279         }
280
281         /* clear FLASH_ER register */
282         target_write_u32(target, str7x_get_flash_adr(bank, FLASH_ER), 0x0);
283
284         cmd = FLASH_SPR;
285         target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), cmd);
286
287         cmd = str7x_get_flash_adr(bank, FLASH_NVWPAR);
288         target_write_u32(target, str7x_get_flash_adr(bank, FLASH_AR), cmd);
289
290         cmd = protect_blocks;
291         target_write_u32(target, str7x_get_flash_adr(bank, FLASH_DR0), cmd);
292
293         cmd = FLASH_SPR | FLASH_WMS;
294         target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), cmd);
295
296         while (((retval = str7x_status(bank)) & str7x_info->busy_bits)) {
297                 alive_sleep(1);
298         }
299
300         retval = str7x_result(bank);
301
302         LOG_DEBUG("retval: 0x%8.8" PRIx32 "", retval);
303
304         if (retval & FLASH_ERER)
305                 return ERROR_FLASH_SECTOR_NOT_ERASED;
306         else if (retval & FLASH_WPF)
307                 return ERROR_FLASH_OPERATION_FAILED;
308
309         return ERROR_OK;
310 }
311
312 static int str7x_write_block(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, uint32_t count)
313 {
314         struct str7x_flash_bank *str7x_info = bank->driver_priv;
315         struct target *target = bank->target;
316         uint32_t buffer_size = 8192;
317         struct working_area *source;
318         uint32_t address = bank->base + offset;
319         struct reg_param reg_params[6];
320         struct armv4_5_algorithm armv4_5_info;
321         int retval = ERROR_OK;
322
323         uint32_t str7x_flash_write_code[] = {
324                                         /* write:                               */
325                 0xe3a04201, /*  mov r4, #0x10000000     */
326                 0xe5824000, /*  str r4, [r2, #0x0]      */
327                 0xe5821010, /*  str r1, [r2, #0x10]     */
328                 0xe4904004, /*  ldr r4, [r0], #4        */
329                 0xe5824008, /*  str r4, [r2, #0x8]      */
330                 0xe4904004, /*  ldr r4, [r0], #4        */
331                 0xe582400c, /*  str r4, [r2, #0xc]      */
332                 0xe3a04209, /*  mov r4, #0x90000000     */
333                 0xe5824000, /*  str r4, [r2, #0x0]      */
334                             /* busy:                            */
335                 0xe5924000, /*  ldr r4, [r2, #0x0]      */
336                 0xe1140005,     /*      tst r4, r5                      */
337                 0x1afffffc, /*  bne busy                        */
338                 0xe5924014, /*  ldr r4, [r2, #0x14]     */
339                 0xe31400ff, /*  tst r4, #0xff           */
340                 0x03140c01, /*  tsteq r4, #0x100        */
341                 0x1a000002, /*  bne exit                        */
342                 0xe2811008, /*  add r1, r1, #0x8        */
343                 0xe2533001, /*  subs r3, r3, #1         */
344                 0x1affffec, /*  bne write                       */
345                                         /* exit:                                */
346                 0xeafffffe, /*  b exit                          */
347         };
348
349         /* flash write code */
350         if (target_alloc_working_area(target, 4 * 20, &str7x_info->write_algorithm) != ERROR_OK)
351         {
352                 LOG_WARNING("no working area available, can't do block memory writes");
353                 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
354         };
355
356         target_write_buffer(target, str7x_info->write_algorithm->address, 20 * 4, (uint8_t*)str7x_flash_write_code);
357
358         /* memory buffer */
359         while (target_alloc_working_area(target, buffer_size, &source) != ERROR_OK)
360         {
361                 buffer_size /= 2;
362                 if (buffer_size <= 256)
363                 {
364                         /* if we already allocated the writing code, but failed to get a buffer, free the algorithm */
365                         if (str7x_info->write_algorithm)
366                                 target_free_working_area(target, str7x_info->write_algorithm);
367
368                         LOG_WARNING("no large enough working area available, can't do block memory writes");
369                         return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
370                 }
371         }
372
373         armv4_5_info.common_magic = ARMV4_5_COMMON_MAGIC;
374         armv4_5_info.core_mode = ARMV4_5_MODE_SVC;
375         armv4_5_info.core_state = ARMV4_5_STATE_ARM;
376
377         init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);
378         init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
379         init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT);
380         init_reg_param(&reg_params[3], "r3", 32, PARAM_OUT);
381         init_reg_param(&reg_params[4], "r4", 32, PARAM_IN);
382         init_reg_param(&reg_params[5], "r5", 32, PARAM_OUT);
383
384         while (count > 0)
385         {
386                 uint32_t thisrun_count = (count > (buffer_size / 8)) ? (buffer_size / 8) : count;
387
388                 target_write_buffer(target, source->address, thisrun_count * 8, buffer);
389
390                 buf_set_u32(reg_params[0].value, 0, 32, source->address);
391                 buf_set_u32(reg_params[1].value, 0, 32, address);
392                 buf_set_u32(reg_params[2].value, 0, 32, str7x_get_flash_adr(bank, FLASH_CR0));
393                 buf_set_u32(reg_params[3].value, 0, 32, thisrun_count);
394                 buf_set_u32(reg_params[5].value, 0, 32, str7x_info->busy_bits);
395
396                 if ((retval = target_run_algorithm(target, 0, NULL, 6, reg_params, str7x_info->write_algorithm->address, str7x_info->write_algorithm->address + (19 * 4), 10000, &armv4_5_info)) != ERROR_OK)
397                 {
398                         LOG_ERROR("error executing str7x flash write algorithm");
399                         retval = ERROR_FLASH_OPERATION_FAILED;
400                         break;
401                 }
402
403                 if (buf_get_u32(reg_params[4].value, 0, 32) != 0x00)
404                 {
405                         retval = ERROR_FLASH_OPERATION_FAILED;
406                         break;
407                 }
408
409                 buffer += thisrun_count * 8;
410                 address += thisrun_count * 8;
411                 count -= thisrun_count;
412         }
413
414         target_free_working_area(target, source);
415         target_free_working_area(target, str7x_info->write_algorithm);
416
417         destroy_reg_param(&reg_params[0]);
418         destroy_reg_param(&reg_params[1]);
419         destroy_reg_param(&reg_params[2]);
420         destroy_reg_param(&reg_params[3]);
421         destroy_reg_param(&reg_params[4]);
422         destroy_reg_param(&reg_params[5]);
423
424         return retval;
425 }
426
427 static int str7x_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, uint32_t count)
428 {
429         struct target *target = bank->target;
430         struct str7x_flash_bank *str7x_info = bank->driver_priv;
431         uint32_t dwords_remaining = (count / 8);
432         uint32_t bytes_remaining = (count & 0x00000007);
433         uint32_t address = bank->base + offset;
434         uint32_t bytes_written = 0;
435         uint32_t cmd;
436         int retval;
437         uint32_t check_address = offset;
438         int i;
439
440         if (bank->target->state != TARGET_HALTED)
441         {
442                 LOG_ERROR("Target not halted");
443                 return ERROR_TARGET_NOT_HALTED;
444         }
445
446         if (offset & 0x7)
447         {
448                 LOG_WARNING("offset 0x%" PRIx32 " breaks required 8-byte alignment", offset);
449                 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
450         }
451
452         for (i = 0; i < bank->num_sectors; i++)
453         {
454                 uint32_t sec_start = bank->sectors[i].offset;
455                 uint32_t sec_end = sec_start + bank->sectors[i].size;
456
457                 /* check if destination falls within the current sector */
458                 if ((check_address >= sec_start) && (check_address < sec_end))
459                 {
460                         /* check if destination ends in the current sector */
461                         if (offset + count < sec_end)
462                                 check_address = offset + count;
463                         else
464                                 check_address = sec_end;
465                 }
466         }
467
468         if (check_address != offset + count)
469                 return ERROR_FLASH_DST_OUT_OF_BANK;
470
471         /* clear FLASH_ER register */
472         target_write_u32(target, str7x_get_flash_adr(bank, FLASH_ER), 0x0);
473
474         /* multiple dwords (8-byte) to be programmed? */
475         if (dwords_remaining > 0)
476         {
477                 /* try using a block write */
478                 if ((retval = str7x_write_block(bank, buffer, offset, dwords_remaining)) != ERROR_OK)
479                 {
480                         if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE)
481                         {
482                                 /* if block write failed (no sufficient working area),
483                                  * we use normal (slow) single dword accesses */
484                                 LOG_WARNING("couldn't use block writes, falling back to single memory accesses");
485                         }
486                         else if (retval == ERROR_FLASH_OPERATION_FAILED)
487                         {
488                                 /* if an error occured, we examine the reason, and quit */
489                                 retval = str7x_result(bank);
490
491                                 LOG_ERROR("flash writing failed with error code: 0x%x", retval);
492                                 return ERROR_FLASH_OPERATION_FAILED;
493                         }
494                 }
495                 else
496                 {
497                         buffer += dwords_remaining * 8;
498                         address += dwords_remaining * 8;
499                         dwords_remaining = 0;
500                 }
501         }
502
503         while (dwords_remaining > 0)
504         {
505                 /* command */
506                 cmd = FLASH_DWPG;
507                 target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), cmd);
508
509                 /* address */
510                 target_write_u32(target, str7x_get_flash_adr(bank, FLASH_AR), address);
511
512                 /* data word 1 */
513                 target_write_memory(target, str7x_get_flash_adr(bank, FLASH_DR0), 4, 1, buffer + bytes_written);
514                 bytes_written += 4;
515
516                 /* data word 2 */
517                 target_write_memory(target, str7x_get_flash_adr(bank, FLASH_DR1), 4, 1, buffer + bytes_written);
518                 bytes_written += 4;
519
520                 /* start programming cycle */
521                 cmd = FLASH_DWPG | FLASH_WMS;
522                 target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), cmd);
523
524                 while (((retval = str7x_status(bank)) & str7x_info->busy_bits))
525                 {
526                         alive_sleep(1);
527                 }
528
529                 retval = str7x_result(bank);
530
531                 if (retval & FLASH_PGER)
532                         return ERROR_FLASH_OPERATION_FAILED;
533                 else if (retval & FLASH_WPF)
534                         return ERROR_FLASH_OPERATION_FAILED;
535
536                 dwords_remaining--;
537                 address += 8;
538         }
539
540         if (bytes_remaining)
541         {
542                 uint8_t last_dword[8] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
543                 int i = 0;
544
545                 while (bytes_remaining > 0)
546                 {
547                         last_dword[i++] = *(buffer + bytes_written);
548                         bytes_remaining--;
549                         bytes_written++;
550                 }
551
552                 /* command */
553                 cmd = FLASH_DWPG;
554                 target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), cmd);
555
556                 /* address */
557                 target_write_u32(target, str7x_get_flash_adr(bank, FLASH_AR), address);
558
559                 /* data word 1 */
560                 target_write_memory(target, str7x_get_flash_adr(bank, FLASH_DR0), 4, 1, last_dword);
561                 bytes_written += 4;
562
563                 /* data word 2 */
564                 target_write_memory(target, str7x_get_flash_adr(bank, FLASH_DR1), 4, 1, last_dword + 4);
565                 bytes_written += 4;
566
567                 /* start programming cycle */
568                 cmd = FLASH_DWPG | FLASH_WMS;
569                 target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), cmd);
570
571                 while (((retval = str7x_status(bank)) & str7x_info->busy_bits))
572                 {
573                         alive_sleep(1);
574                 }
575
576                 retval = str7x_result(bank);
577
578                 if (retval & FLASH_PGER)
579                         return ERROR_FLASH_OPERATION_FAILED;
580                 else if (retval & FLASH_WPF)
581                         return ERROR_FLASH_OPERATION_FAILED;
582         }
583
584         return ERROR_OK;
585 }
586
587 static int str7x_probe(struct flash_bank *bank)
588 {
589         return ERROR_OK;
590 }
591
592 #if 0
593 COMMAND_HANDLER(str7x_handle_part_id_command)
594 {
595         return ERROR_OK;
596 }
597 #endif
598
599 static int str7x_info(struct flash_bank *bank, char *buf, int buf_size)
600 {
601         snprintf(buf, buf_size, "str7x flash driver info");
602         return ERROR_OK;
603 }
604
605 COMMAND_HANDLER(str7x_handle_disable_jtag_command)
606 {
607         struct target *target = NULL;
608         struct str7x_flash_bank *str7x_info = NULL;
609
610         uint32_t flash_cmd;
611         uint16_t ProtectionLevel = 0;
612         uint16_t ProtectionRegs;
613
614         if (CMD_ARGC < 1)
615         {
616                 command_print(CMD_CTX, "str7x disable_jtag <bank>");
617                 return ERROR_OK;
618         }
619
620         struct flash_bank *bank;
621         int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
622         if (ERROR_OK != retval)
623                 return retval;
624
625         str7x_info = bank->driver_priv;
626
627         target = bank->target;
628
629         if (target->state != TARGET_HALTED)
630         {
631                 LOG_ERROR("Target not halted");
632                 return ERROR_TARGET_NOT_HALTED;
633         }
634
635         /* first we get protection status */
636         uint32_t reg;
637         target_read_u32(target, str7x_get_flash_adr(bank, FLASH_NVAPR0), &reg);
638
639         if (!(reg & str7x_info->disable_bit))
640         {
641                 ProtectionLevel = 1;
642         }
643
644         target_read_u32(target, str7x_get_flash_adr(bank, FLASH_NVAPR1), &reg);
645         ProtectionRegs = ~(reg >> 16);
646
647         while (((ProtectionRegs) != 0) && (ProtectionLevel < 16))
648         {
649                 ProtectionRegs >>= 1;
650                 ProtectionLevel++;
651         }
652
653         if (ProtectionLevel == 0)
654         {
655                 flash_cmd = FLASH_SPR;
656                 target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), flash_cmd);
657                 target_write_u32(target, str7x_get_flash_adr(bank, FLASH_AR), 0x4010DFB8);
658                 target_write_u32(target, str7x_get_flash_adr(bank, FLASH_DR0), 0xFFFFFFFD);
659                 flash_cmd = FLASH_SPR | FLASH_WMS;
660                 target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), flash_cmd);
661         }
662         else
663         {
664                 flash_cmd = FLASH_SPR;
665                 target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), flash_cmd);
666                 target_write_u32(target, str7x_get_flash_adr(bank, FLASH_AR), 0x4010DFBC);
667                 target_write_u32(target, str7x_get_flash_adr(bank, FLASH_DR0), ~(1 << (15 + ProtectionLevel)));
668                 flash_cmd = FLASH_SPR | FLASH_WMS;
669                 target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), flash_cmd);
670         }
671
672         return ERROR_OK;
673 }
674
675 static int str7x_register_commands(struct command_context *cmd_ctx)
676 {
677         struct command *str7x_cmd = register_command(cmd_ctx, NULL, "str7x",
678                         NULL, COMMAND_ANY, "str7x flash specific commands");
679
680         register_command(cmd_ctx, str7x_cmd, "disable_jtag",
681                         str7x_handle_disable_jtag_command, COMMAND_EXEC,
682                         "disable jtag access");
683
684         return ERROR_OK;
685 }
686
687 struct flash_driver str7x_flash = {
688                 .name = "str7x",
689                 .register_commands = &str7x_register_commands,
690                 .flash_bank_command = &str7x_flash_bank_command,
691                 .erase = &str7x_erase,
692                 .protect = &str7x_protect,
693                 .write = &str7x_write,
694                 .probe = &str7x_probe,
695                 .auto_probe = &str7x_probe,
696                 .erase_check = &default_flash_blank_check,
697                 .protect_check = &str7x_protect_check,
698                 .info = &str7x_info,
699         };