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