cmd: add missing usage var
[fw/openocd] / src / flash / nor / fm3.c
1 /***************************************************************************
2  *   Copyright (C) 2011 by Marc Willam, Holger Wech                        *
3  *   openOCD.fseu(AT)de.fujitsu.com                                        *
4  *                                                                         *
5  *   Copyright (C) 2011 Ronny Strutz                                       *
6  *                                                                         *
7  *   This program is free software; you can redistribute it and/or modify  *
8  *   it under the terms of the GNU General Public License as published by  *
9  *   the Free Software Foundation; either version 2 of the License, or     *
10  *   (at your option) any later version.                                   *
11  *                                                                         *
12  *   This program is distributed in the hope that it will be useful,       *
13  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
14  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
15  *   GNU General Public License for more details.                          *
16  *                                                                         *
17  *   You should have received a copy of the GNU General Public License     *
18  *   along with this program; if not, write to the                         *
19  *   Free Software Foundation, Inc.,                                       *
20  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
21  ***************************************************************************/
22
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26
27 #include "imp.h"
28 #include <helper/binarybuffer.h>
29 #include <target/algorithm.h>
30 #include <target/armv7m.h>
31
32 #define FLASH_DQ6 0x00000040    /* Data toggle flag bit (TOGG) */
33 #define FLASH_DQ5 0x00000020    /* Time limit exceeding flag bit (TLOV) */
34
35 enum fm3_variant
36 {
37         mb9bfxx1,       /* Flash Type '1' */
38         mb9bfxx2,
39         mb9bfxx3,
40         mb9bfxx4,
41         mb9bfxx5,
42         mb9bfxx6,
43         mb9afxx1,       /* Flash Type '2' */
44         mb9afxx2,
45         mb9afxx3,
46         mb9afxx4,
47         mb9afxx5,
48         mb9afxx6
49 };
50
51 enum fm3_flash_type
52 {
53         fm3_no_flash_type = 0,
54         fm3_flash_type1   = 1,
55         fm3_flash_type2   = 2
56 };
57
58 struct fm3_flash_bank
59 {
60         struct working_area *write_algorithm;
61         enum fm3_variant variant;
62         enum fm3_flash_type flashtype;
63         int probed;
64 };
65
66 FLASH_BANK_COMMAND_HANDLER(fm3_flash_bank_command)
67 {
68         struct fm3_flash_bank *fm3_info;
69
70         if (CMD_ARGC < 6)
71         {
72                 return ERROR_COMMAND_SYNTAX_ERROR;
73         }
74
75         fm3_info = malloc(sizeof(struct fm3_flash_bank));
76         bank->driver_priv = fm3_info;
77
78         /* Flash type '1' */
79         if (strcmp(CMD_ARGV[5], "mb9bfxx1.cpu") == 0)
80         {
81                 fm3_info->variant = mb9bfxx1;
82                 fm3_info->flashtype = fm3_flash_type1;
83         }
84         else if (strcmp(CMD_ARGV[5], "mb9bfxx2.cpu") == 0)
85         {
86                 fm3_info->variant = mb9bfxx2;
87                 fm3_info->flashtype = fm3_flash_type1;
88         }
89         else if (strcmp(CMD_ARGV[5], "mb9bfxx3.cpu") == 0)
90         {
91                 fm3_info->variant = mb9bfxx3;
92                 fm3_info->flashtype = fm3_flash_type1;
93         }
94         else if (strcmp(CMD_ARGV[5], "mb9bfxx4.cpu") == 0)
95         {
96                 fm3_info->variant = mb9bfxx4;
97                 fm3_info->flashtype = fm3_flash_type1;
98         }
99         else if (strcmp(CMD_ARGV[5], "mb9bfxx5.cpu") == 0)
100         {
101                 fm3_info->variant = mb9bfxx5;
102                 fm3_info->flashtype = fm3_flash_type1;
103         }
104         else if (strcmp(CMD_ARGV[5], "mb9bfxx6.cpu") == 0)
105         {
106                 fm3_info->variant = mb9bfxx6;
107                 fm3_info->flashtype = fm3_flash_type1;
108         }
109
110         /* Flash type '2' */
111         else if (strcmp(CMD_ARGV[5], "mb9afxx1.cpu") == 0)
112         {
113                 fm3_info->variant = mb9afxx1;
114                 fm3_info->flashtype = fm3_flash_type2;
115         }
116         else if (strcmp(CMD_ARGV[5], "mb9afxx2.cpu") == 0)
117         {
118                 fm3_info->variant = mb9afxx2;
119                 fm3_info->flashtype = fm3_flash_type2;
120         }
121         else if (strcmp(CMD_ARGV[5], "mb9afxx3.cpu") == 0)
122         {
123                 fm3_info->variant = mb9afxx3;
124                 fm3_info->flashtype = fm3_flash_type2;
125         }
126         else if (strcmp(CMD_ARGV[5], "mb9afxx4.cpu") == 0)
127         {
128                 fm3_info->variant = mb9afxx4;
129                 fm3_info->flashtype = fm3_flash_type2;
130         }
131         else if (strcmp(CMD_ARGV[5], "mb9afxx5.cpu") == 0)
132         {
133                 fm3_info->variant = mb9afxx5;
134                 fm3_info->flashtype = fm3_flash_type2;
135         }
136         else if (strcmp(CMD_ARGV[5], "mb9afxx6.cpu") == 0)
137         {
138                 fm3_info->variant = mb9afxx6;
139                 fm3_info->flashtype = fm3_flash_type2;
140         }
141
142         /* unknown Flash type */
143         else
144         {
145                 LOG_ERROR("unknown fm3 variant: %s", CMD_ARGV[5]);
146                 free(fm3_info);
147                 return ERROR_FLASH_BANK_INVALID;
148         }
149
150         fm3_info->write_algorithm = NULL;
151         fm3_info->probed = 0;
152
153         return ERROR_OK;
154 }
155
156 /* Data polling algorithm */
157 static int fm3_busy_wait(struct target *target, uint32_t offset, int timeout_ms)
158 {
159         int retval = ERROR_OK;
160         uint16_t state1, state2;
161         int ms = 0;
162
163         /* While(1) loop exit via "break" and "return" on error */
164         while(1)
165         {
166                 /* dummy-read - see flash manual */
167                 retval = target_read_u16(target, offset, &state1);
168                 if (retval != ERROR_OK)
169                         return retval;
170
171                 /* Data polling 1 */
172                 retval = target_read_u16(target, offset, &state1);
173                 if (retval != ERROR_OK)
174                         return retval;
175
176                 /* Data polling 2 */
177                 retval = target_read_u16(target, offset, &state2);
178                 if (retval != ERROR_OK)
179                         return retval;
180
181                 /* Flash command finished via polled data equal? */
182                 if ( (state1 & FLASH_DQ6) == (state2 & FLASH_DQ6) )
183                 {
184                         break;
185                 }
186                 /* Timeout Flag? */
187                 else if (state1 & FLASH_DQ5)
188                 {
189                         /* Retry data polling */
190
191                         /* Data polling 1 */
192                         retval = target_read_u16(target, offset, &state1);
193                         if (retval != ERROR_OK)
194                                 return retval;
195
196                         /* Data polling 2 */
197                         retval = target_read_u16(target, offset, &state2);
198                         if (retval != ERROR_OK)
199                                 return retval;
200
201                         /* Flash command finished via polled data equal? */
202                         if ( (state1 & FLASH_DQ6) != (state2 & FLASH_DQ6) )
203                         {
204                                 return ERROR_FLASH_OPERATION_FAILED;
205                         }
206
207                         /* finish anyway */
208                         break;
209                 }
210                 usleep(1000);
211                 ++ms;
212
213                 /* Polling time exceeded? */
214                 if (ms > timeout_ms)
215                 {
216                         LOG_ERROR("Polling data reading timed out!");
217                         return ERROR_FLASH_OPERATION_FAILED;
218                 }
219         }
220
221         if (retval == ERROR_OK)
222                 LOG_DEBUG("fm3_busy_wait(%x) needs about %d ms", offset, ms);
223
224         return retval;
225 }
226
227 static int fm3_erase(struct flash_bank *bank, int first, int last)
228 {
229         struct fm3_flash_bank *fm3_info = bank->driver_priv;
230         struct target *target = bank->target;
231         int retval = ERROR_OK;
232         uint32_t u32DummyRead;
233         int sector, odd;
234         uint32_t u32FlashType;
235         uint32_t u32FlashSeqAddress1;
236         uint32_t u32FlashSeqAddress2;
237
238         u32FlashType = (uint32_t) fm3_info->flashtype;
239
240         if (u32FlashType == fm3_flash_type1)
241         {
242                 u32FlashSeqAddress1 = 0x00001550;
243                 u32FlashSeqAddress2 = 0x00000AA8;
244         }
245         else if (u32FlashType == fm3_flash_type2)
246         {
247                 u32FlashSeqAddress1 = 0x00000AA8;
248                 u32FlashSeqAddress2 = 0x00000554;
249         }
250         else
251         {
252                 LOG_ERROR("Flash/Device type unknown!");
253                 return ERROR_FLASH_OPERATION_FAILED;
254         }
255
256         if (target->state != TARGET_HALTED) {
257                 LOG_ERROR("Target not halted");
258                 return ERROR_TARGET_NOT_HALTED;
259         }
260
261         LOG_INFO("Fujitsu MB9Bxxx: Sector Erase ... (%d to %d)", first, last);
262
263         /* FASZR = 0x01, Enables CPU Programming Mode (16-bit Flash acccess) */
264         retval = target_write_u32(target, 0x40000000, 0x0001);
265         if (retval != ERROR_OK)
266                 return retval;
267
268         /* dummy read of FASZR */
269         retval = target_read_u32(target, 0x40000000, &u32DummyRead);
270         if (retval != ERROR_OK)
271                 return retval;
272
273         for (sector = first ; sector <= last ; sector++)
274         {
275                 uint32_t offset = bank->sectors[sector].offset;
276
277                 for (odd = 0; odd < 2 ; odd++)
278                 {
279                         if (odd)
280                                 offset += 4;
281
282                         /* Flash unlock sequence */
283                         retval = target_write_u16(target, u32FlashSeqAddress1, 0x00AA);
284                         if (retval != ERROR_OK)
285                                 return retval;
286
287                         retval = target_write_u16(target, u32FlashSeqAddress2, 0x0055);
288                         if (retval != ERROR_OK)
289                                 return retval;
290
291                         retval = target_write_u16(target, u32FlashSeqAddress1, 0x0080);
292                         if (retval != ERROR_OK)
293                                 return retval;
294
295                         retval = target_write_u16(target, u32FlashSeqAddress1, 0x00AA);
296                         if (retval != ERROR_OK)
297                                 return retval;
298
299                         retval = target_write_u16(target, u32FlashSeqAddress2, 0x0055);
300                         if (retval != ERROR_OK)
301                                 return retval;
302
303                         /* Sector erase command (0x0030) */
304                         retval = target_write_u16(target, offset, 0x0030);
305                         if (retval != ERROR_OK)
306                                 return retval;
307
308                         retval = fm3_busy_wait(target, offset, 500);
309                         if (retval != ERROR_OK)
310                                 return retval;
311                 }
312                 bank->sectors[sector].is_erased = 1;
313         }
314
315         /* FASZR = 0x02, Enables CPU Run Mode (32-bit Flash acccess) */
316         retval = target_write_u32(target, 0x40000000, 0x0002);
317         if (retval != ERROR_OK)
318                 return retval;
319
320         /* dummy read of FASZR */
321         retval = target_read_u32(target, 0x40000000, &u32DummyRead);
322
323         return retval;
324 }
325
326 static int fm3_write_block(struct flash_bank *bank, uint8_t *buffer,
327                 uint32_t offset, uint32_t count)
328 {
329         struct fm3_flash_bank *fm3_info = bank->driver_priv;
330         struct target *target = bank->target;
331         uint32_t buffer_size = 2048;            /* 8192 for MB9Bxx6! */
332         struct working_area *source;
333         uint32_t address = bank->base + offset;
334         struct reg_param reg_params[6];
335         struct armv7m_algorithm armv7m_info;
336         int retval = ERROR_OK;
337         uint32_t u32FlashType;
338         uint32_t u32FlashSeqAddress1;
339         uint32_t u32FlashSeqAddress2;
340
341         u32FlashType = (uint32_t) fm3_info->flashtype;
342
343         if (u32FlashType == fm3_flash_type1)
344         {
345                 u32FlashSeqAddress1 = 0x00001550;
346                 u32FlashSeqAddress2 = 0x00000AA8;
347         }
348         else if (u32FlashType == fm3_flash_type2)
349         {
350                 u32FlashSeqAddress1 = 0x00000AA8;
351                 u32FlashSeqAddress2 = 0x00000554;
352         }
353         else
354         {
355                 LOG_ERROR("Flash/Device type unknown!");
356                 return ERROR_FLASH_OPERATION_FAILED;
357         }
358
359         /* RAMCODE used for fm3 Flash programming:                 */
360         /* R0 keeps source start address         (u32Source)       */
361         /* R1 keeps target start address         (u32Target)       */
362         /* R2 keeps number of halfwords to write (u32Count)        */
363         /* R3 keeps Flash Sequence address 1     (u32FlashSeq1)    */
364         /* R4 keeps Flash Sequence address 2     (u32FlashSeq2)    */
365         /* R5 returns result value               (u32FlashResult)  */
366
367         const uint8_t fm3_flash_write_code[] = {
368                                                                 /*    fm3_FLASH_IF->FASZ &= 0xFFFD;           */
369         0x5F, 0xF0, 0x80, 0x45,         /*        MOVS.W   R5, #(fm3_FLASH_IF->FASZ)  */
370         0x2D, 0x68,                                     /*        LDR      R5, [R5]                   */
371         0x4F, 0xF6, 0xFD, 0x76,         /*        MOVW     R6, #0xFFFD                */
372         0x35, 0x40,                                     /*        ANDS     R5, R5, R6                 */
373         0x5F, 0xF0, 0x80, 0x46,         /*        MOVS.W   R6, #(fm3_FLASH_IF->FASZ)  */
374         0x35, 0x60,                                     /*        STR      R5, [R6]                   */
375                                                                 /*    fm3_FLASH_IF->FASZ |= 1;                */
376         0x5F, 0xF0, 0x80, 0x45,         /*        MOVS.W   R5, #(fm3_FLASH_IF->FASZ)  */
377         0x2D, 0x68,                                     /*        LDR      R5, [R3]                   */
378         0x55, 0xF0, 0x01, 0x05,         /*        ORRS.W   R5, R5, #1                 */
379         0x5F, 0xF0, 0x80, 0x46,         /*        MOVS.W   R6, #(fm3_FLASH_IF->FASZ)  */
380         0x35, 0x60,                                     /*        STR      R5, [R6]                   */
381                                                                 /*    u32DummyRead = fm3_FLASH_IF->FASZ;      */
382         0x28, 0x4D,                                     /*        LDR.N    R5, ??u32DummyRead         */
383         0x5F, 0xF0, 0x80, 0x46,         /*        MOVS.W   R6, #(fm3_FLASH_IF->FASZ)  */
384         0x36, 0x68,                                     /*        LDR      R6, [R6]                   */
385         0x2E, 0x60,                                     /*        STR      R6, [R5]                   */
386                                                                 /*    u32FlashResult = FLASH_WRITE_NO_RESULT  */
387         0x26, 0x4D,                                     /*        LDR.N    R5, ??u32FlashResult       */
388         0x00, 0x26,                                     /*        MOVS     R6, #0                     */
389         0x2E, 0x60,                                     /*        STR      R6, [R5]                   */
390                                                                 /*    while ((u32Count > 0 )                  */
391                                                                 /*      && (u32FlashResult                    */
392                                                                 /*          == FLASH_WRITE_NO_RESULT))        */
393         0x01, 0x2A,                                     /* L0:    CMP      R2, #1                     */
394         0x2C, 0xDB,                                     /*        BLT.N    L1                         */
395         0x24, 0x4D,                                     /*        LDR.N    R5, ??u32FlashResult       */
396         0x2D, 0x68,                                     /*        LDR      R5, [R5]                   */
397         0x00, 0x2D,                                     /*        CMP      R5, #0                     */
398         0x28, 0xD1,                                     /*        BNE.N    L1                         */
399                                                                 /*    *u32FlashSeq1 = FLASH_WRITE_1;          */
400         0xAA, 0x25,                                     /*        MOVS     R5, #0xAA                  */
401         0x1D, 0x60,                                     /*        STR      R5, [R3]                   */
402                                                                 /*    *u32FlashSeq2 = FLASH_WRITE_2;          */
403         0x55, 0x25,                                     /*        MOVS     R5, #0x55                  */
404         0x25, 0x60,                                     /*        STR      R5, [R4]                   */
405                                                                 /*    *u32FlashSeq1 = FLASH_WRITE_3;          */
406         0xA0, 0x25,                                     /*        MOVS     R5, #0xA0                  */
407         0x1D, 0x60,                                     /*        STRH     R5, [R3]                   */
408                                                                 /*    *(volatile uint16_t*)u32Target          */
409                                                                 /*      = *(volatile uint16_t*)u32Source;     */
410         0x05, 0x88,                                     /*        LDRH     R5, [R0]                   */
411         0x0D, 0x80,                                     /*        STRH     R5, [R1]                   */
412                                                                 /*    while (u32FlashResult                   */
413                                                                 /*           == FLASH_WRITE_NO_RESTULT)       */
414         0x1E, 0x4D,                                     /* L2:    LDR.N    R5, ??u32FlashResult       */
415         0x2D, 0x68,                                     /*        LDR      R5, [R5]                   */
416         0x00, 0x2D,                                     /*        CMP      R5, #0                     */
417         0x11, 0xD1,                                     /*        BNE.N    L3                         */
418                                                                 /*    if ((*(volatile uint16_t*)u32Target     */
419                                                                 /*        & FLASH_DQ5) == FLASH_DQ5)          */
420         0x0D, 0x88,                                     /*        LDRH     R5, [R1]                   */
421         0xAD, 0x06,                                     /*        LSLS     R5, R5, #0x1A              */
422         0x02, 0xD5,                                     /*        BPL.N    L4                         */
423                                                                 /*    u32FlashResult = FLASH_WRITE_TIMEOUT    */
424         0x1A, 0x4D,                                     /*        LDR.N    R5, ??u32FlashResult       */
425         0x02, 0x26,                                     /*        MOVS     R6, #2                     */
426         0x2E, 0x60,                                     /*        STR      R6, [R5]                   */
427                                                                 /*    if ((*(volatile uint16_t *)u32Target    */
428                                                                 /*         & FLASH_DQ7)                       */
429                                                                 /*        == (*(volatile uint16_t*)u32Source  */
430                                                                 /*            & FLASH_DQ7))                   */
431         0x0D, 0x88,                                     /* L4:    LDRH     R5, [R1]                   */
432         0x15, 0xF0, 0x80, 0x05,         /*        ANDS.W   R5, R5, #0x80              */
433         0x06, 0x88,                                     /*        LDRH     R6, [R0]                   */
434         0x16, 0xF0, 0x80, 0x06,         /*        ANDS.W   R6, R6, #0x80              */
435         0xB5, 0x42,                                     /*        CMP      R5, R6                     */
436         0xED, 0xD1,                                     /*        BNE.N    L2                         */
437                                                                 /*    u32FlashResult = FLASH_WRITE_OKAY       */
438         0x15, 0x4D,                                     /*        LDR.N    R5, ??u32FlashResult       */
439         0x01, 0x26,                                     /*        MOVS     R6, #1                     */
440         0x2E, 0x60,                                     /*        STR      R6, [R5]                   */
441         0xE9, 0xE7,                                     /*        B.N      L2                         */
442                                                                 /*    if (u32FlashResult                      */
443                                                                 /*        != FLASH_WRITE_TIMEOUT)             */
444         0x13, 0x4D,                                     /*        LDR.N    R5, ??u32FlashResult       */
445         0x2D, 0x68,                                     /*        LDR      R5, [R5]                   */
446         0x02, 0x2D,                                     /*        CMP      R5, #2                     */
447         0x02, 0xD0,                                     /*        BEQ.N    L5                         */
448                                                                 /*    u32FlashResult = FLASH_WRITE_NO_RESULT  */
449         0x11, 0x4D,                                     /*        LDR.N    R5, ??u32FlashResult       */
450         0x00, 0x26,                                     /*        MOVS     R6, #0                     */
451         0x2E, 0x60,                                     /*        STR      R6, [R5]                   */
452                                                                 /*    u32Count--;                             */
453         0x52, 0x1E,                                     /* L5:    SUBS     R2, R2, #1                 */
454                                                                 /*    u32Source += 2;                         */
455         0x80, 0x1C,                                     /*        ADDS     R0, R0, #2                 */
456                                                                 /*    u32Target += 2;                         */
457         0x89, 0x1C,                                     /*        ADDS     R1, R1, #2                 */
458         0xD0, 0xE7,                                     /*        B.N      L0                         */
459                                                                 /*    fm3_FLASH_IF->FASZ &= 0xFFFE;           */
460         0x5F, 0xF0, 0x80, 0x45,         /* L1:    MOVS.W   R5, #(fm3_FLASH_IF->FASZ)  */
461         0x2D, 0x68,                                     /*        LDR      R5, [R5]                   */
462         0x4F, 0xF6, 0xFE, 0x76,         /*        MOVW     R6, #0xFFFE                */
463         0x35, 0x40,                                     /*        ANDS     R5, R5, R6                 */
464         0x5F, 0xF0, 0x80, 0x46,         /*        MOVS.W   R6, #(fm3_FLASH_IF->FASZ)  */
465         0x35, 0x60,                                     /*        STR      R5, [R6]                   */
466                                                                 /*    fm3_FLASH_IF->FASZ |= 2;                */
467         0x5F, 0xF0, 0x80, 0x45,         /*        MOVS.W   R5, #(fm3_FLASH_IF->FASZ)  */
468         0x2D, 0x68,                                     /*        LDR      R5, [R5]                   */
469         0x55, 0xF0, 0x02, 0x05,         /*        ORRS.W   R5, R5, #2                 */
470         0x5F, 0xF0, 0x80, 0x46,         /*        MOVS.W   R6, #(fm3_FLASH_IF->FASZ)  */
471         0x35, 0x60,                                     /*        STR      R5, [R6]                   */
472                                                                 /*    u32DummyRead = fm3_FLASH_IF->FASZ;      */
473         0x04, 0x4D,                                     /*        LDR.N    R5, ??u32DummyRead         */
474         0x5F, 0xF0, 0x80, 0x46,         /*        MOVS.W   R6, #(fm3_FLASH_IF->FASZ)  */
475         0x36, 0x68,                                     /*        LDR      R6, [R6]                   */
476         0x2E, 0x60,                                     /*        STR      R6, [R5]                   */
477                                                                 /*    copy u32FlashResult to R3 for return    */
478                                                                 /*      value                                 */
479         0xDF, 0xF8, 0x08, 0x50,         /*        LDR.W    R5, ??u32FlashResult       */
480         0x2D, 0x68,                                     /*        LDR      R5, [R5]                   */
481                                                                 /*    Breakpoint here                         */
482         0x00, 0xBE,                                     /*        BKPT     #0                         */
483
484         /* The following address pointers assume, that the code is running from   */
485         /* address 0x1FFF8008. These address pointers will be patched, if a       */
486         /* different start address in RAM is used (e.g. for Flash type 2)!        */
487         0x00, 0x80, 0xFF, 0x1F,         /* u32DummyRead address in RAM (0x1FFF8000)   */
488         0x04, 0x80, 0xFF, 0x1F          /* u32FlashResult address in RAM (0x1FFF8004) */
489         };
490
491         LOG_INFO("Fujitsu MB9B500: FLASH Write ...");
492
493         /* disable HW watchdog */
494         retval = target_write_u32(target, 0x40011C00, 0x1ACCE551);
495         if (retval != ERROR_OK)
496                 return retval;
497
498         retval = target_write_u32(target, 0x40011C00, 0xE5331AAE);
499         if (retval != ERROR_OK)
500                 return retval;
501
502         retval = target_write_u32(target, 0x40011008, 0x00000000);
503         if (retval != ERROR_OK)
504                 return retval;
505
506         count = count / 2;              /* number bytes -> number halfwords */
507
508         /* check code alignment */
509         if (offset & 0x1)
510         {
511                 LOG_WARNING("offset 0x%" PRIx32 " breaks required 2-byte alignment", offset);
512                 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
513         }
514
515         /* allocate working area with flash programming code */
516         if (target_alloc_working_area(target, sizeof(fm3_flash_write_code),
517                         &fm3_info->write_algorithm) != ERROR_OK)
518         {
519                 LOG_WARNING("no working area available, can't do block memory writes");
520                 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
521         }
522
523         retval = target_write_buffer(target, fm3_info->write_algorithm->address,
524                 sizeof(fm3_flash_write_code), fm3_flash_write_code);
525         if (retval != ERROR_OK)
526                 return retval;
527
528         /* memory buffer */
529         while (target_alloc_working_area(target, buffer_size, &source) != ERROR_OK)
530         {
531                 buffer_size /= 2;
532                 if (buffer_size <= 256)
533                 {
534                         /* free working area, if write algorithm already allocated */
535                         if (fm3_info->write_algorithm)
536                         {
537                                 target_free_working_area(target, fm3_info->write_algorithm);
538                         }
539
540                         LOG_WARNING("No large enough working area available, can't do block memory writes");
541                         return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
542                 }
543         }
544
545         armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
546         armv7m_info.core_mode = ARMV7M_MODE_ANY;
547
548         init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT); /* source start address */
549         init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT); /* target start address */
550         init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT); /* number of halfwords to program */
551         init_reg_param(&reg_params[3], "r3", 32, PARAM_OUT); /* Flash Sequence address 1 */
552         init_reg_param(&reg_params[4], "r4", 32, PARAM_OUT); /* Flash Sequence address 1 */
553         init_reg_param(&reg_params[5], "r5", 32, PARAM_IN);  /* result */
554
555         /* write code buffer and use Flash programming code within fm3 */
556         /* Set breakpoint to 0 with time-out of 1000 ms */
557         while (count > 0)
558         {
559                 uint32_t thisrun_count = (count > (buffer_size / 2)) ? (buffer_size / 2) : count;
560
561                 retval = target_write_buffer(target, fm3_info->write_algorithm->address,
562                                 8, fm3_flash_write_code);
563                 if (retval != ERROR_OK)
564                         break;
565
566                 /* Patching 'local variable address' for different RAM addresses */
567                 if (fm3_info->write_algorithm->address != 0x1FFF8008)
568                 {
569                         /* Algorithm: u32DummyRead: */
570                         retval = target_write_u32(target, (fm3_info->write_algorithm->address)
571                                         + sizeof(fm3_flash_write_code) - 8,
572                                         (fm3_info->write_algorithm->address) - 8);
573                         if (retval != ERROR_OK)
574                                 break;
575
576                         /* Algorithm: u32FlashResult: */
577                         retval = target_write_u32(target, (fm3_info->write_algorithm->address)
578                                         + sizeof(fm3_flash_write_code) - 4, (fm3_info->write_algorithm->address) - 4);
579                         if (retval != ERROR_OK)
580                                 break;
581                 }
582
583                 retval = target_write_buffer(target, source->address, thisrun_count * 2,
584                                 buffer);
585                 if (retval != ERROR_OK)
586                         break;
587
588                 buf_set_u32(reg_params[0].value, 0, 32, source->address);
589                 buf_set_u32(reg_params[1].value, 0, 32, address);
590                 buf_set_u32(reg_params[2].value, 0, 32, thisrun_count);
591                 buf_set_u32(reg_params[3].value, 0, 32, u32FlashSeqAddress1);
592                 buf_set_u32(reg_params[4].value, 0, 32, u32FlashSeqAddress2);
593
594                 retval = target_run_algorithm(target, 0, NULL, 6, reg_params,
595                                 fm3_info->write_algorithm->address, 0, 1000, &armv7m_info);
596                 if (retval != ERROR_OK)
597                 {
598                         LOG_ERROR("Error executing fm3 Flash programming algorithm");
599                         retval = ERROR_FLASH_OPERATION_FAILED;
600                         break;
601                 }
602
603                 if (buf_get_u32(reg_params[5].value, 0, 32) != ERROR_OK)
604                 {
605                         LOG_ERROR("Fujitsu MB9[A/B]FXXX: Flash programming ERROR (Timeout) \
606                                         -> Reg R3: %x", buf_get_u32(reg_params[5].value, 0, 32));
607                         retval = ERROR_FLASH_OPERATION_FAILED;
608                         break;
609                 }
610
611                 buffer  += thisrun_count * 2;
612                 address += thisrun_count * 2;
613                 count   -= thisrun_count;
614         }
615
616         target_free_working_area(target, source);
617         target_free_working_area(target, fm3_info->write_algorithm);
618
619         destroy_reg_param(&reg_params[0]);
620         destroy_reg_param(&reg_params[1]);
621         destroy_reg_param(&reg_params[2]);
622         destroy_reg_param(&reg_params[3]);
623         destroy_reg_param(&reg_params[4]);
624         destroy_reg_param(&reg_params[5]);
625
626         return retval;
627 }
628
629 static int fm3_probe(struct flash_bank *bank)
630 {
631         struct fm3_flash_bank *fm3_info = bank->driver_priv;
632         uint16_t num_pages;
633
634         if (bank->target->state != TARGET_HALTED)
635         {
636                 LOG_ERROR("Target not halted");
637                 return ERROR_TARGET_NOT_HALTED;
638         }
639
640         num_pages = 6;                          /* max number of Flash pages for malloc */
641         fm3_info->probed = 0;
642
643         bank->sectors = malloc(sizeof(struct flash_sector) * num_pages);
644         bank->base = 0x00000000;
645         bank->size = 32 * 1024;         /* bytes */
646
647         bank->sectors[0].offset = 0;
648         bank->sectors[0].size = 16 * 1024;
649         bank->sectors[0].is_erased = -1;
650         bank->sectors[0].is_protected = -1;
651
652         bank->sectors[1].offset = 0x4000;
653         bank->sectors[1].size = 16 * 1024;
654         bank->sectors[1].is_erased = -1;
655         bank->sectors[1].is_protected = -1;
656
657         if ((fm3_info->variant == mb9bfxx1) || (fm3_info->variant == mb9afxx1))
658         {
659                 num_pages = 3;
660                 bank->size = 64 * 1024; /* bytes */
661                 bank->num_sectors = num_pages;
662
663                 bank->sectors[2].offset = 0x8000;
664                 bank->sectors[2].size = 32 * 1024;
665                 bank->sectors[2].is_erased = -1;
666                 bank->sectors[2].is_protected = -1;
667         }
668
669         if ((fm3_info->variant == mb9bfxx2)
670                 || (fm3_info->variant == mb9bfxx4)
671                 || (fm3_info->variant == mb9bfxx5)
672                 || (fm3_info->variant == mb9bfxx6)
673                 || (fm3_info->variant == mb9afxx2)
674                 || (fm3_info->variant == mb9afxx4)
675                 || (fm3_info->variant == mb9afxx5)
676                 || (fm3_info->variant == mb9afxx6))
677         {
678                 num_pages = 3;
679                 bank->size = 128 * 1024; /* bytes */
680                 bank->num_sectors = num_pages;
681
682                 bank->sectors[2].offset = 0x8000;
683                 bank->sectors[2].size = 96 * 1024;
684                 bank->sectors[2].is_erased = -1;
685                 bank->sectors[2].is_protected = -1;
686         }
687
688         if ((fm3_info->variant == mb9bfxx4)
689                 || (fm3_info->variant == mb9bfxx5)
690                 || (fm3_info->variant == mb9bfxx6)
691                 || (fm3_info->variant == mb9afxx4)
692                 || (fm3_info->variant == mb9afxx5)
693                 || (fm3_info->variant == mb9afxx6))
694         {
695                 num_pages = 4;
696                 bank->size = 256 * 1024; /* bytes */
697                 bank->num_sectors = num_pages;
698
699                 bank->sectors[3].offset = 0x20000;
700                 bank->sectors[3].size = 128 * 1024;
701                 bank->sectors[3].is_erased = -1;
702                 bank->sectors[3].is_protected = -1;
703         }
704
705         if ((fm3_info->variant == mb9bfxx5)
706                 || (fm3_info->variant == mb9bfxx6)
707                 || (fm3_info->variant == mb9afxx5)
708                 || (fm3_info->variant == mb9afxx6))
709         {
710                 num_pages = 5;
711                 bank->size = 384 * 1024; /* bytes */
712                 bank->num_sectors = num_pages;
713
714                 bank->sectors[4].offset = 0x40000;
715                 bank->sectors[4].size = 128 * 1024;
716                 bank->sectors[4].is_erased = -1;
717                 bank->sectors[4].is_protected = -1;
718         }
719
720         if ((fm3_info->variant == mb9bfxx6)
721                 || (fm3_info->variant == mb9afxx6))
722         {
723                 num_pages = 6;
724                 bank->size = 512 * 1024; /* bytes */
725                 bank->num_sectors = num_pages;
726
727                 bank->sectors[5].offset = 0x60000;
728                 bank->sectors[5].size = 128 * 1024;
729                 bank->sectors[5].is_erased = -1;
730                 bank->sectors[5].is_protected = -1;
731         }
732
733         fm3_info->probed = 1;
734
735         return ERROR_OK;
736 }
737
738 static int fm3_auto_probe(struct flash_bank *bank)
739 {
740         struct fm3_flash_bank *fm3_info = bank->driver_priv;
741         if (fm3_info->probed)
742                 return ERROR_OK;
743         return fm3_probe(bank);
744 }
745
746 static int fm3_info_cmd(struct flash_bank *bank, char *buf, int buf_size)
747 {
748         snprintf(buf, buf_size, "Fujitsu fm3 Device does not support Chip-ID (Type unknown)");
749         return ERROR_OK;
750 }
751
752 static int fm3_chip_erase(struct flash_bank *bank)
753 {
754         struct target *target = bank->target;
755         struct fm3_flash_bank *fm3_info = bank->driver_priv;
756         int retval = ERROR_OK;
757         uint32_t u32DummyRead;
758         uint32_t u32FlashType;
759         uint32_t u32FlashSeqAddress1;
760         uint32_t u32FlashSeqAddress2;
761
762         u32FlashType = (uint32_t) fm3_info->flashtype;
763
764         if (u32FlashType == fm3_flash_type1)
765         {
766                 LOG_INFO("*** Erasing mb9bfxxx type");
767                 u32FlashSeqAddress1 = 0x00001550;
768                 u32FlashSeqAddress2 = 0x00000AA8;
769         }
770         else if (u32FlashType == fm3_flash_type2)
771         {
772                 LOG_INFO("*** Erasing mb9afxxx type");
773                 u32FlashSeqAddress1 = 0x00000AA8;
774                 u32FlashSeqAddress2 = 0x00000554;
775         }
776         else
777         {
778                 LOG_ERROR("Flash/Device type unknown!");
779                 return ERROR_FLASH_OPERATION_FAILED;
780         }
781
782         if (target->state != TARGET_HALTED)
783         {
784                 LOG_ERROR("Target not halted");
785                 return ERROR_TARGET_NOT_HALTED;
786         }
787
788         LOG_INFO("Fujitsu MB9[AB]xxx: Chip Erase ... (may take several seconds)");
789
790         /* Implement Flash chip erase (mass erase) completely on host */
791
792         /* FASZR = 0x01, Enables CPU Programming Mode (16-bit Flash access) */
793         retval = target_write_u32(target, 0x40000000, 0x0001);
794         if (retval != ERROR_OK)
795                 return retval;
796
797         /* dummy read of FASZR */
798         retval = target_read_u32(target, 0x40000000, &u32DummyRead);
799         if (retval != ERROR_OK)
800                 return retval;
801
802         /* Flash unlock sequence */
803         retval = target_write_u16(target, u32FlashSeqAddress1, 0x00AA);
804         if (retval != ERROR_OK)
805                 return retval;
806
807         retval = target_write_u16(target, u32FlashSeqAddress2, 0x0055);
808         if (retval != ERROR_OK)
809                 return retval;
810
811         retval = target_write_u16(target, u32FlashSeqAddress1, 0x0080);
812         if (retval != ERROR_OK)
813                 return retval;
814
815         retval = target_write_u16(target, u32FlashSeqAddress1, 0x00AA);
816         if (retval != ERROR_OK)
817                 return retval;
818
819         retval = target_write_u16(target, u32FlashSeqAddress2, 0x0055);
820         if (retval != ERROR_OK)
821                 return retval;
822
823         /* Chip Erase command (0x0010) */
824         retval = target_write_u16(target, u32FlashSeqAddress1, 0x0010);
825         if (retval != ERROR_OK)
826                 return retval;
827
828         retval = fm3_busy_wait(target, u32FlashSeqAddress2, 20000);     /* 20s timeout */
829         if (retval != ERROR_OK)
830                 return retval;
831
832         /* FASZR = 0x02, Re-enables CPU Run Mode (32-bit Flash access) */
833         retval = target_write_u32(target, 0x40000000, 0x0002);
834         if (retval != ERROR_OK)
835                 return retval;
836
837         /* dummy read of FASZR */
838         retval = target_read_u32(target, 0x40000000, &u32DummyRead);
839
840         return retval;
841 }
842
843 COMMAND_HANDLER(fm3_handle_chip_erase_command)
844 {
845         int i;
846
847         if (CMD_ARGC < 1)
848         {
849                 return ERROR_COMMAND_SYNTAX_ERROR;
850         }
851
852         struct flash_bank *bank;
853         int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
854         if (ERROR_OK != retval)
855                 return retval;
856
857         if (fm3_chip_erase(bank) == ERROR_OK)
858         {
859                 /* set all sectors as erased */
860                 for (i = 0; i < bank->num_sectors; i++)
861                         bank->sectors[i].is_erased = 1;
862
863                 command_print(CMD_CTX, "fm3 chip erase complete");
864         }
865         else
866         {
867                 command_print(CMD_CTX, "fm3 chip erase failed");
868         }
869
870         return ERROR_OK;
871 }
872
873 static const struct command_registration fm3_exec_command_handlers[] = {
874         {
875                 .name = "chip_erase",
876                 .usage = "<bank>",
877                 .handler = fm3_handle_chip_erase_command,
878                 .mode = COMMAND_EXEC,
879                 .help = "Erase entire Flash device.",
880         },
881         COMMAND_REGISTRATION_DONE
882 };
883
884 static const struct command_registration fm3_command_handlers[] = {
885         {
886                 .name = "fm3",
887                 .mode = COMMAND_ANY,
888                 .help = "fm3 Flash command group",
889                 .usage = "",
890                 .chain = fm3_exec_command_handlers,
891         },
892         COMMAND_REGISTRATION_DONE
893 };
894
895 struct flash_driver fm3_flash = {
896         .name = "fm3",
897         .commands = fm3_command_handlers,
898         .flash_bank_command = fm3_flash_bank_command,
899         .erase = fm3_erase,
900         .write = fm3_write_block,
901         .probe = fm3_probe,
902         .auto_probe = fm3_auto_probe,
903         .erase_check = default_flash_mem_blank_check,
904         .info = fm3_info_cmd,
905 };