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