]> git.sur5r.net Git - openocd/blob - src/flash/str7x.c
0419394e753bbfdc67c0be63ce91a5ec0e6006d7
[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 <str71_variant> <target#>
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[5], "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[5], "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
187         {
188                 ERROR("unknown STR7x variant");
189                 free(str7x_info);
190                 return ERROR_FLASH_BANK_INVALID;
191         }
192         
193         str7x_info->target = get_target_by_num(strtoul(args[6], NULL, 0));
194         if (!str7x_info->target)
195         {
196                 ERROR("no target '%s' configured", args[6]);
197                 exit(-1);
198         }
199
200         str7x_build_block_list(bank);
201         
202         str7x_info->write_algorithm = NULL;
203         
204         return ERROR_OK;
205 }
206
207 u32 str7x_status(struct flash_bank_s *bank)
208 {
209         str7x_flash_bank_t *str7x_info = bank->driver_priv;
210         target_t *target = str7x_info->target;
211         u32 retval;
212
213         target_read_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), &retval);
214
215         return retval;
216 }
217
218 u32 str7x_result(struct flash_bank_s *bank)
219 {
220         str7x_flash_bank_t *str7x_info = bank->driver_priv;
221         target_t *target = str7x_info->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         str7x_flash_bank_t *str7x_info = bank->driver_priv;
232         target_t *target = str7x_info->target;
233         u8 *buffer;
234         int i;
235         int nBytes;
236         
237         if ((first < 0) || (last > bank->num_sectors))
238                 return ERROR_FLASH_SECTOR_INVALID;
239
240         if (str7x_info->target->state != TARGET_HALTED)
241         {
242                 return ERROR_TARGET_NOT_HALTED;
243         }
244         
245         buffer = malloc(256);
246         
247         for (i = first; i <= last; i++)
248         {
249                 bank->sectors[i].is_erased = 1;
250
251                 target->type->read_memory(target, bank->base + bank->sectors[i].offset, 4, 256/4, buffer);
252                 
253                 for (nBytes = 0; nBytes < 256; nBytes++)
254                 {
255                         if (buffer[nBytes] != 0xFF)
256                         {
257                                 bank->sectors[i].is_erased = 0;
258                                 break;
259                         }
260                 }       
261         }
262         
263         free(buffer);
264
265         return ERROR_OK;
266 }
267
268 int str7x_protect_check(struct flash_bank_s *bank)
269 {
270         str7x_flash_bank_t *str7x_info = bank->driver_priv;
271         target_t *target = str7x_info->target;
272         
273         int i;
274         u32 retval;
275
276         if (str7x_info->target->state != TARGET_HALTED)
277         {
278                 return ERROR_TARGET_NOT_HALTED;
279         }
280
281         target_read_u32(target, str7x_get_flash_adr(bank, FLASH_NVWPAR), &retval);
282
283         for (i = 0; i < bank->num_sectors; i++)
284         {
285                 if (retval & str7x_info->sector_bits[i])
286                         bank->sectors[i].is_protected = 0;
287                 else
288                         bank->sectors[i].is_protected = 1;
289         }
290
291         return ERROR_OK;
292 }
293
294 int str7x_erase(struct flash_bank_s *bank, int first, int last)
295 {
296         str7x_flash_bank_t *str7x_info = bank->driver_priv;
297         target_t *target = str7x_info->target;
298         
299         int i;
300         u32 cmd;
301         u32 retval;
302         u32 b0_sectors = 0, b1_sectors = 0;
303         
304         if (str7x_info->target->state != TARGET_HALTED)
305         {
306                 return ERROR_TARGET_NOT_HALTED;
307         }
308         
309         for (i = first; i <= last; i++)
310         {
311                 if (str7x_info->sector_bank[i] == 0)
312                         b0_sectors |= str7x_info->sector_bits[i];
313                 else if (str7x_info->sector_bank[i] == 1)
314                         b1_sectors |= str7x_info->sector_bits[i];
315                 else
316                         ERROR("BUG: str7x_info->sector_bank[i] neither 0 nor 1 (%i)", str7x_info->sector_bank[i]);
317         }
318         
319         if (b0_sectors)
320         {
321                 DEBUG("b0_sectors: 0x%x", b0_sectors);
322                 
323                 /* clear FLASH_ER register */   
324                 target_write_u32(target, str7x_get_flash_adr(bank, FLASH_ER), 0x0);
325                 
326                 cmd = FLASH_SER;
327                 target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), cmd);
328                 
329                 cmd = b0_sectors;
330                 target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR1), cmd);
331                 
332                 cmd = FLASH_SER|FLASH_WMS;
333                 target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), cmd);
334                 
335                 while (((retval = str7x_status(bank)) & (FLASH_BSYA1|FLASH_BSYA2))){
336                         usleep(1000);
337                 }
338                 
339                 retval = str7x_result(bank);
340                 
341                 if (retval)
342                 {
343                         ERROR("error erasing flash bank, FLASH_ER: 0x%x", retval);
344                         return ERROR_FLASH_OPERATION_FAILED;
345                 }
346         }
347         
348         if (b1_sectors)
349         {
350                 DEBUG("b1_sectors: 0x%x", b1_sectors);
351                 
352                 /* clear FLASH_ER register */   
353                 target_write_u32(target, str7x_get_flash_adr(bank, FLASH_ER), 0x0);
354                 
355                 cmd = FLASH_SER;
356                 target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), cmd);
357                 
358                 cmd = b1_sectors;
359                 target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR1), cmd);
360                 
361                 cmd = FLASH_SER|FLASH_WMS;
362                 target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), cmd);
363                 
364                 while (((retval = str7x_status(bank)) & (FLASH_BSYA1|FLASH_BSYA2))){
365                         usleep(1000);
366                 }
367                 
368                 retval = str7x_result(bank);
369                 
370                 if (retval)
371                 {
372                         ERROR("error erasing flash bank, FLASH_ER: 0x%x", retval);
373                         return ERROR_FLASH_OPERATION_FAILED;
374                 }
375         }
376         
377         for (i = first; i <= last; i++)
378                 bank->sectors[i].is_erased = 1;
379
380         return ERROR_OK;
381 }
382
383 int str7x_protect(struct flash_bank_s *bank, int set, int first, int last)
384 {
385         str7x_flash_bank_t *str7x_info = bank->driver_priv;
386         target_t *target = str7x_info->target;
387         int i;
388         u32 cmd;
389         u32 retval;
390         u32 protect_blocks;
391         
392         if (str7x_info->target->state != TARGET_HALTED)
393         {
394                 return ERROR_TARGET_NOT_HALTED;
395         }
396         
397         protect_blocks = 0xFFFFFFFF;
398
399         if (set)
400         {
401                 for (i = first; i <= last; i++)
402                         protect_blocks &= ~(str7x_info->sector_bits[i]);
403         }
404         
405         /* clear FLASH_ER register */   
406         target_write_u32(target, str7x_get_flash_adr(bank, FLASH_ER), 0x0);
407
408         cmd = FLASH_SPR;
409         target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), cmd);
410         
411         cmd = str7x_get_flash_adr(bank, FLASH_NVWPAR);
412         target_write_u32(target, str7x_get_flash_adr(bank, FLASH_AR), cmd);
413         
414         cmd = protect_blocks;
415         target_write_u32(target, str7x_get_flash_adr(bank, FLASH_DR0), cmd);
416         
417         cmd = FLASH_SPR|FLASH_WMS;
418         target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), cmd);
419         
420         while (((retval = str7x_status(bank)) & (FLASH_BSYA1|FLASH_BSYA2))){
421                 usleep(1000);
422         }
423         
424         retval = str7x_result(bank);
425         
426         DEBUG("retval: 0x%8.8x", retval);
427         
428         if (retval & FLASH_ERER)
429                 return ERROR_FLASH_SECTOR_NOT_ERASED;
430         else if (retval & FLASH_WPF)
431                 return ERROR_FLASH_OPERATION_FAILED;
432
433         return ERROR_OK;
434 }
435
436 int str7x_write_block(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count)
437 {
438         str7x_flash_bank_t *str7x_info = bank->driver_priv;
439         target_t *target = str7x_info->target;
440         u32 buffer_size = 8192;
441         working_area_t *source;
442         u32 address = bank->base + offset;
443         reg_param_t reg_params[5];
444         armv4_5_algorithm_t armv4_5_info;
445         int retval;
446         
447         u32 str7x_flash_write_code[] = {
448                                         /* write:                               */
449                 0xe3a04201, /*  mov r4, #0x10000000     */
450                 0xe5824000, /*  str r4, [r2, #0x0]      */
451                 0xe5821010, /*  str r1, [r2, #0x10]     */
452                 0xe4904004, /*  ldr r4, [r0], #4        */
453                 0xe5824008, /*  str r4, [r2, #0x8]      */
454                 0xe4904004, /*  ldr r4, [r0], #4        */
455                 0xe582400c, /*  str r4, [r2, #0xc]      */
456                 0xe3a04209, /*  mov r4, #0x90000000     */
457                 0xe5824000, /*  str r4, [r2, #0x0]      */
458                             /* busy:                            */
459                 0xe5924000, /*  ldr r4, [r2, #0x0]      */
460                 0xe3140016, /*  tst r4, #0x16           */
461                 0x1afffffc, /*  bne busy                        */
462                 0xe5924014, /*  ldr r4, [r2, #0x14]     */
463                 0xe31400ff, /*  tst r4, #0xff           */
464                 0x03140c01, /*  tsteq r4, #0x100        */
465                 0x1a000002, /*  bne exit                        */
466                 0xe2811008, /*  add r1, r1, #0x8        */
467                 0xe2533001, /*  subs r3, r3, #1         */
468                 0x1affffec, /*  bne write                       */
469                                         /* exit:                                */
470                 0xeafffffe, /*  b exit                          */
471         };
472         
473         u8 str7x_flash_write_code_buf[80];
474         int i;
475         
476         /* flash write code */
477         if (!str7x_info->write_algorithm)
478         {
479                 if (target_alloc_working_area(target, 4 * 20, &str7x_info->write_algorithm) != ERROR_OK)
480                 {
481                         WARNING("no working area available, can't do block memory writes");
482                         return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
483                 };
484
485                 /* convert flash writing code into a buffer in target endianness */
486                 for (i = 0; i < 20; i++)
487                         target_buffer_set_u32(target, str7x_flash_write_code_buf + i*4, str7x_flash_write_code[i]);
488                         
489                 target_write_buffer(target, str7x_info->write_algorithm->address, 20 * 4, str7x_flash_write_code_buf);
490         }
491
492         /* memory buffer */
493         while (target_alloc_working_area(target, buffer_size, &source) != ERROR_OK)
494         {
495                 buffer_size /= 2;
496                 if (buffer_size <= 256)
497                 {
498                         /* if we already allocated the writing code, but failed to get a buffer, free the algorithm */
499                         if (str7x_info->write_algorithm)
500                                 target_free_working_area(target, str7x_info->write_algorithm);
501                         
502                         WARNING("no large enough working area available, can't do block memory writes");
503                         return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
504                 }
505         };
506         
507         armv4_5_info.common_magic = ARMV4_5_COMMON_MAGIC;
508         armv4_5_info.core_mode = ARMV4_5_MODE_SVC;
509         armv4_5_info.core_state = ARMV4_5_STATE_ARM;
510         
511         init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);
512         init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
513         init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT);
514         init_reg_param(&reg_params[3], "r3", 32, PARAM_OUT);
515         init_reg_param(&reg_params[4], "r4", 32, PARAM_IN);
516         
517         while (count > 0)
518         {
519                 u32 thisrun_count = (count > (buffer_size / 8)) ? (buffer_size / 8) : count;
520                 
521                 target_write_buffer(target, source->address, thisrun_count * 8, buffer);
522                 
523                 buf_set_u32(reg_params[0].value, 0, 32, source->address);
524                 buf_set_u32(reg_params[1].value, 0, 32, address);
525                 buf_set_u32(reg_params[2].value, 0, 32, str7x_get_flash_adr(bank, FLASH_CR0));
526                 buf_set_u32(reg_params[3].value, 0, 32, thisrun_count);
527         
528                 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)
529                 {
530                         ERROR("error executing str7x flash write algorithm");
531                         return ERROR_FLASH_OPERATION_FAILED;
532                 }
533         
534                 if (buf_get_u32(reg_params[4].value, 0, 32) != 0x00)
535                 {
536                         return ERROR_FLASH_OPERATION_FAILED;
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 ERROR_OK;
553 }
554
555 int str7x_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count)
556 {
557         str7x_flash_bank_t *str7x_info = bank->driver_priv;
558         target_t *target = str7x_info->target;
559         u32 dwords_remaining = (count / 8);
560         u32 bytes_remaining = (count & 0x00000007);
561         u32 address = bank->base + offset;
562         u32 bytes_written = 0;
563         u32 cmd;
564         u32 retval;
565         u32 check_address = offset;
566         int i;
567         
568         if (str7x_info->target->state != TARGET_HALTED)
569         {
570                 return ERROR_TARGET_NOT_HALTED;
571         }
572         
573         if (offset & 0x7)
574         {
575                 WARNING("offset 0x%x breaks required 8-byte alignment", offset);
576                 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
577         }
578         
579         for (i = 0; i < bank->num_sectors; i++)
580         {
581                 u32 sec_start = bank->sectors[i].offset;
582                 u32 sec_end = sec_start + bank->sectors[i].size;
583                 
584                 /* check if destination falls within the current sector */
585                 if ((check_address >= sec_start) && (check_address < sec_end))
586                 {
587                         /* check if destination ends in the current sector */
588                         if (offset + count < sec_end)
589                                 check_address = offset + count;
590                         else
591                                 check_address = sec_end;
592                 }
593         }
594         
595         if (check_address != offset + count)
596                 return ERROR_FLASH_DST_OUT_OF_BANK;
597                 
598         /* clear FLASH_ER register */   
599         target_write_u32(target, str7x_get_flash_adr(bank, FLASH_ER), 0x0);
600
601         /* multiple dwords (8-byte) to be programmed? */
602         if (dwords_remaining > 0) 
603         {
604                 /* try using a block write */
605                 if ((retval = str7x_write_block(bank, buffer, offset, dwords_remaining)) != ERROR_OK)
606                 {
607                         if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE)
608                         {
609                                 /* if block write failed (no sufficient working area),
610                                  * we use normal (slow) single dword accesses */ 
611                                 WARNING("couldn't use block writes, falling back to single memory accesses");
612                         }
613                         else if (retval == ERROR_FLASH_OPERATION_FAILED)
614                         {
615                                 /* if an error occured, we examine the reason, and quit */
616                                 retval = str7x_result(bank);
617                                 
618                                 ERROR("flash writing failed with error code: 0x%x", retval);
619                                 return ERROR_FLASH_OPERATION_FAILED;
620                         }
621                 }
622                 else
623                 {
624                         buffer += dwords_remaining * 8;
625                         address += dwords_remaining * 8;
626                         dwords_remaining = 0;
627                 }
628         }
629
630         while (dwords_remaining > 0)
631         {
632                 // command
633                 cmd = FLASH_DWPG;
634                 target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), cmd);
635                 
636                 // address
637                 target_write_u32(target, str7x_get_flash_adr(bank, FLASH_AR), address);
638                 
639                 // data word 1
640                 target->type->write_memory(target, str7x_get_flash_adr(bank, FLASH_DR0), 4, 1, buffer + bytes_written);
641                 bytes_written += 4;
642                 
643                 // data word 2
644                 target->type->write_memory(target, str7x_get_flash_adr(bank, FLASH_DR1), 4, 1, buffer + bytes_written);
645                 bytes_written += 4;
646                 
647                 /* start programming cycle */
648                 cmd = FLASH_DWPG | FLASH_WMS;
649                 target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), cmd);
650                 
651                 while (((retval = str7x_status(bank)) & (FLASH_BSYA1 | FLASH_BSYA2)))
652                 {
653                         usleep(1000);
654                 }
655                 
656                 retval = str7x_result(bank);
657                 
658                 if (retval & FLASH_PGER)
659                         return ERROR_FLASH_OPERATION_FAILED;
660                 else if (retval & FLASH_WPF)
661                         return ERROR_FLASH_OPERATION_FAILED;
662
663                 dwords_remaining--;
664                 address += 8;
665         }
666         
667         if (bytes_remaining)
668         {
669                 u8 last_dword[8] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
670                 int i = 0;
671                                 
672                 while(bytes_remaining > 0)
673                 {
674                         last_dword[i++] = *(buffer + bytes_written); 
675                         bytes_remaining--;
676                         bytes_written++;
677                 }
678                 
679                 // command
680                 cmd = FLASH_DWPG;
681                 target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), cmd);
682                 
683                 // address
684                 target_write_u32(target, str7x_get_flash_adr(bank, FLASH_AR), address);
685                 
686                 // data word 1
687                 target->type->write_memory(target, str7x_get_flash_adr(bank, FLASH_DR0), 4, 1, last_dword);
688                 bytes_written += 4;
689                 
690                 // data word 2
691                 target->type->write_memory(target, str7x_get_flash_adr(bank, FLASH_DR1), 4, 1, last_dword + 4);
692                 bytes_written += 4;
693                 
694                 /* start programming cycle */
695                 cmd = FLASH_DWPG | FLASH_WMS;
696                 target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), cmd);
697                 
698                 while (((retval = str7x_status(bank)) & (FLASH_BSYA1 | FLASH_BSYA2)))
699                 {
700                         usleep(1000);
701                 }
702                 
703                 retval = str7x_result(bank);
704                 
705                 if (retval & FLASH_PGER)
706                         return ERROR_FLASH_OPERATION_FAILED;
707                 else if (retval & FLASH_WPF)
708                         return ERROR_FLASH_OPERATION_FAILED;
709         }
710                 
711         return ERROR_OK;
712 }
713
714 int str7x_probe(struct flash_bank_s *bank)
715 {
716         return ERROR_OK;
717 }
718
719 int str7x_handle_part_id_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
720 {
721         return ERROR_OK;
722 }
723
724 int str7x_erase_check(struct flash_bank_s *bank)
725 {
726         return str7x_blank_check(bank, 0, bank->num_sectors - 1);
727 }
728
729 int str7x_info(struct flash_bank_s *bank, char *buf, int buf_size)
730 {
731         snprintf(buf, buf_size, "str7x flash driver info" );
732         return ERROR_OK;
733 }