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