]> git.sur5r.net Git - openocd/blob - src/flash/str9x.c
David Brownell <david-b@pacbell.net>:
[openocd] / src / flash / str9x.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) 2008 by Oyvind 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 "str9x.h"
31 #include "arm966e.h"
32
33
34 static u32 bank1start = 0x00080000;
35
36 static int str9x_register_commands(struct command_context_s *cmd_ctx);
37 static int str9x_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank);
38 static int str9x_erase(struct flash_bank_s *bank, int first, int last);
39 static int str9x_protect(struct flash_bank_s *bank, int set, int first, int last);
40 static int str9x_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count);
41 static int str9x_probe(struct flash_bank_s *bank);
42 //static int str9x_handle_part_id_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
43 static int str9x_protect_check(struct flash_bank_s *bank);
44 static int str9x_info(struct flash_bank_s *bank, char *buf, int buf_size);
45
46 static int str9x_handle_flash_config_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
47
48 flash_driver_t str9x_flash =
49 {
50         .name = "str9x",
51         .register_commands = str9x_register_commands,
52         .flash_bank_command = str9x_flash_bank_command,
53         .erase = str9x_erase,
54         .protect = str9x_protect,
55         .write = str9x_write,
56         .probe = str9x_probe,
57         .auto_probe = str9x_probe,
58         .erase_check = default_flash_blank_check,
59         .protect_check = str9x_protect_check,
60         .info = str9x_info
61 };
62
63 static int str9x_register_commands(struct command_context_s *cmd_ctx)
64 {
65         command_t *str9x_cmd = register_command(cmd_ctx, NULL, "str9x", NULL, COMMAND_ANY, NULL);
66
67         register_command(cmd_ctx, str9x_cmd, "flash_config", str9x_handle_flash_config_command, COMMAND_EXEC,
68                                          "configure str9 flash controller");
69
70         return ERROR_OK;
71 }
72
73 static int str9x_build_block_list(struct flash_bank_s *bank)
74 {
75         str9x_flash_bank_t *str9x_info = bank->driver_priv;
76
77         int i;
78         int num_sectors;
79         int b0_sectors = 0, b1_sectors = 0;
80         u32 offset = 0;
81
82         /* set if we have large flash str9 */
83         str9x_info->variant = 0;
84         str9x_info->bank1 = 0;
85
86         switch (bank->size)
87         {
88                 case (256 * 1024):
89                         b0_sectors = 4;
90                         break;
91                 case (512 * 1024):
92                         b0_sectors = 8;
93                         break;
94                 case (1024 * 1024):
95                         bank1start = 0x00100000;
96                         str9x_info->variant = 1;
97                         b0_sectors = 16;
98                         break;
99                 case (2048 * 1024):
100                         bank1start = 0x00200000;
101                         str9x_info->variant = 1;
102                         b0_sectors = 32;
103                         break;
104                 case (128 * 1024):
105                         str9x_info->variant = 1;
106                         str9x_info->bank1 = 1;
107                         b1_sectors = 8;
108                         bank1start = bank->base;
109                         break;
110                 case (32 * 1024):
111                         str9x_info->bank1 = 1;
112                         b1_sectors = 4;
113                         bank1start = bank->base;
114                         break;
115                 default:
116                         LOG_ERROR("BUG: unknown bank->size encountered");
117                         exit(-1);
118         }
119
120         num_sectors = b0_sectors + b1_sectors;
121
122         bank->num_sectors = num_sectors;
123         bank->sectors = malloc(sizeof(flash_sector_t) * num_sectors);
124         str9x_info->sector_bits = malloc(sizeof(u32) * num_sectors);
125
126         num_sectors = 0;
127
128         for (i = 0; i < b0_sectors; i++)
129         {
130                 bank->sectors[num_sectors].offset = offset;
131                 bank->sectors[num_sectors].size = 0x10000;
132                 offset += bank->sectors[i].size;
133                 bank->sectors[num_sectors].is_erased = -1;
134                 bank->sectors[num_sectors].is_protected = 1;
135                 str9x_info->sector_bits[num_sectors++] = (1<<i);
136         }
137
138         for (i = 0; i < b1_sectors; i++)
139         {
140                 bank->sectors[num_sectors].offset = offset;
141                 bank->sectors[num_sectors].size = str9x_info->variant == 0 ? 0x2000 : 0x4000;
142                 offset += bank->sectors[i].size;
143                 bank->sectors[num_sectors].is_erased = -1;
144                 bank->sectors[num_sectors].is_protected = 1;
145                 if (str9x_info->variant)
146                         str9x_info->sector_bits[num_sectors++] = (1<<i);
147                 else
148                         str9x_info->sector_bits[num_sectors++] = (1<<(i+8));
149         }
150
151         return ERROR_OK;
152 }
153
154 /* flash bank str9x <base> <size> 0 0 <target#>
155  */
156 static int str9x_flash_bank_command(struct command_context_s *cmd_ctx,
157                 char *cmd, char **args, int argc, struct flash_bank_s *bank)
158 {
159         str9x_flash_bank_t *str9x_info;
160
161         if (argc < 6)
162         {
163                 LOG_WARNING("incomplete flash_bank str9x configuration");
164                 return ERROR_FLASH_BANK_INVALID;
165         }
166
167         str9x_info = malloc(sizeof(str9x_flash_bank_t));
168         bank->driver_priv = str9x_info;
169
170         str9x_build_block_list(bank);
171
172         str9x_info->write_algorithm = NULL;
173
174         return ERROR_OK;
175 }
176
177 static int str9x_protect_check(struct flash_bank_s *bank)
178 {
179         int retval;
180         str9x_flash_bank_t *str9x_info = bank->driver_priv;
181         target_t *target = bank->target;
182
183         int i;
184         u32 adr;
185         u32 status = 0;
186         u16 hstatus = 0;
187
188         if (bank->target->state != TARGET_HALTED)
189         {
190                 LOG_ERROR("Target not halted");
191                 return ERROR_TARGET_NOT_HALTED;
192         }
193
194         /* read level one protection */
195
196         if (str9x_info->variant)
197         {
198                 if (str9x_info->bank1)
199                 {
200                         adr = bank1start + 0x18;
201                         if ((retval=target_write_u16(target, adr, 0x90))!=ERROR_OK)
202                         {
203                                 return retval;
204                         }
205                         if ((retval=target_read_u16(target, adr, &hstatus))!=ERROR_OK)
206                         {
207                                 return retval;
208                         }
209                         status = hstatus;
210                 }
211                 else
212                 {
213                         adr = bank1start + 0x14;
214                         if ((retval=target_write_u16(target, adr, 0x90))!=ERROR_OK)
215                         {
216                                 return retval;
217                         }
218                         if ((retval=target_read_u32(target, adr, &status))!=ERROR_OK)
219                         {
220                                 return retval;
221                         }
222                 }
223         }
224         else
225         {
226                 adr = bank1start + 0x10;
227                 if ((retval=target_write_u16(target, adr, 0x90))!=ERROR_OK)
228                 {
229                         return retval;
230                 }
231                 if ((retval=target_read_u16(target, adr, &hstatus))!=ERROR_OK)
232                 {
233                         return retval;
234                 }
235                 status = hstatus;
236         }
237
238         /* read array command */
239         if ((retval=target_write_u16(target, adr, 0xFF))!=ERROR_OK)
240         {
241                 return retval;
242         }
243
244         for (i = 0; i < bank->num_sectors; i++)
245         {
246                 if (status & str9x_info->sector_bits[i])
247                         bank->sectors[i].is_protected = 1;
248                 else
249                         bank->sectors[i].is_protected = 0;
250         }
251
252         return ERROR_OK;
253 }
254
255 static int str9x_erase(struct flash_bank_s *bank, int first, int last)
256 {
257         target_t *target = bank->target;
258         int i;
259         u32 adr;
260         u8 status;
261         u8 erase_cmd;
262
263         if (bank->target->state != TARGET_HALTED)
264         {
265                 LOG_ERROR("Target not halted");
266                 return ERROR_TARGET_NOT_HALTED;
267         }
268
269         /* Check if we erase whole bank */
270         if ((first == 0) && (last == (bank->num_sectors - 1)))
271         {
272                 /* Optimize to run erase bank command instead of sector */
273                 erase_cmd = 0x80;
274         }
275         else
276         {
277                 /* Erase sector command */
278                 erase_cmd = 0x20;
279         }
280
281         for (i = first; i <= last; i++)
282         {
283                 int retval;
284                 adr = bank->base + bank->sectors[i].offset;
285
286                 /* erase sectors */
287                 if ((retval=target_write_u16(target, adr, erase_cmd))!=ERROR_OK)
288                 {
289                         return retval;
290                 }
291                 if ((retval=target_write_u16(target, adr, 0xD0))!=ERROR_OK)
292                 {
293                         return retval;
294                 }
295
296                 /* get status */
297                 if ((retval=target_write_u16(target, adr, 0x70))!=ERROR_OK)
298                 {
299                         return retval;
300                 }
301
302                 int timeout;
303                 for (timeout=0; timeout<1000; timeout++) {
304                         if ((retval=target_read_u8(target, adr, &status))!=ERROR_OK)
305                         {
306                                 return retval;
307                         }
308                         if( status & 0x80 )
309                                 break;
310                         alive_sleep(1);
311                 }
312                 if (timeout==1000)
313                 {
314                         LOG_ERROR("erase timed out");
315                         return ERROR_FAIL;
316                 }
317
318                 /* clear status, also clear read array */
319                 if ((retval=target_write_u16(target, adr, 0x50))!=ERROR_OK)
320                 {
321                         return retval;
322                 }
323
324                 /* read array command */
325                 if ((retval=target_write_u16(target, adr, 0xFF))!=ERROR_OK)
326                 {
327                         return retval;
328                 }
329
330                 if( status & 0x22 )
331                 {
332                         LOG_ERROR("error erasing flash bank, status: 0x%x", status);
333                         return ERROR_FLASH_OPERATION_FAILED;
334                 }
335
336                 /* If we ran erase bank command, we are finished */
337                 if (erase_cmd == 0x80)
338                         break;
339         }
340
341         for (i = first; i <= last; i++)
342                 bank->sectors[i].is_erased = 1;
343
344         return ERROR_OK;
345 }
346
347 static int str9x_protect(struct flash_bank_s *bank,
348                 int set, int first, int last)
349 {
350         target_t *target = bank->target;
351         int i;
352         u32 adr;
353         u8 status;
354
355         if (bank->target->state != TARGET_HALTED)
356         {
357                 LOG_ERROR("Target not halted");
358                 return ERROR_TARGET_NOT_HALTED;
359         }
360
361         for (i = first; i <= last; i++)
362         {
363                 /* Level One Protection */
364
365                 adr = bank->base + bank->sectors[i].offset;
366
367                 target_write_u16(target, adr, 0x60);
368                 if( set )
369                         target_write_u16(target, adr, 0x01);
370                 else
371                         target_write_u16(target, adr, 0xD0);
372
373                 /* query status */
374                 target_read_u8(target, adr, &status);
375
376                 /* clear status, also clear read array */
377                 target_write_u16(target, adr, 0x50);
378
379                 /* read array command */
380                 target_write_u16(target, adr, 0xFF);
381         }
382
383         return ERROR_OK;
384 }
385
386 static int str9x_write_block(struct flash_bank_s *bank,
387                 u8 *buffer, u32 offset, u32 count)
388 {
389         str9x_flash_bank_t *str9x_info = bank->driver_priv;
390         target_t *target = bank->target;
391         u32 buffer_size = 8192;
392         working_area_t *source;
393         u32 address = bank->base + offset;
394         reg_param_t reg_params[4];
395         armv4_5_algorithm_t armv4_5_info;
396         int retval = ERROR_OK;
397
398         u32 str9x_flash_write_code[] = {
399                                         /* write:                               */
400                 0xe3c14003,     /*      bic     r4, r1, #3              */
401                 0xe3a03040,     /*      mov     r3, #0x40               */
402                 0xe1c430b0,     /*      strh r3, [r4, #0]       */
403                 0xe0d030b2,     /*      ldrh r3, [r0], #2       */
404                 0xe0c130b2,     /*      strh r3, [r1], #2       */
405                 0xe3a03070,     /*      mov r3, #0x70           */
406                 0xe1c430b0,     /*      strh r3, [r4, #0]       */
407                                         /* busy:                                */
408                 0xe5d43000,     /*      ldrb r3, [r4, #0]       */
409                 0xe3130080,     /*      tst r3, #0x80           */
410                 0x0afffffc,     /*      beq busy                        */
411                 0xe3a05050,     /*      mov     r5, #0x50               */
412                 0xe1c450b0,     /*      strh r5, [r4, #0]       */
413                 0xe3a050ff,     /*      mov     r5, #0xFF               */
414                 0xe1c450b0,     /*      strh r5, [r4, #0]       */
415                 0xe3130012,     /*      tst     r3, #0x12               */
416                 0x1a000001,     /*      bne exit                        */
417                 0xe2522001,     /*      subs r2, r2, #1         */
418                 0x1affffed,     /*      bne write                       */
419                                         /* exit:                                */
420                 0xeafffffe,     /*      b exit                          */
421         };
422
423         /* flash write code */
424         if (target_alloc_working_area(target, 4 * 19, &str9x_info->write_algorithm) != ERROR_OK)
425         {
426                 LOG_WARNING("no working area available, can't do block memory writes");
427                 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
428         };
429
430         target_write_buffer(target, str9x_info->write_algorithm->address, 19 * 4, (u8*)str9x_flash_write_code);
431
432         /* memory buffer */
433         while (target_alloc_working_area(target, buffer_size, &source) != ERROR_OK)
434         {
435                 buffer_size /= 2;
436                 if (buffer_size <= 256)
437                 {
438                         /* if we already allocated the writing code, but failed to get a buffer, free the algorithm */
439                         if (str9x_info->write_algorithm)
440                                 target_free_working_area(target, str9x_info->write_algorithm);
441
442                         LOG_WARNING("no large enough working area available, can't do block memory writes");
443                         return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
444                 }
445         }
446
447         armv4_5_info.common_magic = ARMV4_5_COMMON_MAGIC;
448         armv4_5_info.core_mode = ARMV4_5_MODE_SVC;
449         armv4_5_info.core_state = ARMV4_5_STATE_ARM;
450
451         init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);
452         init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
453         init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT);
454         init_reg_param(&reg_params[3], "r3", 32, PARAM_IN);
455
456         while (count > 0)
457         {
458                 u32 thisrun_count = (count > (buffer_size / 2)) ? (buffer_size / 2) : count;
459
460                 target_write_buffer(target, source->address, thisrun_count * 2, buffer);
461
462                 buf_set_u32(reg_params[0].value, 0, 32, source->address);
463                 buf_set_u32(reg_params[1].value, 0, 32, address);
464                 buf_set_u32(reg_params[2].value, 0, 32, thisrun_count);
465
466                 if ((retval = target_run_algorithm(target, 0, NULL, 4, reg_params, str9x_info->write_algorithm->address, str9x_info->write_algorithm->address + (18 * 4), 10000, &armv4_5_info)) != ERROR_OK)
467                 {
468                         LOG_ERROR("error executing str9x flash write algorithm");
469                         retval = ERROR_FLASH_OPERATION_FAILED;
470                         break;
471                 }
472
473                 if (buf_get_u32(reg_params[3].value, 0, 32) != 0x80)
474                 {
475                         retval = ERROR_FLASH_OPERATION_FAILED;
476                         break;
477                 }
478
479                 buffer += thisrun_count * 2;
480                 address += thisrun_count * 2;
481                 count -= thisrun_count;
482         }
483
484         target_free_working_area(target, source);
485         target_free_working_area(target, str9x_info->write_algorithm);
486
487         destroy_reg_param(&reg_params[0]);
488         destroy_reg_param(&reg_params[1]);
489         destroy_reg_param(&reg_params[2]);
490         destroy_reg_param(&reg_params[3]);
491
492         return retval;
493 }
494
495 static int str9x_write(struct flash_bank_s *bank,
496                 u8 *buffer, u32 offset, u32 count)
497 {
498         target_t *target = bank->target;
499         u32 words_remaining = (count / 2);
500         u32 bytes_remaining = (count & 0x00000001);
501         u32 address = bank->base + offset;
502         u32 bytes_written = 0;
503         u8 status;
504         int retval;
505         u32 check_address = offset;
506         u32 bank_adr;
507         int i;
508
509         if (bank->target->state != TARGET_HALTED)
510         {
511                 LOG_ERROR("Target not halted");
512                 return ERROR_TARGET_NOT_HALTED;
513         }
514
515         if (offset & 0x1)
516         {
517                 LOG_WARNING("offset 0x%x breaks required 2-byte alignment", offset);
518                 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
519         }
520
521         for (i = 0; i < bank->num_sectors; i++)
522         {
523                 u32 sec_start = bank->sectors[i].offset;
524                 u32 sec_end = sec_start + bank->sectors[i].size;
525
526                 /* check if destination falls within the current sector */
527                 if ((check_address >= sec_start) && (check_address < sec_end))
528                 {
529                         /* check if destination ends in the current sector */
530                         if (offset + count < sec_end)
531                                 check_address = offset + count;
532                         else
533                                 check_address = sec_end;
534                 }
535         }
536
537         if (check_address != offset + count)
538                 return ERROR_FLASH_DST_OUT_OF_BANK;
539
540         /* multiple half words (2-byte) to be programmed? */
541         if (words_remaining > 0)
542         {
543                 /* try using a block write */
544                 if ((retval = str9x_write_block(bank, buffer, offset, words_remaining)) != ERROR_OK)
545                 {
546                         if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE)
547                         {
548                                 /* if block write failed (no sufficient working area),
549                                  * we use normal (slow) single dword accesses */
550                                 LOG_WARNING("couldn't use block writes, falling back to single memory accesses");
551                         }
552                         else if (retval == ERROR_FLASH_OPERATION_FAILED)
553                         {
554                                 LOG_ERROR("flash writing failed with error code: 0x%x", retval);
555                                 return ERROR_FLASH_OPERATION_FAILED;
556                         }
557                 }
558                 else
559                 {
560                         buffer += words_remaining * 2;
561                         address += words_remaining * 2;
562                         words_remaining = 0;
563                 }
564         }
565
566         while (words_remaining > 0)
567         {
568                 bank_adr = address & ~0x03;
569
570                 /* write data command */
571                 target_write_u16(target, bank_adr, 0x40);
572                 target_write_memory(target, address, 2, 1, buffer + bytes_written);
573
574                 /* get status command */
575                 target_write_u16(target, bank_adr, 0x70);
576
577                 int timeout;
578                 for (timeout=0; timeout<1000; timeout++)
579                 {
580                         target_read_u8(target, bank_adr, &status);
581                         if( status & 0x80 )
582                                 break;
583                         alive_sleep(1);
584                 }
585                 if (timeout==1000)
586                 {
587                         LOG_ERROR("write timed out");
588                         return ERROR_FAIL;
589                 }
590
591                 /* clear status reg and read array */
592                 target_write_u16(target, bank_adr, 0x50);
593                 target_write_u16(target, bank_adr, 0xFF);
594
595                 if (status & 0x10)
596                         return ERROR_FLASH_OPERATION_FAILED;
597                 else if (status & 0x02)
598                         return ERROR_FLASH_OPERATION_FAILED;
599
600                 bytes_written += 2;
601                 words_remaining--;
602                 address += 2;
603         }
604
605         if (bytes_remaining)
606         {
607                 u8 last_halfword[2] = {0xff, 0xff};
608                 int i = 0;
609
610                 while(bytes_remaining > 0)
611                 {
612                         last_halfword[i++] = *(buffer + bytes_written);
613                         bytes_remaining--;
614                         bytes_written++;
615                 }
616
617                 bank_adr = address & ~0x03;
618
619                 /* write data command */
620                 target_write_u16(target, bank_adr, 0x40);
621                 target_write_memory(target, address, 2, 1, last_halfword);
622
623                 /* query status command */
624                 target_write_u16(target, bank_adr, 0x70);
625
626                 int timeout;
627                 for (timeout=0; timeout<1000; timeout++)
628                 {
629                         target_read_u8(target, bank_adr, &status);
630                         if( status & 0x80 )
631                                 break;
632                         alive_sleep(1);
633                 }
634                 if (timeout==1000)
635                 {
636                         LOG_ERROR("write timed out");
637                         return ERROR_FAIL;
638                 }
639
640                 /* clear status reg and read array */
641                 target_write_u16(target, bank_adr, 0x50);
642                 target_write_u16(target, bank_adr, 0xFF);
643
644                 if (status & 0x10)
645                         return ERROR_FLASH_OPERATION_FAILED;
646                 else if (status & 0x02)
647                         return ERROR_FLASH_OPERATION_FAILED;
648         }
649
650         return ERROR_OK;
651 }
652
653 static int str9x_probe(struct flash_bank_s *bank)
654 {
655         return ERROR_OK;
656 }
657
658 #if 0
659 static int str9x_handle_part_id_command(struct command_context_s *cmd_ctx,
660                 char *cmd, char **args, int argc)
661 {
662         return ERROR_OK;
663 }
664 #endif
665
666 static int str9x_info(struct flash_bank_s *bank, char *buf, int buf_size)
667 {
668         snprintf(buf, buf_size, "str9x flash driver info" );
669         return ERROR_OK;
670 }
671
672 static int str9x_handle_flash_config_command(struct command_context_s *cmd_ctx,
673                 char *cmd, char **args, int argc)
674 {
675         str9x_flash_bank_t *str9x_info;
676         flash_bank_t *bank;
677         target_t *target = NULL;
678
679         if (argc < 5)
680         {
681                 return ERROR_COMMAND_SYNTAX_ERROR;
682         }
683
684         bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));
685         if (!bank)
686         {
687                 command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);
688                 return ERROR_OK;
689         }
690
691         str9x_info = bank->driver_priv;
692
693         target = bank->target;
694
695         if (bank->target->state != TARGET_HALTED)
696         {
697                 LOG_ERROR("Target not halted");
698                 return ERROR_TARGET_NOT_HALTED;
699         }
700
701         /* config flash controller */
702         target_write_u32(target, FLASH_BBSR, strtoul(args[1], NULL, 0));
703         target_write_u32(target, FLASH_NBBSR, strtoul(args[2], NULL, 0));
704         target_write_u32(target, FLASH_BBADR, (strtoul(args[3], NULL, 0) >> 2));
705         target_write_u32(target, FLASH_NBBADR, (strtoul(args[4], NULL, 0) >> 2));
706
707         /* set bit 18 instruction TCM order as per flash programming manual */
708         arm966e_write_cp15(target, 62, 0x40000);
709
710         /* enable flash bank 1 */
711         target_write_u32(target, FLASH_CR, 0x18);
712         return ERROR_OK;
713 }