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