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