helper/command: change prototype of command_print/command_print_sameline
[fw/openocd] / src / flash / nor / niietcm4.c
1 /***************************************************************************
2  *   Copyright (C) 2015 by Bogdan Kolbov                                   *
3  *   kolbov@niiet.ru                                                       *
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, see <http://www.gnu.org/licenses/>. *
17  ***************************************************************************/
18
19 #ifdef HAVE_CONFIG_H
20 #include "config.h"
21 #endif
22
23 #include "imp.h"
24 #include <helper/binarybuffer.h>
25 #include <target/algorithm.h>
26 #include <target/armv7m.h>
27
28 #define FLASH_DRIVER_VER                        0x00010000
29 #define CHIPID_ADDR                                     0xF0000000
30 #define K1921VK01T_ID                           0x00000000
31
32 /*==============================================================================
33  *                                                      FLASH CONTROL REGS
34  *==============================================================================
35  */
36
37 #define MAIN_MEM_TYPE                           0
38 #define INFO_MEM_TYPE                           1
39 #define SERVICE_MODE_ERASE_ADDR         0x80030164
40 #define MAGIC_KEY                                       0xA442
41
42 /*-- BOOTFLASH ---------------------------------------------------------------*/
43 #define BOOTFLASH_BASE                          0xA001C000
44 #define FMA                                                     (BOOTFLASH_BASE + 0x00)
45 #define FMD1                                            (BOOTFLASH_BASE + 0x04)
46 #define FMC                                                     (BOOTFLASH_BASE + 0x08)
47 #define FCIS                                            (BOOTFLASH_BASE + 0x0C)
48 #define FCIM                                            (BOOTFLASH_BASE + 0x10)
49 #define FCIC                                            (BOOTFLASH_BASE + 0x14)
50 #define FMD2                                            (BOOTFLASH_BASE + 0x50)
51 #define FMD3                                            (BOOTFLASH_BASE + 0x54)
52 #define FMD4                                            (BOOTFLASH_BASE + 0x58)
53
54
55 /*---- FMC: Command register */
56 #define FMC_WRITE                                       (1<<0)                          /* Writing in main region */
57 #define FMC_PAGE_ERASE                          (1<<1)                          /* Page erase the main region */
58 #define FMC_FULL_ERASE                          (1<<2)                          /* Erase full flash */
59 #define FMC_WRITE_IFB                           (1<<4)                          /* Writing in info region */
60 #define FMC_PAGEERASE_IFB                       (1<<5)                          /* Erase page of info region */
61 #define FMC_MAGIC_KEY                           (MAGIC_KEY<<16)         /* Operation run command */
62
63 /*---- FCIS: Status register */
64 #define FCIS_OP_CMLT                            (1<<0)                          /* Completion flag operation */
65 #define FCIS_OP_ERROR                           (1<<1)                          /* Flag operation error */
66
67 /*---- FCIC: CLear status register */
68 #define FCIC_CLR_OPCMLT                         (1<<0)                          /* Cleare completion flag in register FCIS */
69 #define FCIC_CLR_OPERROR                        (1<<1)                          /* Cleare error flag in register FCIS */
70
71 /*-- USERFLASH ---------------------------------------------------------------*/
72 #define USERFLASH_PAGE_SIZE                     256
73 #define USERFLASH_PAGE_TOTALNUM         256
74
75 #define USERFLASH_BASE                          0xA0022000
76 #define UFMA                                            (USERFLASH_BASE + 0x00)
77 #define UFMD                                            (USERFLASH_BASE + 0x04)
78 #define UFMC                                            (USERFLASH_BASE + 0x08)
79 #define UFCIS                                           (USERFLASH_BASE + 0x0C)
80 #define UFCIM                                           (USERFLASH_BASE + 0x10)
81 #define UFCIC                                           (USERFLASH_BASE + 0x14)
82
83 /*---- UFMC: Command register */
84 #define UFMC_WRITE                                      (1<<0)                          /* Writing in main region */
85 #define UFMC_PAGE_ERASE                         (1<<1)                          /* Paged erase the main region */
86 #define UFMC_FULL_ERASE                         (1<<2)                          /* Erase full flash */
87 #define UFMC_READ                                       (1<<3)                          /* Reading from main region */
88 #define UFMC_WRITE_IFB                          (1<<4)                          /* Writing in info region */
89 #define UFMC_PAGEERASE_IFB                      (1<<5)                          /* Erase page of info region */
90 #define UFMC_READ_IFB                           (1<<6)                          /* Reading from info region */
91 #define UFMC_MAGIC_KEY                          (MAGIC_KEY<<16)         /* Operation run command */
92
93 /*---- UFCIS: Status register */
94 #define UFCIS_OP_CMLT                           (1<<0)                          /* Completion flag operation */
95 #define UFCIS_OP_ERROR                          (1<<1)                          /* Flag operation error */
96
97 /*---- UFCIC: CLear status register */
98 #define UFCIC_CLR_OPCMLT                        (1<<0)                          /* Cleared completion flag in register FCIS */
99 #define UFCIC_CLR_OPERROR                       (1<<1)                          /* Cleared error flag in register FCIS */
100
101 /*---- In info userflash address space */
102 #define INFOWORD0_ADDR                          0x00
103 #define INFOWORD0_BOOTFROM_IFB          (1<<0)                          /* Boot from bootflash or bootflash_ifb */
104 #define INFOWORD0_EN_GPIO                       (1<<1)                          /* Remap to 0x00000000 extmem or bootflash */
105 #define INFOWORD0_BOOTFROM_IFB_POS      0
106 #define INFOWORD0_EN_GPIO_POS           1
107 #define INFOWORD0_EXTMEM_SEL_POS        3                                       /* Choose altfunc of gpio to work with extmem */
108
109 #define INFOWORD1_ADDR                          0x01
110 #define INFOWORD1_PINNUM_POS            0                                       /* Choose gpio pin number to control extmem boot */
111 #define INFOWORD1_PORTNUM_POS           4                                       /* Choose gpio port to control extmem boot */
112
113 #define INFOWORD2_ADDR                          0x02
114 #define INFOWORD2_LOCK_IFB_BF           (1<<0)                          /* Protect info part of bootflash */
115
116 #define INFOWORD3_ADDR                          0x03
117 #define INFOWORD3_LOCK_IFB_UF           (1<<0)                          /* Protect info part of userflash */
118
119 #define BF_LOCK_ADDR                            0x40
120 #define UF_LOCK_ADDR                            0x80
121
122 /**
123  * Private data for flash driver.
124  */
125 struct niietcm4_flash_bank {
126         /* target params */
127         bool probed;
128         uint32_t chipid;
129         char *chip_name;
130         char chip_brief[4096];
131         /* not mapped userflash params */
132         uint32_t uflash_width;
133         uint32_t uflash_size;
134         uint32_t uflash_pagetotal;
135         uint32_t uflash_info_size;
136         uint32_t uflash_info_pagetotal;
137         /* boot params */
138         bool bflash_info_remap;
139         char *extmem_boot_port;
140         uint32_t extmem_boot_pin;
141         uint32_t extmem_boot_altfunc;
142         bool extmem_boot;
143 };
144
145 /*==============================================================================
146  *                                                      HELPER FUNCTIONS
147  *==============================================================================
148  */
149
150 /**
151  * Wait while operation with bootflash being performed and check result status
152  */
153 static int niietcm4_opstatus_check(struct flash_bank *bank)
154 {
155         struct target *target = bank->target;
156         int retval;
157         int timeout = 5000;
158
159         uint32_t flash_status;
160         retval = target_read_u32(target, FCIS, &flash_status);
161         if (retval != ERROR_OK)
162                 return retval;
163
164         while (flash_status == 0x00) {
165                 retval = target_read_u32(target, FCIS, &flash_status);
166                 if (retval != ERROR_OK)
167                         return retval;
168                 if (timeout-- <= 0) {
169                         LOG_ERROR("Bootflash operation timeout");
170                         return ERROR_FLASH_OPERATION_FAILED;
171                         }
172                 busy_sleep(1);  /* can use busy sleep for short times. */
173         }
174         if (flash_status == FCIS_OP_ERROR) {
175                 LOG_ERROR("Bootflash operation error");
176                 return ERROR_FLASH_OPERATION_FAILED;
177         }
178         /* clear status */
179         uint32_t flash_cmd = FCIC_CLR_OPCMLT | FCIC_CLR_OPERROR;
180         retval = target_write_u32(target, FCIC, flash_cmd);
181         if (retval != ERROR_OK)
182                 return retval;
183
184         return retval;
185 }
186
187 /**
188  * Wait while operation with userflash being performed and check result status
189  */
190 static int niietcm4_uopstatus_check(struct flash_bank *bank)
191 {
192         struct target *target = bank->target;
193         int retval;
194         int timeout = 5000;
195
196         uint32_t uflash_status;
197         retval = target_read_u32(target, UFCIS, &uflash_status);
198         if (retval != ERROR_OK)
199                 return retval;
200
201         while (uflash_status == 0x00) {
202                 retval = target_read_u32(target, UFCIS, &uflash_status);
203                 if (retval != ERROR_OK)
204                         return retval;
205                 if (timeout-- <= 0) {
206                         LOG_ERROR("Userflash operation timeout");
207                         return ERROR_FLASH_OPERATION_FAILED;
208                         }
209                 busy_sleep(1);  /* can use busy sleep for short times. */
210         }
211         if (uflash_status == UFCIS_OP_ERROR) {
212                 LOG_ERROR("Userflash operation error");
213                 return ERROR_FLASH_OPERATION_FAILED;
214         }
215         /* clear status */
216         uint32_t uflash_cmd = UFCIC_CLR_OPCMLT | UFCIC_CLR_OPERROR;
217         retval = target_write_u32(target, UFCIC, uflash_cmd);
218         if (retval != ERROR_OK)
219                 return retval;
220
221         return retval;
222 }
223
224 /**
225  * Dump page of userflash region.
226  * If we want to change some settings, we have to dump it full, because userflash is flash(not EEPROM).
227  * And correct write to flash can be performed only after erase.
228  * So without dump, changing one registers will clear others.
229  */
230 static int niietcm4_dump_uflash_page(struct flash_bank *bank, uint32_t *dump, int page_num, int mem_type)
231 {
232         struct target *target = bank->target;
233         int i;
234         int retval = ERROR_OK;
235
236         uint32_t uflash_cmd;
237         if (mem_type == INFO_MEM_TYPE)
238                 uflash_cmd = UFMC_MAGIC_KEY | UFMC_READ_IFB;
239         else
240                 uflash_cmd = UFMC_MAGIC_KEY | UFMC_READ;
241
242         int first = page_num*USERFLASH_PAGE_SIZE;
243         int last = first + USERFLASH_PAGE_SIZE;
244
245         for (i = first; i < last; i++) {
246                 retval = target_write_u32(target, UFMA, i);
247                 if (retval != ERROR_OK)
248                         return retval;
249                 retval = target_write_u32(target, UFMC, uflash_cmd);
250                 if (retval != ERROR_OK)
251                         return retval;
252                 retval = niietcm4_uopstatus_check(bank);
253                 if (retval != ERROR_OK)
254                         return retval;
255                 retval = target_read_u32(target, UFMD, &dump[i]);
256                 if (retval != ERROR_OK)
257                         return retval;
258         }
259
260         return retval;
261 }
262
263 /**
264  * Load modified page dump to userflash region page.
265  */
266 static int niietcm4_load_uflash_page(struct flash_bank *bank, uint32_t *dump, int page_num, int mem_type)
267 {
268         struct target *target = bank->target;
269         int i;
270         int retval = ERROR_OK;
271
272         uint32_t uflash_cmd;
273         if (mem_type == INFO_MEM_TYPE)
274                 uflash_cmd = UFMC_MAGIC_KEY | UFMC_WRITE_IFB;
275         else
276                 uflash_cmd = UFMC_MAGIC_KEY | UFMC_WRITE;
277
278         int first = page_num*USERFLASH_PAGE_SIZE;
279         int last = first + USERFLASH_PAGE_SIZE;
280
281         for (i = first; i < last; i++) {
282                 retval = target_write_u32(target, UFMA, i);
283                 if (retval != ERROR_OK)
284                         return retval;
285                 retval = target_write_u32(target, UFMD, dump[i]);
286                 if (retval != ERROR_OK)
287                         return retval;
288                 retval = target_write_u32(target, UFMC, uflash_cmd);
289                 if (retval != ERROR_OK)
290                         return retval;
291                 retval = niietcm4_uopstatus_check(bank);
292                 if (retval != ERROR_OK)
293                         return retval;
294         }
295
296         return retval;
297 }
298
299 /**
300  * Erase one page of userflash info or main region
301  */
302 static int niietcm4_uflash_page_erase(struct flash_bank *bank, int page_num, int mem_type)
303 {
304         struct target *target = bank->target;
305         int retval;
306
307         uint32_t uflash_cmd;
308         if (mem_type == INFO_MEM_TYPE)
309                 uflash_cmd = UFMC_MAGIC_KEY | UFMC_PAGEERASE_IFB;
310         else
311                 uflash_cmd = UFMC_MAGIC_KEY | UFMC_PAGE_ERASE;
312
313         retval = target_write_u32(target, UFMA, page_num*USERFLASH_PAGE_SIZE);
314         if (retval != ERROR_OK)
315                 return retval;
316         retval = target_write_u32(target, UFMD, 0xFF);
317         if (retval != ERROR_OK)
318                 return retval;
319         retval = target_write_u32(target, UFMC, uflash_cmd);
320         if (retval != ERROR_OK)
321                 return retval;
322         /* status check */
323         retval = niietcm4_uopstatus_check(bank);
324         if (retval != ERROR_OK)
325                         return retval;
326
327         return retval;
328 }
329
330 /**
331  * Enable or disable protection of userflash pages
332  */
333 static int niietcm4_uflash_protect(struct flash_bank *bank, int mem_type, int set, int first, int last)
334 {
335         int retval;
336         if (mem_type == INFO_MEM_TYPE) {
337                 /* read dump */
338                 uint32_t uflash_dump[USERFLASH_PAGE_SIZE];
339                 retval = niietcm4_dump_uflash_page(bank, uflash_dump, 0, 1);
340                 if (retval != ERROR_OK)
341                         return retval;
342                 /* modify dump */
343                 if (set)
344                         uflash_dump[INFOWORD2_ADDR] &= ~INFOWORD3_LOCK_IFB_UF;
345                 else
346                         uflash_dump[INFOWORD2_ADDR] |= INFOWORD3_LOCK_IFB_UF;
347                 /* erase page 0 userflash */
348                 retval = niietcm4_uflash_page_erase(bank, 0, 1);
349                 if (retval != ERROR_OK)
350                         return retval;
351                 /* write dump to userflash */
352                 retval = niietcm4_load_uflash_page(bank, uflash_dump, 0, 1);
353                 if (retval != ERROR_OK)
354                         return retval;
355         } else {
356                 /* read dump */
357                 uint32_t uflash_dump[USERFLASH_PAGE_SIZE];
358                 retval = niietcm4_dump_uflash_page(bank, uflash_dump, 0, 1);
359                 if (retval != ERROR_OK)
360                         return retval;
361                 /* modify dump */
362                 for (int i = first; i <= last; i++)     {
363                         uint32_t reg_num = i/8;
364                         uint32_t bit_num = i%8;
365                         if (set)
366                                 uflash_dump[UF_LOCK_ADDR+reg_num] &= ~(1<<bit_num);
367                         else
368                                 uflash_dump[UF_LOCK_ADDR+reg_num] |= (1<<bit_num);
369                 }
370                 /* erase page 0 info userflash */
371                 retval = niietcm4_uflash_page_erase(bank, 0, 1);
372                 if (retval != ERROR_OK)
373                         return retval;
374                 /* write dump to userflash */
375                 retval = niietcm4_load_uflash_page(bank, uflash_dump,  0, 1);
376                 if (retval != ERROR_OK)
377                         return retval;
378         }
379
380         return retval;
381 }
382
383 /*==============================================================================
384  *                                                      FLASH COMMANDS
385  *==============================================================================
386  */
387 COMMAND_HANDLER(niietcm4_handle_uflash_read_byte_command)
388 {
389         if (CMD_ARGC < 3)
390                 return ERROR_COMMAND_SYNTAX_ERROR;
391
392         struct flash_bank *bank;
393         int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
394         if (retval != ERROR_OK)
395                 return retval;
396         struct target *target = bank->target;
397
398         /* skip over flash bank */
399         CMD_ARGC--;
400         CMD_ARGV++;
401
402         uint32_t uflash_addr;
403         uint32_t uflash_cmd;
404         uint32_t uflash_data;
405
406         if (strcmp("info", CMD_ARGV[0]) == 0)
407                         uflash_cmd = UFMC_MAGIC_KEY | UFMC_READ_IFB;
408         else if (strcmp("main", CMD_ARGV[0]) == 0)
409                 uflash_cmd = UFMC_MAGIC_KEY | UFMC_READ;
410         else
411                 return ERROR_COMMAND_SYNTAX_ERROR;
412
413         COMMAND_PARSE_NUMBER(uint, CMD_ARGV[1], uflash_addr);
414
415         retval = target_write_u32(target, UFMA, uflash_addr);
416         if (retval != ERROR_OK)
417                 return retval;
418         retval = target_write_u32(target, UFMC, uflash_cmd);
419         if (retval != ERROR_OK)
420                 return retval;
421         /* status check */
422         retval = niietcm4_uopstatus_check(bank);
423         if (retval != ERROR_OK)
424                 return retval;
425         retval = target_read_u32(target, UFMD, &uflash_data);
426         if (retval != ERROR_OK)
427                 return retval;
428         command_print(CMD,  "Read userflash %s region:\n"
429                                                         "address = 0x%04x,\n"
430                                                         "value   = 0x%02x.", CMD_ARGV[0], uflash_addr, uflash_data);
431         return retval;
432 }
433
434 COMMAND_HANDLER(niietcm4_handle_uflash_write_byte_command)
435 {
436         if (CMD_ARGC < 4)
437                 return ERROR_COMMAND_SYNTAX_ERROR;
438
439         struct flash_bank *bank;
440         int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
441         if (retval != ERROR_OK)
442                 return retval;
443         struct target *target = bank->target;
444
445         if (target->state != TARGET_HALTED) {
446                 LOG_ERROR("Target not halted");
447                 return ERROR_TARGET_NOT_HALTED;
448         }
449
450         /* skip over flash bank */
451         CMD_ARGC--;
452         CMD_ARGV++;
453
454         uint32_t uflash_addr;
455         uint32_t uflash_data;
456         int mem_type;
457
458         if (strcmp("info", CMD_ARGV[0]) == 0)
459                 mem_type = 1;
460         else if (strcmp("main", CMD_ARGV[0]) == 0)
461                 mem_type = 0;
462         else
463                 return ERROR_COMMAND_SYNTAX_ERROR;
464
465         COMMAND_PARSE_NUMBER(uint, CMD_ARGV[1], uflash_addr);
466         COMMAND_PARSE_NUMBER(uint, CMD_ARGV[2], uflash_data);
467
468         int page_num = uflash_addr/USERFLASH_PAGE_SIZE;
469
470         command_print(CMD, "Write userflash %s region:\n"
471                                                    "address = 0x%04x,\n"
472                                                    "value   = 0x%02x.\n"
473                                                    "Please wait ... ", CMD_ARGV[0], uflash_addr, uflash_data);
474         /* dump */
475         uint32_t uflash_dump[USERFLASH_PAGE_SIZE];
476         niietcm4_dump_uflash_page(bank, uflash_dump, page_num, mem_type);
477
478         /* modify dump */
479         uflash_dump[uflash_addr%USERFLASH_PAGE_SIZE] = uflash_data;
480
481         /* erase page userflash */
482         niietcm4_uflash_page_erase(bank, page_num, mem_type);
483
484         /* write dump to userflash */
485         niietcm4_load_uflash_page(bank, uflash_dump, page_num, mem_type);
486         command_print(CMD, "done!");
487         return retval;
488 }
489
490 COMMAND_HANDLER(niietcm4_handle_uflash_full_erase_command)
491 {
492         if (CMD_ARGC < 1)
493                 return ERROR_COMMAND_SYNTAX_ERROR;
494
495         struct flash_bank *bank;
496         int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
497         if (retval != ERROR_OK)
498                 return retval;
499         struct target *target = bank->target;
500
501         if (target->state != TARGET_HALTED) {
502                 LOG_ERROR("Target not halted");
503                 return ERROR_TARGET_NOT_HALTED;
504         }
505
506         uint32_t uflash_addr = 0;
507         uint32_t uflash_data = 0xFF;
508         uint32_t uflash_cmd = UFMC_MAGIC_KEY | UFMC_FULL_ERASE;
509
510         retval = target_write_u32(target, UFMA, uflash_addr);
511         if (retval != ERROR_OK)
512                 return retval;
513         retval = target_write_u32(target, UFMD, uflash_data);
514         if (retval != ERROR_OK)
515                 return retval;
516         retval = target_write_u32(target, UFMC, uflash_cmd);
517         if (retval != ERROR_OK)
518                 return retval;
519         /* status check */
520         retval = niietcm4_uopstatus_check(bank);
521         if (retval != ERROR_OK)
522                 return retval;
523         command_print(CMD, "Userflash full erase done!");
524
525         return retval;
526 }
527
528 COMMAND_HANDLER(niietcm4_handle_uflash_erase_command)
529 {
530         if (CMD_ARGC < 4)
531                 return ERROR_COMMAND_SYNTAX_ERROR;
532
533         struct flash_bank *bank;
534         int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
535         if (retval != ERROR_OK)
536                 return retval;
537         struct target *target = bank->target;
538
539         if (target->state != TARGET_HALTED) {
540                 LOG_ERROR("Target not halted");
541                 return ERROR_TARGET_NOT_HALTED;
542         }
543
544         /* skip over flash bank */
545         CMD_ARGC--;
546         CMD_ARGV++;
547
548         unsigned int first, last;
549         int mem_type;
550
551         if (strcmp("info", CMD_ARGV[0]) == 0)
552                         mem_type = 1;
553         else if (strcmp("main", CMD_ARGV[0]) == 0)
554                 mem_type = 0;
555         else
556                 return ERROR_COMMAND_SYNTAX_ERROR;
557
558         COMMAND_PARSE_NUMBER(uint, CMD_ARGV[1], first);
559         COMMAND_PARSE_NUMBER(uint, CMD_ARGV[2], last);
560         for (unsigned int i = first; i <= last; i++) {
561                 retval = niietcm4_uflash_page_erase(bank, i, mem_type);
562                 if (retval != ERROR_OK)
563                         return retval;
564         }
565
566         command_print(CMD, "Erase %s userflash pages %d through %d done!", CMD_ARGV[0], first, last);
567
568         return retval;
569 }
570
571 COMMAND_HANDLER(niietcm4_handle_uflash_protect_check_command)
572 {
573         if (CMD_ARGC < 2)
574                 return ERROR_COMMAND_SYNTAX_ERROR;
575
576         struct flash_bank *bank;
577         int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
578         if (retval != ERROR_OK)
579                 return retval;
580
581         struct target *target = bank->target;
582         if (target->state != TARGET_HALTED) {
583                 LOG_ERROR("Target not halted");
584                 return ERROR_TARGET_NOT_HALTED;
585         }
586
587         /* skip over flash bank */
588         CMD_ARGC--;
589         CMD_ARGV++;
590
591         int mem_type;
592         if (strcmp("info", CMD_ARGV[0]) == 0)
593                 mem_type = 1;
594         else if (strcmp("main", CMD_ARGV[0]) == 0)
595                 mem_type = 0;
596         else
597                 return ERROR_COMMAND_SYNTAX_ERROR;
598
599         int i, j;
600         uint32_t uflash_addr;
601         uint32_t uflash_cmd;
602         uint32_t uflash_data;
603
604         /* chose between main userflash and info userflash */
605         if (mem_type == INFO_MEM_TYPE) {
606                 uflash_addr = INFOWORD3_ADDR;
607                 uflash_cmd = UFMC_MAGIC_KEY | UFMC_READ_IFB;
608                 retval = target_write_u32(target, UFMA, uflash_addr);
609                 if (retval != ERROR_OK)
610                         return retval;
611                 retval = target_write_u32(target, UFMC, uflash_cmd);
612                 if (retval != ERROR_OK)
613                         return retval;
614
615                 /* status check */
616                 retval = niietcm4_uopstatus_check(bank);
617                 if (retval != ERROR_OK)
618                         return retval;
619                 retval = target_read_u32(target, UFMD, &uflash_data);
620                 if (retval != ERROR_OK)
621                         return retval;
622
623                 if (uflash_data & INFOWORD3_LOCK_IFB_UF)
624                         command_print(CMD, "All sectors of info userflash are not protected!");
625                 else
626                         command_print(CMD, "All sectors of info userflash are protected!");
627         } else {
628                 uflash_addr = UF_LOCK_ADDR;
629                 uflash_cmd = UFMC_MAGIC_KEY | UFMC_READ_IFB;
630                 for (i = 0; i < USERFLASH_PAGE_TOTALNUM/8; i++) {
631                         retval = target_write_u32(target, UFMA, uflash_addr);
632                         if (retval != ERROR_OK)
633                                 return retval;
634                         retval = target_write_u32(target, UFMC, uflash_cmd);
635                         if (retval != ERROR_OK)
636                                 return retval;
637
638                         /* status check */
639                         retval = niietcm4_uopstatus_check(bank);
640                         if (retval != ERROR_OK)
641                                 return retval;
642                         retval = target_read_u32(target, UFMD, &uflash_data);
643                         if (retval != ERROR_OK)
644                                 return retval;
645
646                         for (j = 0; j < 8; j++) {
647                                 if (uflash_data & 0x1)
648                                         command_print(CMD, "Userflash sector #%03d: 0x%04x (0x100) is not protected!",
649                                                                                         i*8+j, (i*8+j)*USERFLASH_PAGE_SIZE);
650                                 else
651                                         command_print(CMD, "Userflash sector #%03d: 0x%04x (0x100) is protected!",
652                                                                                         i*8+j, (i*8+j)*USERFLASH_PAGE_SIZE);
653                                 uflash_data = uflash_data >> 1;
654                         }
655                         uflash_addr++;
656                 }
657         }
658
659         return retval;
660 }
661
662 COMMAND_HANDLER(niietcm4_handle_uflash_protect_command)
663 {
664         if (CMD_ARGC < 5)
665                 return ERROR_COMMAND_SYNTAX_ERROR;
666
667         struct flash_bank *bank;
668         int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
669         if (retval != ERROR_OK)
670                 return retval;
671         struct target *target = bank->target;
672
673         if (target->state != TARGET_HALTED) {
674                 LOG_ERROR("Target not halted");
675                 return ERROR_TARGET_NOT_HALTED;
676         }
677
678         /* skip over flash bank */
679         CMD_ARGC--;
680         CMD_ARGV++;
681
682         int mem_type;
683         if (strcmp("info", CMD_ARGV[0]) == 0)
684                 mem_type = 1;
685         else if (strcmp("main", CMD_ARGV[0]) == 0)
686                 mem_type = 0;
687         else
688                 return ERROR_COMMAND_SYNTAX_ERROR;
689
690         unsigned int first, last;
691         COMMAND_PARSE_NUMBER(uint, CMD_ARGV[1], first);
692         COMMAND_PARSE_NUMBER(uint, CMD_ARGV[2], last);
693
694         int set;
695         if (strcmp("on", CMD_ARGV[3]) == 0) {
696                 command_print(CMD, "Try to enable %s userflash sectors %d through %d protection. Please wait ... ",
697                                                                 CMD_ARGV[0], first, last);
698                 set = 1;
699         } else if (strcmp("off", CMD_ARGV[3]) == 0) {
700                 command_print(CMD, "Try to disable %s userflash sectors %d through %d protection. Please wait ... ",
701                                                                 CMD_ARGV[0], first, last);
702                 set = 0;
703         } else
704                 return ERROR_COMMAND_SYNTAX_ERROR;
705
706         retval = niietcm4_uflash_protect(bank, mem_type, set, first, last);
707                 if (retval != ERROR_OK)
708                         return retval;
709
710         command_print(CMD, "done!");
711         return retval;
712 }
713
714 COMMAND_HANDLER(niietcm4_handle_bflash_info_remap_command)
715 {
716         if (CMD_ARGC < 2)
717                 return ERROR_COMMAND_SYNTAX_ERROR;
718
719         struct flash_bank *bank;
720         int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
721         if (retval != ERROR_OK)
722                 return retval;
723         struct target *target = bank->target;
724
725         if (target->state != TARGET_HALTED) {
726                 LOG_ERROR("Target not halted");
727                 return ERROR_TARGET_NOT_HALTED;
728         }
729
730         /* skip over flash bank */
731         CMD_ARGC--;
732         CMD_ARGV++;
733
734         int set;
735         if (strcmp("on", CMD_ARGV[0]) == 0) {
736                 command_print(CMD, "Try to enable bootflash info region remap. Please wait ...");
737                 set = 1;
738         } else if (strcmp("off", CMD_ARGV[0]) == 0) {
739                 command_print(CMD, "Try to disable bootflash info region remap. Please wait ...");
740                 set = 0;
741         } else
742                 return ERROR_COMMAND_SYNTAX_ERROR;
743
744         /* dump */
745         uint32_t uflash_dump[USERFLASH_PAGE_SIZE];
746         niietcm4_dump_uflash_page(bank, uflash_dump, 0, 1);
747
748         /* modify dump */
749         if (set)
750                 uflash_dump[INFOWORD0_ADDR] &= ~INFOWORD0_BOOTFROM_IFB;
751         else
752                 uflash_dump[INFOWORD0_ADDR] |= INFOWORD0_BOOTFROM_IFB;
753
754         /* erase page userflash */
755         niietcm4_uflash_page_erase(bank, 0, 1);
756
757         /* write dump to userflash */
758         niietcm4_load_uflash_page(bank, uflash_dump, 0, 1);
759         command_print(CMD, "done!");
760
761         return retval;
762 }
763
764 COMMAND_HANDLER(niietcm4_handle_extmem_cfg_command)
765 {
766         if (CMD_ARGC < 4)
767                 return ERROR_COMMAND_SYNTAX_ERROR;
768
769         struct flash_bank *bank;
770         int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
771         if (retval != ERROR_OK)
772                 return retval;
773         struct target *target = bank->target;
774
775         if (target->state != TARGET_HALTED) {
776                 LOG_ERROR("Target not halted");
777                 return ERROR_TARGET_NOT_HALTED;
778         }
779
780         /* skip over flash bank */
781         CMD_ARGC--;
782         CMD_ARGV++;
783
784         uint32_t port;
785         if (strcmp("gpioa", CMD_ARGV[0]) == 0)
786                 port = 8;
787         else if (strcmp("gpiob", CMD_ARGV[0]) == 0)
788                 port = 9;
789         else if (strcmp("gpioc", CMD_ARGV[0]) == 0)
790                 port = 10;
791         else if (strcmp("gpiod", CMD_ARGV[0]) == 0)
792                 port = 11;
793         else if (strcmp("gpioe", CMD_ARGV[0]) == 0)
794                 port = 12;
795         else if (strcmp("gpiof", CMD_ARGV[0]) == 0)
796                 port = 13;
797         else if (strcmp("gpiog", CMD_ARGV[0]) == 0)
798                 port = 14;
799         else if (strcmp("gpioh", CMD_ARGV[0]) == 0)
800                 port = 15;
801         else
802                 return ERROR_COMMAND_SYNTAX_ERROR;
803
804         uint32_t pin;
805         COMMAND_PARSE_NUMBER(uint, CMD_ARGV[1], pin);
806         if (pin > 15)
807                 return ERROR_COMMAND_SYNTAX_ERROR;
808
809         uint32_t func;
810         if (strcmp("func1", CMD_ARGV[2]) == 0)
811                 func = 0;
812         else if (strcmp("func3", CMD_ARGV[2]) == 0)
813                 func = 3;
814         else
815                 return ERROR_COMMAND_SYNTAX_ERROR;
816
817         command_print(CMD,  "Try to configure external memory boot interface:\n"
818                                                         "port = %s\n"
819                                                         "pin  = %s\n"
820                                                         "func = %s\n"
821                                                         "Please wait ...", CMD_ARGV[0], CMD_ARGV[1], CMD_ARGV[2]);
822         /* dump */
823         uint32_t uflash_dump[USERFLASH_PAGE_SIZE];
824         niietcm4_dump_uflash_page(bank, uflash_dump, 0, 1);
825
826         /* modify dump */
827         uflash_dump[INFOWORD0_ADDR] &= ~(3<<INFOWORD0_EXTMEM_SEL_POS);
828         uflash_dump[INFOWORD0_ADDR] |= func<<INFOWORD0_EXTMEM_SEL_POS;
829         uflash_dump[INFOWORD1_ADDR] = (port<<INFOWORD1_PORTNUM_POS) | (pin<<INFOWORD1_PINNUM_POS);
830
831         /* erase page userflash */
832         niietcm4_uflash_page_erase(bank, 0, 1);
833
834         /* write dump to userflash */
835         niietcm4_load_uflash_page(bank, uflash_dump, 0, 1);
836         command_print(CMD, "done!");
837
838         return retval;
839 }
840
841 COMMAND_HANDLER(niietcm4_handle_extmem_boot_command)
842 {
843         if (CMD_ARGC < 2)
844                 return ERROR_COMMAND_SYNTAX_ERROR;
845
846         struct flash_bank *bank;
847         int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
848         if (retval != ERROR_OK)
849                 return retval;
850         struct target *target = bank->target;
851
852         if (target->state != TARGET_HALTED) {
853                 LOG_ERROR("Target not halted");
854                 return ERROR_TARGET_NOT_HALTED;
855         }
856
857         /* skip over flash bank */
858         CMD_ARGC--;
859         CMD_ARGV++;
860
861         int set;
862
863         if (strcmp("on", CMD_ARGV[0]) == 0) {
864                 command_print(CMD, "Try to enable boot from external memory. Please wait ...");
865                 set = 1;
866         } else if (strcmp("off", CMD_ARGV[0]) == 0) {
867                 command_print(CMD, "Try to disable boot from external memory. Please wait ...");
868                 set = 0;
869         } else
870                 return ERROR_COMMAND_SYNTAX_ERROR;
871
872         /* dump */
873         uint32_t uflash_dump[USERFLASH_PAGE_SIZE];
874         niietcm4_dump_uflash_page(bank, uflash_dump, 0, 1);
875
876         /* modify dump */
877         if (set)
878                 uflash_dump[INFOWORD0_ADDR] &= ~INFOWORD0_EN_GPIO;
879         else
880                 uflash_dump[INFOWORD0_ADDR] |= INFOWORD0_EN_GPIO;
881
882         /* erase page userflash */
883         niietcm4_uflash_page_erase(bank, 0, 1);
884
885         /* write dump to userflash */
886         niietcm4_load_uflash_page(bank, uflash_dump, 0, 1);
887         command_print(CMD, "done!");
888
889         return retval;
890 }
891
892 COMMAND_HANDLER(niietcm4_handle_service_mode_erase_command)
893 {
894         if (CMD_ARGC < 1)
895                 return ERROR_COMMAND_SYNTAX_ERROR;
896
897         struct flash_bank *bank;
898         int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
899         if (retval != ERROR_OK)
900                 return retval;
901         struct target *target = bank->target;
902
903         command_print(CMD, "Try to perform service mode erase. Please wait ...");
904
905         retval = target_write_u32(target, SERVICE_MODE_ERASE_ADDR, 1);
906         if (retval != ERROR_OK)
907                 return retval;
908
909         int timeout = 500;
910         uint32_t status;
911
912         retval = target_read_u32(target, SERVICE_MODE_ERASE_ADDR, &status);
913         if (retval != ERROR_OK)
914                 return retval;
915
916         while (status != 0x03) {
917                 retval = target_read_u32(target, SERVICE_MODE_ERASE_ADDR, &status);
918                 if (retval != ERROR_OK)
919                         return retval;
920                 if (timeout-- <= 0) {
921                         LOG_ERROR("Service mode erase timeout");
922                         return ERROR_FLASH_OPERATION_FAILED;
923                         }
924                 busy_sleep(1);  /* can use busy sleep for short times. */
925         }
926         command_print(CMD, "done! All data erased.");
927
928         return retval;
929 }
930
931 COMMAND_HANDLER(niietcm4_handle_driver_info_command)
932 {
933         if (CMD_ARGC < 1)
934                 return ERROR_COMMAND_SYNTAX_ERROR;
935
936         struct flash_bank *bank;
937         int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
938         if (retval != ERROR_OK)
939                 return retval;
940
941         command_print(CMD, "niietcm4 flash driver\n"
942                                                    "version: %d.%d\n"
943                                                    "author: Bogdan Kolbov\n"
944                                                    "mail: kolbov@niiet.ru",
945                                                    FLASH_DRIVER_VER>>16,
946                                                    FLASH_DRIVER_VER&0xFFFF);
947
948         return retval;
949 }
950
951 static const struct command_registration niietcm4_exec_command_handlers[] = {
952         {
953                 .name = "uflash_read_byte",
954                 .handler = niietcm4_handle_uflash_read_byte_command,
955                 .mode = COMMAND_EXEC,
956                 .usage = "bank_id ('main'|'info') address",
957                 .help = "Read byte from main or info userflash region",
958         },
959         {
960                 .name = "uflash_write_byte",
961                 .handler = niietcm4_handle_uflash_write_byte_command,
962                 .mode = COMMAND_EXEC,
963                 .usage = "bank_id ('main'|'info') address value",
964                 .help = "Write byte to main or info userflash region",
965         },
966         {
967                 .name = "uflash_full_erase",
968                 .handler = niietcm4_handle_uflash_full_erase_command,
969                 .mode = COMMAND_EXEC,
970                 .usage = "bank_id",
971                 .help = "Erase all userflash including info region",
972         },
973         {
974                 .name = "uflash_erase",
975                 .handler = niietcm4_handle_uflash_erase_command,
976                 .mode = COMMAND_EXEC,
977                 .usage = "bank_id ('main'|'info') first_sector_num last_sector_num",
978                 .help = "Erase sectors of main or info userflash region, starting at sector first up to and including last.",
979         },
980         {
981                 .name = "uflash_protect_check",
982                 .handler = niietcm4_handle_uflash_protect_check_command,
983                 .mode = COMMAND_EXEC,
984                 .usage = "bank_id ('main'|'info')",
985                 .help = "Check sectors protect.",
986         },
987         {
988                 .name = "uflash_protect",
989                 .handler = niietcm4_handle_uflash_protect_command,
990                 .mode = COMMAND_EXEC,
991                 .usage = "bank_id ('main'|'info') first_sector_num last_sector_num ('on'|'off')",
992                 .help = "Protect sectors of main or info userflash region, starting at sector first up to and including last.",
993         },
994         {
995                 .name = "bflash_info_remap",
996                 .handler = niietcm4_handle_bflash_info_remap_command,
997                 .mode = COMMAND_EXEC,
998                 .usage = "bank_id ('on'|'off')",
999                 .help = "Enable remapping bootflash info region to 0x00000000 (or 0x40000000 if external memory boot used).",
1000         },
1001         {
1002                 .name = "extmem_cfg",
1003                 .handler = niietcm4_handle_extmem_cfg_command,
1004                 .mode = COMMAND_EXEC,
1005                 .usage = "bank_id ('gpioa'|'gpiob'|'gpioc'|'gpiod'|'gpioe'|'gpiof'|'gpiog'|'gpioh') pin_num ('func1'|'func3')",
1006                 .help = "Configure external memory interface for boot.",
1007         },
1008         {
1009                 .name = "extmem_boot",
1010                 .handler = niietcm4_handle_extmem_boot_command,
1011                 .mode = COMMAND_EXEC,
1012                 .usage = "bank_id ('on'|'off')",
1013                 .help = "Enable boot from external memory.",
1014         },
1015         {
1016                 .name = "service_mode_erase",
1017                 .handler = niietcm4_handle_service_mode_erase_command,
1018                 .mode = COMMAND_EXEC,
1019                 .usage = "bank_id",
1020                 .help = "Perform emergency erase of all flash (bootflash and userflash).",
1021         },
1022         {
1023                 .name = "driver_info",
1024                 .handler = niietcm4_handle_driver_info_command,
1025                 .mode = COMMAND_EXEC,
1026                 .usage = "bank_id",
1027                 .help = "Show information about flash driver.",
1028         },
1029         COMMAND_REGISTRATION_DONE
1030 };
1031
1032 static const struct command_registration niietcm4_command_handlers[] = {
1033         {
1034                 .name = "niietcm4",
1035                 .mode = COMMAND_ANY,
1036                 .help = "niietcm4 flash command group",
1037                 .usage = "",
1038                 .chain = niietcm4_exec_command_handlers,
1039         },
1040         COMMAND_REGISTRATION_DONE
1041 };
1042
1043 /*==============================================================================
1044  *                                                      FLASH INTERFACE
1045  *==============================================================================
1046  */
1047
1048 FLASH_BANK_COMMAND_HANDLER(niietcm4_flash_bank_command)
1049 {
1050         struct niietcm4_flash_bank *niietcm4_info;
1051
1052         if (CMD_ARGC < 6)
1053                 return ERROR_COMMAND_SYNTAX_ERROR;
1054
1055         niietcm4_info = malloc(sizeof(struct niietcm4_flash_bank));
1056
1057         bank->driver_priv = niietcm4_info;
1058
1059         /* information will be updated by probing */
1060         niietcm4_info->probed = false;
1061         niietcm4_info->chipid = 0;
1062         niietcm4_info->chip_name = NULL;
1063         niietcm4_info->uflash_width = 0;
1064         niietcm4_info->uflash_size = 0;
1065         niietcm4_info->uflash_pagetotal = 0;
1066         niietcm4_info->uflash_info_size = 0;
1067         niietcm4_info->uflash_info_pagetotal = 0;
1068         niietcm4_info->bflash_info_remap = false;
1069         niietcm4_info->extmem_boot_port = NULL;
1070         niietcm4_info->extmem_boot_pin = 0;
1071         niietcm4_info->extmem_boot_altfunc = 0;
1072         niietcm4_info->extmem_boot = false;
1073
1074         return ERROR_OK;
1075 }
1076
1077 static int niietcm4_protect_check(struct flash_bank *bank)
1078 {
1079         struct target *target = bank->target;
1080         struct niietcm4_flash_bank *niietcm4_info = bank->driver_priv;
1081
1082         int retval = ERROR_FLASH_OPERATION_FAILED;
1083         int set;
1084         uint32_t uflash_addr;
1085         uint32_t uflash_cmd;
1086         uint32_t uflash_data;
1087         /* chose between main bootflash and info bootflash  */
1088         if (niietcm4_info->bflash_info_remap) {
1089                 uflash_addr = INFOWORD2_ADDR;
1090                 uflash_cmd = UFMC_MAGIC_KEY | UFMC_READ_IFB;
1091                 retval = target_write_u32(target, UFMA, uflash_addr);
1092                 if (retval != ERROR_OK)
1093                         return retval;
1094                 retval = target_write_u32(target, UFMC, uflash_cmd);
1095                 if (retval != ERROR_OK)
1096                         return retval;
1097
1098                 /* status check */
1099                 retval = niietcm4_uopstatus_check(bank);
1100                 if (retval != ERROR_OK)
1101                         return retval;
1102                 retval = target_read_u32(target, UFMD, &uflash_data);
1103                 if (retval != ERROR_OK)
1104                         return retval;
1105
1106                 if (uflash_data & INFOWORD2_LOCK_IFB_BF)
1107                         set = 0;
1108                 else
1109                         set = 1;
1110                 bank->sectors[0].is_protected = set;
1111         } else {
1112                 uflash_addr = BF_LOCK_ADDR;
1113                 uflash_cmd = UFMC_MAGIC_KEY | UFMC_READ_IFB;
1114                 for (int i = 0; i < bank->num_sectors/8; i++) {
1115                         retval = target_write_u32(target, UFMA, uflash_addr);
1116                         if (retval != ERROR_OK)
1117                                 return retval;
1118                         retval = target_write_u32(target, UFMC, uflash_cmd);
1119                         if (retval != ERROR_OK)
1120                                 return retval;
1121
1122                         /* status check */
1123                         retval = niietcm4_uopstatus_check(bank);
1124                         if (retval != ERROR_OK)
1125                                 return retval;
1126                         retval = target_read_u32(target, UFMD, &uflash_data);
1127                         if (retval != ERROR_OK)
1128                                 return retval;
1129
1130                         for (int j = 0; j < 8; j++) {
1131                                 if (uflash_data & 0x1)
1132                                         set = 0;
1133                                 else
1134                                         set = 1;
1135                                 bank->sectors[i*8+j].is_protected = set;
1136                                 uflash_data = uflash_data >> 1;
1137                         }
1138                         uflash_addr++;
1139                 }
1140         }
1141
1142         return retval;
1143 }
1144
1145 static int niietcm4_mass_erase(struct flash_bank *bank)
1146 {
1147         struct target *target = bank->target;
1148
1149         int retval;
1150         uint32_t flash_cmd;
1151
1152         /* start mass erase */
1153         flash_cmd = FMC_MAGIC_KEY | FMC_FULL_ERASE;
1154         retval = target_write_u32(target, FMC, flash_cmd);
1155         if (retval != ERROR_OK)
1156                 return retval;
1157
1158         /* status check */
1159         retval = niietcm4_opstatus_check(bank);
1160         if (retval != ERROR_OK)
1161                 return retval;
1162
1163         return retval;
1164 }
1165
1166 static int niietcm4_erase(struct flash_bank *bank, int first, int last)
1167 {
1168         struct target *target = bank->target;
1169         struct niietcm4_flash_bank *niietcm4_info = bank->driver_priv;
1170         int retval = ERROR_FLASH_OPERATION_FAILED;
1171
1172         if (bank->target->state != TARGET_HALTED) {
1173                 LOG_ERROR("Target not halted");
1174                 return ERROR_TARGET_NOT_HALTED;
1175         }
1176
1177         if ((first == 0) && (last == (bank->num_sectors - 1))) {
1178                 retval = niietcm4_mass_erase(bank);
1179                 return retval;
1180         }
1181
1182         /* chose between main bootflash and info bootflash */
1183         uint32_t flash_cmd, flash_addr;
1184         if (niietcm4_info->bflash_info_remap)
1185                 flash_cmd = FMC_MAGIC_KEY | FMC_PAGEERASE_IFB;
1186         else
1187                 flash_cmd = FMC_MAGIC_KEY | FMC_PAGE_ERASE;
1188
1189         /* erasing pages */
1190         unsigned int page_size = bank->size / bank->num_sectors;
1191         for (int i = first; i <= last; i++) {
1192                 /* current page addr */
1193                 flash_addr = i*page_size;
1194                 retval = target_write_u32(target, FMA, flash_addr);
1195                 if (retval != ERROR_OK)
1196                         return retval;
1197
1198                 /* start erase */
1199                 retval = target_write_u32(target, FMC, flash_cmd);
1200                 if (retval != ERROR_OK)
1201                         return retval;
1202
1203                 /* status check */
1204                 retval = niietcm4_opstatus_check(bank);
1205                 if (retval != ERROR_OK)
1206                         return retval;
1207
1208                 bank->sectors[i].is_erased = 1;
1209         }
1210
1211         return retval;
1212 }
1213
1214 static int niietcm4_protect(struct flash_bank *bank, int set, int first, int last)
1215 {
1216         struct target *target = bank->target;
1217         struct niietcm4_flash_bank *niietcm4_info = bank->driver_priv;
1218
1219         int retval;
1220
1221         if (target->state != TARGET_HALTED) {
1222                 LOG_ERROR("Target not halted");
1223                 return ERROR_TARGET_NOT_HALTED;
1224         }
1225
1226         LOG_INFO("Plese wait ..."); /* it`s quite a long process */
1227         /* chose between main bootflash and info bootflash */
1228         if (niietcm4_info->bflash_info_remap) {
1229                 /* dump */
1230                 uint32_t uflash_dump[USERFLASH_PAGE_SIZE];
1231                 retval = niietcm4_dump_uflash_page(bank, uflash_dump, 0, 1);
1232                 if (retval != ERROR_OK)
1233                         return retval;
1234                 /* modify dump */
1235                 if (set)
1236                         uflash_dump[INFOWORD2_ADDR] &= ~INFOWORD2_LOCK_IFB_BF;
1237                 else
1238                         uflash_dump[INFOWORD2_ADDR] |= INFOWORD2_LOCK_IFB_BF;
1239                 /* erase page 0 userflash */
1240                 retval = niietcm4_uflash_page_erase(bank, 0, 1);
1241                 if (retval != ERROR_OK)
1242                         return retval;
1243                 /* write dump to userflash */
1244                 retval = niietcm4_load_uflash_page(bank, uflash_dump, 0, 1);
1245                 if (retval != ERROR_OK)
1246                         return retval;
1247         } else {
1248                 /* read dump*/
1249                 uint32_t uflash_dump[USERFLASH_PAGE_SIZE];
1250                 retval = niietcm4_dump_uflash_page(bank, uflash_dump, 0, 1);
1251                 if (retval != ERROR_OK)
1252                         return retval;
1253                 /* modify dump */
1254                 for (int i = first; i <= last; i++)     {
1255                         uint32_t reg_num = i/8;
1256                         uint32_t bit_num = i%8;
1257                         if (set)
1258                                 uflash_dump[BF_LOCK_ADDR+reg_num] &= ~(1<<bit_num);
1259                         else
1260                                 uflash_dump[BF_LOCK_ADDR+reg_num] |= (1<<bit_num);
1261                 }
1262                 /* erase page 0 info userflash */
1263                 retval = niietcm4_uflash_page_erase(bank, 0, 1);
1264                 if (retval != ERROR_OK)
1265                         return retval;
1266                 /* write dump to userflash */
1267                 retval = niietcm4_load_uflash_page(bank, uflash_dump,  0, 1);
1268                 if (retval != ERROR_OK)
1269                         return retval;
1270         }
1271
1272         return retval;
1273 }
1274
1275 static int niietcm4_write_block(struct flash_bank *bank, const uint8_t *buffer,
1276                 uint32_t offset, uint32_t count)
1277 {
1278         struct target *target = bank->target;
1279         struct niietcm4_flash_bank *niietcm4_info = bank->driver_priv;
1280         uint32_t buffer_size = 32768 + 8; /* 8 bytes for rp and wp */
1281         struct working_area *write_algorithm;
1282         struct working_area *source;
1283         uint32_t address = bank->base + offset;
1284         struct reg_param reg_params[5];
1285         struct armv7m_algorithm armv7m_info;
1286         int retval = ERROR_OK;
1287
1288         /* see contrib/loaders/flash/k1921vk01t.S for src */
1289         static const uint8_t niietcm4_flash_write_code[] = {
1290                 0x14, 0x4f, 0x16, 0x68, 0x00, 0x2e, 0x23, 0xd0, 0x55, 0x68, 0xb5, 0x42, 0xf9, 0xd0, 0x2e, 0x68,
1291                 0x7e, 0x60, 0x04, 0x35, 0x2e, 0x68, 0x3e, 0x65, 0x04, 0x35, 0x2e, 0x68, 0x7e, 0x65, 0x04, 0x35,
1292                 0x2e, 0x68, 0xbe, 0x65, 0x04, 0x35, 0x3c, 0x60, 0x10, 0x34, 0xb8, 0x60, 0xfe, 0x68, 0x00, 0x2e,
1293                 0xfc, 0xd0, 0x02, 0x2e, 0x0a, 0xd0, 0x01, 0x26, 0x7e, 0x61, 0x9d, 0x42, 0x01, 0xd3, 0x15, 0x46,
1294                 0x08, 0x35, 0x55, 0x60, 0x01, 0x39, 0x00, 0x29, 0x02, 0xd0, 0xda, 0xe7, 0x00, 0x20, 0x50, 0x60,
1295                 0x30, 0x46, 0x00, 0xbe, 0x00, 0xc0, 0x01, 0xa0
1296         };
1297
1298         /* flash write code */
1299         if (target_alloc_working_area(target, sizeof(niietcm4_flash_write_code),
1300                         &write_algorithm) != ERROR_OK) {
1301                 LOG_WARNING("no working area available, can't do block memory writes");
1302                 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
1303         }
1304
1305         retval = target_write_buffer(target, write_algorithm->address,
1306                         sizeof(niietcm4_flash_write_code), niietcm4_flash_write_code);
1307         if (retval != ERROR_OK)
1308                 return retval;
1309
1310         /* memory buffer */
1311         while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) {
1312                 buffer_size /= 2;
1313                 buffer_size &= ~15UL; /* Make sure it's 16 byte aligned */
1314                 buffer_size += 8; /* And 8 bytes for WP and RP */
1315                 if (buffer_size <= 256) {
1316                         /* we already allocated the writing code, but failed to get a
1317                          * buffer, free the algorithm */
1318                         target_free_working_area(target, write_algorithm);
1319
1320                         LOG_WARNING("no large enough working area available, can't do block memory writes");
1321                         return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
1322                 }
1323         }
1324
1325         init_reg_param(&reg_params[0], "r0", 32, PARAM_IN_OUT); /* write_cmd base (in), status (out) */
1326         init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);    /* count (128bit) */
1327         init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT);    /* buffer start */
1328         init_reg_param(&reg_params[3], "r3", 32, PARAM_OUT);    /* buffer end */
1329         init_reg_param(&reg_params[4], "r4", 32, PARAM_IN_OUT); /* target address */
1330
1331         uint32_t flash_cmd;
1332         if (niietcm4_info->bflash_info_remap)
1333                 flash_cmd = FMC_MAGIC_KEY | FMC_WRITE_IFB;
1334         else
1335                 flash_cmd = FMC_MAGIC_KEY | FMC_WRITE;
1336
1337         buf_set_u32(reg_params[0].value, 0, 32, flash_cmd);
1338         buf_set_u32(reg_params[1].value, 0, 32, count);
1339         buf_set_u32(reg_params[2].value, 0, 32, source->address);
1340         buf_set_u32(reg_params[3].value, 0, 32, source->address + source->size);
1341         buf_set_u32(reg_params[4].value, 0, 32, address);
1342
1343         armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
1344         armv7m_info.core_mode = ARM_MODE_THREAD;
1345
1346         retval = target_run_flash_async_algorithm(target, buffer, count, 16,
1347                         0, NULL,
1348                         5, reg_params,
1349                         source->address, source->size,
1350                         write_algorithm->address, 0,
1351                         &armv7m_info);
1352
1353         if (retval == ERROR_FLASH_OPERATION_FAILED)
1354                 LOG_ERROR("flash write failed at address 0x%"PRIx32,
1355                                 buf_get_u32(reg_params[4].value, 0, 32));
1356
1357         target_free_working_area(target, source);
1358         target_free_working_area(target, write_algorithm);
1359
1360         destroy_reg_param(&reg_params[0]);
1361         destroy_reg_param(&reg_params[1]);
1362         destroy_reg_param(&reg_params[2]);
1363         destroy_reg_param(&reg_params[3]);
1364         destroy_reg_param(&reg_params[4]);
1365
1366         return retval;
1367 }
1368
1369 static int niietcm4_write(struct flash_bank *bank, const uint8_t *buffer,
1370                 uint32_t offset, uint32_t count)
1371 {
1372         struct target *target = bank->target;
1373         struct niietcm4_flash_bank *niietcm4_info = bank->driver_priv;
1374         uint8_t *new_buffer = NULL;
1375
1376         if (bank->target->state != TARGET_HALTED) {
1377                 LOG_ERROR("Target not halted");
1378                 return ERROR_TARGET_NOT_HALTED;
1379         }
1380
1381         if (offset & 0xF) {
1382                 LOG_ERROR("offset 0x%" PRIx32 " breaks required 4-word alignment", offset);
1383                 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
1384         }
1385
1386         /* If there's an odd number of words, the data has to be padded. Duplicate
1387          * the buffer and use the normal code path with a single block write since
1388          * it's probably cheaper than to special case the last odd write using
1389          * discrete accesses. */
1390
1391         int rem = count % 16;
1392         if (rem) {
1393                 new_buffer = malloc(count + 16 - rem);
1394                 if (new_buffer == NULL) {
1395                         LOG_ERROR("Odd number of words to write and no memory for padding buffer");
1396                         return ERROR_FAIL;
1397                 }
1398                 LOG_INFO("Odd number of words to write, padding with 0xFFFFFFFF");
1399                 buffer = memcpy(new_buffer, buffer, count);
1400                 while (rem < 16) {
1401                         new_buffer[count++] = 0xff;
1402                         rem++;
1403                 }
1404         }
1405
1406         int retval;
1407
1408         /* try using block write */
1409         retval = niietcm4_write_block(bank, buffer, offset, count/16);
1410         uint32_t flash_addr, flash_cmd, flash_data;
1411
1412         if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) {
1413                 /* if block write failed (no sufficient working area),
1414                  * we use normal (slow) single halfword accesses */
1415                 LOG_WARNING("Can't use block writes, falling back to single memory accesses");
1416                 LOG_INFO("Plese wait ..."); /* it`s quite a long process */
1417
1418                 /* chose between main bootflash and info bootflash */
1419                 if (niietcm4_info->bflash_info_remap)
1420                         flash_cmd = FMC_MAGIC_KEY | FMC_WRITE_IFB;
1421                 else
1422                         flash_cmd = FMC_MAGIC_KEY | FMC_WRITE;
1423
1424                 /* write 16 bytes per try */
1425                 for (unsigned int i = 0; i < count; i += 16) {
1426                         /* current addr */
1427                         LOG_INFO("%d byte of %d", i, count);
1428                         flash_addr = offset + i;
1429                         retval = target_write_u32(target, FMA, flash_addr);
1430                         if (retval != ERROR_OK)
1431                                 goto free_buffer;
1432
1433                         /* Prepare data (4 words) */
1434                         uint32_t value[4];
1435                         memcpy(&value, buffer + i*16, 4*sizeof(uint32_t));
1436
1437                         /* place in reg 16 bytes of data */
1438                         flash_data = value[0];
1439                         retval = target_write_u32(target, FMD1, flash_data);
1440                         if (retval != ERROR_OK)
1441                                 goto free_buffer;
1442                         flash_data = value[1];
1443                         retval = target_write_u32(target, FMD2, flash_data);
1444                         if (retval != ERROR_OK)
1445                                 goto free_buffer;
1446                         flash_data = value[2];
1447                         retval = target_write_u32(target, FMD3, flash_data);
1448                         if (retval != ERROR_OK)
1449                                 goto free_buffer;
1450                         flash_data = value[3];
1451                         retval = target_write_u32(target, FMD4, flash_data);
1452                         if (retval != ERROR_OK)
1453                                 goto free_buffer;
1454
1455                         /* write start */
1456                         retval = target_write_u32(target, FMC, flash_cmd);
1457                         if (retval != ERROR_OK)
1458                                 goto free_buffer;
1459
1460                         /* status check */
1461                         retval = niietcm4_opstatus_check(bank);
1462                         if (retval != ERROR_OK)
1463                                 goto free_buffer;
1464                 }
1465
1466         }
1467
1468 free_buffer:
1469         if (new_buffer)
1470                 free(new_buffer);
1471
1472         return retval;
1473 }
1474
1475 static int niietcm4_probe_k1921vk01t(struct flash_bank *bank)
1476 {
1477         struct niietcm4_flash_bank *niietcm4_info = bank->driver_priv;
1478         struct target *target = bank->target;
1479         int retval;
1480
1481         niietcm4_info->chip_name = "K1921VK01T";
1482
1483         /* check if we in service mode */
1484         uint32_t service_mode;
1485         retval = target_read_u32(target, 0x80017000, &service_mode);
1486         if (retval != ERROR_OK)
1487                 return retval;
1488         service_mode = (service_mode>>2) & 0x1;
1489
1490         if (!service_mode) {
1491                 niietcm4_info->uflash_width = 8;
1492                 niietcm4_info->uflash_size = 0x10000;
1493                 niietcm4_info->uflash_pagetotal = 256;
1494                 niietcm4_info->uflash_info_size = 0x200;
1495                 niietcm4_info->uflash_info_pagetotal = 2;
1496
1497                 uint32_t uflash_data[2];
1498                 uint32_t uflash_cmd = UFMC_MAGIC_KEY | UFMC_READ_IFB;
1499                 for (int i = 0; i < 2; i++) {
1500                         retval = target_write_u32(target, UFMA, i);
1501                         if (retval != ERROR_OK)
1502                                 return retval;
1503                         retval = target_write_u32(target, UFMC, uflash_cmd);
1504                         if (retval != ERROR_OK)
1505                                 return retval;
1506                         /* status check */
1507                         retval = niietcm4_uopstatus_check(bank);
1508                         if (retval != ERROR_OK)
1509                                 return retval;
1510                         retval = target_read_u32(target, UFMD, &uflash_data[i]);
1511                         if (retval != ERROR_OK)
1512                                 return retval;
1513                 }
1514
1515                 int boot_from_ifb = (uflash_data[0]>>INFOWORD0_BOOTFROM_IFB_POS) & 0x1;
1516                 int en_gpio = (uflash_data[0]>>INFOWORD0_EN_GPIO_POS) & 0x1;
1517                 int extmem_sel = (uflash_data[0]>>INFOWORD0_EXTMEM_SEL_POS) & 0x3;
1518                 int pinnum = (uflash_data[1]>>INFOWORD1_PINNUM_POS) & 0xF;
1519                 int portnum = (uflash_data[1]>>INFOWORD1_PORTNUM_POS) & 0x7;
1520
1521                 if (boot_from_ifb)
1522                         niietcm4_info->bflash_info_remap = false;
1523                 else
1524                         niietcm4_info->bflash_info_remap = true;
1525                 if (extmem_sel == 0x2)
1526                         niietcm4_info->extmem_boot_altfunc = 3;
1527                 else
1528                         niietcm4_info->extmem_boot_altfunc = 1;
1529                 if (portnum == 0x0)
1530                         niietcm4_info->extmem_boot_port = "GPIOA";
1531                 else if (portnum == 0x1)
1532                         niietcm4_info->extmem_boot_port = "GPIOB";
1533                 else if (portnum == 0x2)
1534                         niietcm4_info->extmem_boot_port = "GPIOC";
1535                 else if (portnum == 0x3)
1536                         niietcm4_info->extmem_boot_port = "GPIOD";
1537                 else if (portnum == 0x4)
1538                         niietcm4_info->extmem_boot_port = "GPIOE";
1539                 else if (portnum == 0x5)
1540                         niietcm4_info->extmem_boot_port = "GPIOF";
1541                 else if (portnum == 0x6)
1542                         niietcm4_info->extmem_boot_port = "GPIOG";
1543                 else if (portnum == 0x7)
1544                         niietcm4_info->extmem_boot_port = "GPIOH";
1545                 else
1546                         niietcm4_info->extmem_boot_port = "not defined";
1547                 if (en_gpio)
1548                         niietcm4_info->extmem_boot = false;
1549                 else
1550                         niietcm4_info->extmem_boot = true;
1551                 niietcm4_info->extmem_boot_pin = pinnum;
1552
1553                 /* check state of extmem boot en pin, if "high", extmem remapped to 0x00000000 */
1554                 uint32_t extmem_boot_port_data;
1555                 retval = target_read_u32(target, 0x80010000 + 0x1000*portnum, &extmem_boot_port_data);
1556                 if (retval != ERROR_OK)
1557                         return retval;
1558                 int extmem_boot_pin_data = (extmem_boot_port_data>>pinnum) & 0x1;
1559
1560                 uint32_t extmem_base;
1561                 uint32_t bflash_base;
1562                 if (extmem_boot_pin_data && niietcm4_info->extmem_boot) {
1563                         extmem_base = 0x00000000;
1564                         bflash_base = 0x40000000;
1565                 } else {
1566                         extmem_base = 0x40000000;
1567                         bflash_base = 0x00000000;
1568                 }
1569
1570                 uint32_t bflash_size = 0x100000;
1571                 uint32_t bflash_pages = 128;
1572                 uint32_t bflash_info_size = 0x2000;
1573                 uint32_t bflash_info_pages = 1;
1574                 if (niietcm4_info->bflash_info_remap) {
1575                         bflash_base += 0x2000;
1576                         bflash_size -= 0x2000;
1577                         bflash_pages--;
1578                         bank->size = bflash_info_size;
1579                         bank->num_sectors = bflash_info_pages;
1580                 } else {
1581                         bank->size = bflash_size;
1582                         bank->num_sectors = bflash_pages;
1583                 }
1584
1585                 char info_bootflash_addr_str[64];
1586                 if (niietcm4_info->bflash_info_remap)
1587                         snprintf(info_bootflash_addr_str, sizeof(info_bootflash_addr_str),
1588                                         TARGET_ADDR_FMT " base adress", bank->base);
1589                 else
1590                         snprintf(info_bootflash_addr_str, sizeof(info_bootflash_addr_str),
1591                                         "not mapped to global adress space");
1592
1593                 snprintf(niietcm4_info->chip_brief,
1594                                 sizeof(niietcm4_info->chip_brief),
1595                                 "\n"
1596                                 "MEMORY CONFIGURATION\n"
1597                                 "Bootflash :\n"
1598                                 "    %d kB total\n"
1599                                 "    %d pages %d kB each\n"
1600                                 "    0x%08x base adress\n"
1601                                 "%s"
1602                                 "Info bootflash :\n"
1603                                 "    %d kB total\n"
1604                                 "    %d pages %d kB each\n"
1605                                 "    %s\n"
1606                                 "%s"
1607                                 "Userflash :\n"
1608                                 "    %d kB total\n"
1609                                 "    %d pages %d B each\n"
1610                                 "    %d bit cells\n"
1611                                 "    not maped to global adress space\n"
1612                                 "Info userflash :\n"
1613                                 "    %d B total\n"
1614                                 "    %d pages of %d B each\n"
1615                                 "    %d bit cells\n"
1616                                 "    not maped to global adress space\n"
1617                                 "RAM :\n"
1618                                 "    192 kB total\n"
1619                                 "    0x20000000 base adress\n"
1620                                 "External memory :\n"
1621                                 "    8/16 bit address space\n"
1622                                 "    0x%08x base adress\n"
1623                                 "\n"
1624                                 "INFOWORD STATUS\n"
1625                                 "Bootflash info region remap :\n"
1626                                 "    %s\n"
1627                                 "External memory boot port :\n"
1628                                 "    %s\n"
1629                                 "External memory boot pin :\n"
1630                                 "    %d\n"
1631                                 "External memory interface alternative function :\n"
1632                                 "    %d\n"
1633                                 "Option boot from external memory :\n"
1634                                 "    %s\n",
1635                                 bflash_size/1024,
1636                                 bflash_pages,
1637                                 (bflash_size/bflash_pages)/1024,
1638                                 bflash_base,
1639                                 niietcm4_info->bflash_info_remap ? "" : "    this flash will be used for debugging, writing and etc\n",
1640                                 bflash_info_size/1024,
1641                                 bflash_info_pages,
1642                                 (bflash_info_size/bflash_info_pages)/1024,
1643                                 info_bootflash_addr_str,
1644                                 niietcm4_info->bflash_info_remap ? "    this flash will be used for debugging, writing and etc\n" : "",
1645                                 niietcm4_info->uflash_size/1024,
1646                                 niietcm4_info->uflash_pagetotal,
1647                                 niietcm4_info->uflash_size/niietcm4_info->uflash_pagetotal,
1648                                 niietcm4_info->uflash_width,
1649                                 niietcm4_info->uflash_info_size,
1650                                 niietcm4_info->uflash_info_pagetotal,
1651                                 niietcm4_info->uflash_info_size/niietcm4_info->uflash_info_pagetotal,
1652                                 niietcm4_info->uflash_width,
1653                                 extmem_base,
1654                                 niietcm4_info->bflash_info_remap ? "enable" : "disable",
1655                                 niietcm4_info->extmem_boot_port,
1656                                 niietcm4_info->extmem_boot_pin,
1657                                 niietcm4_info->extmem_boot_altfunc,
1658                                 niietcm4_info->extmem_boot ? "enable" : "disable");
1659         } else{
1660                 bank->size = 0x100000;
1661                 bank->num_sectors = 128;
1662
1663                 sprintf(niietcm4_info->chip_brief,
1664                                 "\n"
1665                                 "H[2] was HIGH while startup. Device entered service mode.\n"
1666                                 "All flashes were locked.\n"
1667                                 "If you want to perform emergency erase (erase all flashes),\n"
1668                                 "please use \"service_mode_erase\" command and reset device.\n"
1669                                 "Do not forget to pull H[2] down while reset for returning to normal operation mode.\n"
1670                                 );
1671         }
1672
1673         return retval;
1674 }
1675
1676 static int niietcm4_probe(struct flash_bank *bank)
1677 {
1678         struct niietcm4_flash_bank *niietcm4_info = bank->driver_priv;
1679         struct target *target = bank->target;
1680
1681         if (bank->sectors) {
1682                 free(bank->sectors);
1683                 bank->sectors = NULL;
1684         }
1685         uint32_t retval;
1686         uint32_t chipid;
1687
1688         retval = target_read_u32(target, CHIPID_ADDR, &chipid);
1689         if (retval != ERROR_OK) {
1690                 chipid = K1921VK01T_ID;
1691                 LOG_INFO("unknown chipid, assuming K1921VK01T");
1692         }
1693
1694         if (chipid == K1921VK01T_ID)
1695                 niietcm4_probe_k1921vk01t(bank);
1696
1697         int page_total = bank->num_sectors;
1698         int page_size = bank->size / page_total;
1699
1700         bank->sectors = malloc(sizeof(struct flash_sector) * page_total);
1701
1702         for (int i = 0; i < page_total; i++) {
1703                 bank->sectors[i].offset = i * page_size;
1704                 bank->sectors[i].size = page_size;
1705                 bank->sectors[i].is_erased = -1;
1706                 bank->sectors[i].is_protected = -1;
1707         }
1708
1709         niietcm4_info->probed = true;
1710
1711         return ERROR_OK;
1712 }
1713
1714 static int niietcm4_auto_probe(struct flash_bank *bank)
1715 {
1716         struct niietcm4_flash_bank *niietcm4_info = bank->driver_priv;
1717         if (niietcm4_info->probed)
1718                 return ERROR_OK;
1719         return niietcm4_probe(bank);
1720 }
1721
1722 static int get_niietcm4_info(struct flash_bank *bank, char *buf, int buf_size)
1723 {
1724         struct niietcm4_flash_bank *niietcm4_info = bank->driver_priv;
1725         LOG_INFO("\nNIIET Cortex-M4F %s\n%s", niietcm4_info->chip_name, niietcm4_info->chip_brief);
1726         snprintf(buf, buf_size, " ");
1727
1728         return ERROR_OK;
1729 }
1730
1731
1732 const struct flash_driver niietcm4_flash = {
1733         .name = "niietcm4",
1734         .usage = "flash bank <name> niietcm4 <base> <size> 0 0 <target#>",
1735         .commands = niietcm4_command_handlers,
1736         .flash_bank_command = niietcm4_flash_bank_command,
1737         .erase = niietcm4_erase,
1738         .protect = niietcm4_protect,
1739         .write = niietcm4_write,
1740         .read = default_flash_read,
1741         .probe = niietcm4_probe,
1742         .auto_probe = niietcm4_auto_probe,
1743         .erase_check = default_flash_blank_check,
1744         .protect_check = niietcm4_protect_check,
1745         .info = get_niietcm4_info,
1746         .free_driver_priv = default_flash_free_driver_priv,
1747 };