]> git.sur5r.net Git - openocd/blob - src/flash/nor/fm3.c
09ce3173822733bd52c66a4cc1569c7ddefc84e8
[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  *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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(%" PRIx32 ") 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 MB9[A/B]FXXX: 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;            /* Default minimum value */
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         /* Increase buffer_size if needed */
311         if (buffer_size < (target->working_area_size / 2))
312                 buffer_size = (target->working_area_size / 2);
313
314         u32FlashType = (uint32_t) fm3_info->flashtype;
315
316         if (u32FlashType == fm3_flash_type1) {
317                 u32FlashSeqAddress1 = 0x00001550;
318                 u32FlashSeqAddress2 = 0x00000AA8;
319         } else if (u32FlashType == fm3_flash_type2) {
320                 u32FlashSeqAddress1 = 0x00000AA8;
321                 u32FlashSeqAddress2 = 0x00000554;
322         } else {
323                 LOG_ERROR("Flash/Device type unknown!");
324                 return ERROR_FLASH_OPERATION_FAILED;
325         }
326
327         /* RAMCODE used for fm3 Flash programming:                 */
328         /* R0 keeps source start address         (u32Source)       */
329         /* R1 keeps target start address         (u32Target)       */
330         /* R2 keeps number of halfwords to write (u32Count)        */
331         /* R3 keeps Flash Sequence address 1     (u32FlashSeq1)    */
332         /* R4 keeps Flash Sequence address 2     (u32FlashSeq2)    */
333         /* R5 returns result value               (u32FlashResult)  */
334
335         const uint8_t fm3_flash_write_code[] = {
336                                                                 /*    fm3_FLASH_IF->FASZ &= 0xFFFD;           */
337         0x5F, 0xF0, 0x80, 0x45,         /*        MOVS.W   R5, #(fm3_FLASH_IF->FASZ)  */
338         0x2D, 0x68,                                     /*        LDR      R5, [R5]                   */
339         0x4F, 0xF6, 0xFD, 0x76,         /*        MOVW     R6, #0xFFFD                */
340         0x35, 0x40,                                     /*        ANDS     R5, R5, R6                 */
341         0x5F, 0xF0, 0x80, 0x46,         /*        MOVS.W   R6, #(fm3_FLASH_IF->FASZ)  */
342         0x35, 0x60,                                     /*        STR      R5, [R6]                   */
343                                                                 /*    fm3_FLASH_IF->FASZ |= 1;                */
344         0x5F, 0xF0, 0x80, 0x45,         /*        MOVS.W   R5, #(fm3_FLASH_IF->FASZ)  */
345         0x2D, 0x68,                                     /*        LDR      R5, [R3]                   */
346         0x55, 0xF0, 0x01, 0x05,         /*        ORRS.W   R5, R5, #1                 */
347         0x5F, 0xF0, 0x80, 0x46,         /*        MOVS.W   R6, #(fm3_FLASH_IF->FASZ)  */
348         0x35, 0x60,                                     /*        STR      R5, [R6]                   */
349                                                                 /*    u32DummyRead = fm3_FLASH_IF->FASZ;      */
350         0x28, 0x4D,                                     /*        LDR.N    R5, ??u32DummyRead         */
351         0x5F, 0xF0, 0x80, 0x46,         /*        MOVS.W   R6, #(fm3_FLASH_IF->FASZ)  */
352         0x36, 0x68,                                     /*        LDR      R6, [R6]                   */
353         0x2E, 0x60,                                     /*        STR      R6, [R5]                   */
354                                                                 /*    u32FlashResult = FLASH_WRITE_NO_RESULT  */
355         0x26, 0x4D,                                     /*        LDR.N    R5, ??u32FlashResult       */
356         0x00, 0x26,                                     /*        MOVS     R6, #0                     */
357         0x2E, 0x60,                                     /*        STR      R6, [R5]                   */
358                                                                 /*    while ((u32Count > 0 )                  */
359                                                                 /*      && (u32FlashResult                    */
360                                                                 /*          == FLASH_WRITE_NO_RESULT))        */
361         0x01, 0x2A,                                     /* L0:    CMP      R2, #1                     */
362         0x2C, 0xDB,                                     /*        BLT.N    L1                         */
363         0x24, 0x4D,                                     /*        LDR.N    R5, ??u32FlashResult       */
364         0x2D, 0x68,                                     /*        LDR      R5, [R5]                   */
365         0x00, 0x2D,                                     /*        CMP      R5, #0                     */
366         0x28, 0xD1,                                     /*        BNE.N    L1                         */
367                                                                 /*    *u32FlashSeq1 = FLASH_WRITE_1;          */
368         0xAA, 0x25,                                     /*        MOVS     R5, #0xAA                  */
369         0x1D, 0x60,                                     /*        STR      R5, [R3]                   */
370                                                                 /*    *u32FlashSeq2 = FLASH_WRITE_2;          */
371         0x55, 0x25,                                     /*        MOVS     R5, #0x55                  */
372         0x25, 0x60,                                     /*        STR      R5, [R4]                   */
373                                                                 /*    *u32FlashSeq1 = FLASH_WRITE_3;          */
374         0xA0, 0x25,                                     /*        MOVS     R5, #0xA0                  */
375         0x1D, 0x60,                                     /*        STRH     R5, [R3]                   */
376                                                                 /*    *(volatile uint16_t*)u32Target          */
377                                                                 /*      = *(volatile uint16_t*)u32Source;     */
378         0x05, 0x88,                                     /*        LDRH     R5, [R0]                   */
379         0x0D, 0x80,                                     /*        STRH     R5, [R1]                   */
380                                                                 /*    while (u32FlashResult                   */
381                                                                 /*           == FLASH_WRITE_NO_RESTULT)       */
382         0x1E, 0x4D,                                     /* L2:    LDR.N    R5, ??u32FlashResult       */
383         0x2D, 0x68,                                     /*        LDR      R5, [R5]                   */
384         0x00, 0x2D,                                     /*        CMP      R5, #0                     */
385         0x11, 0xD1,                                     /*        BNE.N    L3                         */
386                                                                 /*    if ((*(volatile uint16_t*)u32Target     */
387                                                                 /*        & FLASH_DQ5) == FLASH_DQ5)          */
388         0x0D, 0x88,                                     /*        LDRH     R5, [R1]                   */
389         0xAD, 0x06,                                     /*        LSLS     R5, R5, #0x1A              */
390         0x02, 0xD5,                                     /*        BPL.N    L4                         */
391                                                                 /*    u32FlashResult = FLASH_WRITE_TIMEOUT    */
392         0x1A, 0x4D,                                     /*        LDR.N    R5, ??u32FlashResult       */
393         0x02, 0x26,                                     /*        MOVS     R6, #2                     */
394         0x2E, 0x60,                                     /*        STR      R6, [R5]                   */
395                                                                 /*    if ((*(volatile uint16_t *)u32Target    */
396                                                                 /*         & FLASH_DQ7)                       */
397                                                                 /*        == (*(volatile uint16_t*)u32Source  */
398                                                                 /*            & FLASH_DQ7))                   */
399         0x0D, 0x88,                                     /* L4:    LDRH     R5, [R1]                   */
400         0x15, 0xF0, 0x80, 0x05,         /*        ANDS.W   R5, R5, #0x80              */
401         0x06, 0x88,                                     /*        LDRH     R6, [R0]                   */
402         0x16, 0xF0, 0x80, 0x06,         /*        ANDS.W   R6, R6, #0x80              */
403         0xB5, 0x42,                                     /*        CMP      R5, R6                     */
404         0xED, 0xD1,                                     /*        BNE.N    L2                         */
405                                                                 /*    u32FlashResult = FLASH_WRITE_OKAY       */
406         0x15, 0x4D,                                     /*        LDR.N    R5, ??u32FlashResult       */
407         0x01, 0x26,                                     /*        MOVS     R6, #1                     */
408         0x2E, 0x60,                                     /*        STR      R6, [R5]                   */
409         0xE9, 0xE7,                                     /*        B.N      L2                         */
410                                                                 /*    if (u32FlashResult                      */
411                                                                 /*        != FLASH_WRITE_TIMEOUT)             */
412         0x13, 0x4D,                                     /*        LDR.N    R5, ??u32FlashResult       */
413         0x2D, 0x68,                                     /*        LDR      R5, [R5]                   */
414         0x02, 0x2D,                                     /*        CMP      R5, #2                     */
415         0x02, 0xD0,                                     /*        BEQ.N    L5                         */
416                                                                 /*    u32FlashResult = FLASH_WRITE_NO_RESULT  */
417         0x11, 0x4D,                                     /*        LDR.N    R5, ??u32FlashResult       */
418         0x00, 0x26,                                     /*        MOVS     R6, #0                     */
419         0x2E, 0x60,                                     /*        STR      R6, [R5]                   */
420                                                                 /*    u32Count--;                             */
421         0x52, 0x1E,                                     /* L5:    SUBS     R2, R2, #1                 */
422                                                                 /*    u32Source += 2;                         */
423         0x80, 0x1C,                                     /*        ADDS     R0, R0, #2                 */
424                                                                 /*    u32Target += 2;                         */
425         0x89, 0x1C,                                     /*        ADDS     R1, R1, #2                 */
426         0xD0, 0xE7,                                     /*        B.N      L0                         */
427                                                                 /*    fm3_FLASH_IF->FASZ &= 0xFFFE;           */
428         0x5F, 0xF0, 0x80, 0x45,         /* L1:    MOVS.W   R5, #(fm3_FLASH_IF->FASZ)  */
429         0x2D, 0x68,                                     /*        LDR      R5, [R5]                   */
430         0x4F, 0xF6, 0xFE, 0x76,         /*        MOVW     R6, #0xFFFE                */
431         0x35, 0x40,                                     /*        ANDS     R5, R5, R6                 */
432         0x5F, 0xF0, 0x80, 0x46,         /*        MOVS.W   R6, #(fm3_FLASH_IF->FASZ)  */
433         0x35, 0x60,                                     /*        STR      R5, [R6]                   */
434                                                                 /*    fm3_FLASH_IF->FASZ |= 2;                */
435         0x5F, 0xF0, 0x80, 0x45,         /*        MOVS.W   R5, #(fm3_FLASH_IF->FASZ)  */
436         0x2D, 0x68,                                     /*        LDR      R5, [R5]                   */
437         0x55, 0xF0, 0x02, 0x05,         /*        ORRS.W   R5, R5, #2                 */
438         0x5F, 0xF0, 0x80, 0x46,         /*        MOVS.W   R6, #(fm3_FLASH_IF->FASZ)  */
439         0x35, 0x60,                                     /*        STR      R5, [R6]                   */
440                                                                 /*    u32DummyRead = fm3_FLASH_IF->FASZ;      */
441         0x04, 0x4D,                                     /*        LDR.N    R5, ??u32DummyRead         */
442         0x5F, 0xF0, 0x80, 0x46,         /*        MOVS.W   R6, #(fm3_FLASH_IF->FASZ)  */
443         0x36, 0x68,                                     /*        LDR      R6, [R6]                   */
444         0x2E, 0x60,                                     /*        STR      R6, [R5]                   */
445                                                                 /*    copy u32FlashResult to R3 for return    */
446                                                                 /*      value                                 */
447         0xDF, 0xF8, 0x08, 0x50,         /*        LDR.W    R5, ??u32FlashResult       */
448         0x2D, 0x68,                                     /*        LDR      R5, [R5]                   */
449                                                                 /*    Breakpoint here                         */
450         0x00, 0xBE,                                     /*        BKPT     #0                         */
451
452         /* The following address pointers assume, that the code is running from   */
453         /* SRAM basic-address + 8.These address pointers will be patched, if a    */
454         /* different start address in RAM is used (e.g. for Flash type 2)!        */
455         /* Default SRAM basic-address is 0x20000000.                              */
456         0x00, 0x00, 0x00, 0x20,     /* u32DummyRead address in RAM (0x20000000)   */
457         0x04, 0x00, 0x00, 0x20      /* u32FlashResult address in RAM (0x20000004) */
458         };
459
460         LOG_INFO("Fujitsu MB9[A/B]FXXX: FLASH Write ...");
461
462         /* disable HW watchdog */
463         retval = target_write_u32(target, 0x40011C00, 0x1ACCE551);
464         if (retval != ERROR_OK)
465                 return retval;
466
467         retval = target_write_u32(target, 0x40011C00, 0xE5331AAE);
468         if (retval != ERROR_OK)
469                 return retval;
470
471         retval = target_write_u32(target, 0x40011008, 0x00000000);
472         if (retval != ERROR_OK)
473                 return retval;
474
475         count = count / 2;              /* number bytes -> number halfwords */
476
477         /* check code alignment */
478         if (offset & 0x1) {
479                 LOG_WARNING("offset 0x%" PRIx32 " breaks required 2-byte alignment", offset);
480                 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
481         }
482
483         /* allocate working area and variables with flash programming code */
484         if (target_alloc_working_area(target, sizeof(fm3_flash_write_code) + 8,
485                         &write_algorithm) != ERROR_OK) {
486                 LOG_WARNING("no working area available, can't do block memory writes");
487                 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
488         }
489
490         retval = target_write_buffer(target, write_algorithm->address + 8,
491                 sizeof(fm3_flash_write_code), fm3_flash_write_code);
492         if (retval != ERROR_OK)
493                 return retval;
494
495         /* Patching 'local variable address' */
496         /* Algorithm: u32DummyRead: */
497         retval = target_write_u32(target, (write_algorithm->address + 8)
498                         + sizeof(fm3_flash_write_code) - 8, (write_algorithm->address));
499         if (retval != ERROR_OK)
500                 return retval;
501         /* Algorithm: u32FlashResult: */
502         retval = target_write_u32(target, (write_algorithm->address + 8)
503                         + sizeof(fm3_flash_write_code) - 4, (write_algorithm->address) + 4);
504         if (retval != ERROR_OK)
505                 return retval;
506
507
508
509         /* memory buffer */
510         while (target_alloc_working_area(target, buffer_size, &source) != ERROR_OK) {
511                 buffer_size /= 2;
512                 if (buffer_size <= 256) {
513                         /* free working area, write algorithm already allocated */
514                         target_free_working_area(target, write_algorithm);
515
516                         LOG_WARNING("No large enough working area available, can't do block memory writes");
517                         return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
518                 }
519         }
520
521         armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
522         armv7m_info.core_mode = ARM_MODE_THREAD;
523
524         init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT); /* source start address */
525         init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT); /* target start address */
526         init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT); /* number of halfwords to program */
527         init_reg_param(&reg_params[3], "r3", 32, PARAM_OUT); /* Flash Sequence address 1 */
528         init_reg_param(&reg_params[4], "r4", 32, PARAM_OUT); /* Flash Sequence address 1 */
529         init_reg_param(&reg_params[5], "r5", 32, PARAM_IN);  /* result */
530
531         /* write code buffer and use Flash programming code within fm3           */
532         /* Set breakpoint to 0 with time-out of 1000 ms                          */
533         while (count > 0) {
534                 uint32_t thisrun_count = (count > (buffer_size / 2)) ? (buffer_size / 2) : count;
535
536                 retval = target_write_buffer(target, source->address, thisrun_count * 2, buffer);
537                 if (retval != ERROR_OK)
538                         break;
539
540                 buf_set_u32(reg_params[0].value, 0, 32, source->address);
541                 buf_set_u32(reg_params[1].value, 0, 32, address);
542                 buf_set_u32(reg_params[2].value, 0, 32, thisrun_count);
543                 buf_set_u32(reg_params[3].value, 0, 32, u32FlashSeqAddress1);
544                 buf_set_u32(reg_params[4].value, 0, 32, u32FlashSeqAddress2);
545
546                 retval = target_run_algorithm(target, 0, NULL, 6, reg_params,
547                                 (write_algorithm->address + 8), 0, 1000, &armv7m_info);
548                 if (retval != ERROR_OK) {
549                         LOG_ERROR("Error executing fm3 Flash programming algorithm");
550                         retval = ERROR_FLASH_OPERATION_FAILED;
551                         break;
552                 }
553
554                 if (buf_get_u32(reg_params[5].value, 0, 32) != ERROR_OK) {
555                         LOG_ERROR("Fujitsu MB9[A/B]FXXX: Flash programming ERROR (Timeout) -> Reg R3: %" PRIx32,
556                                 buf_get_u32(reg_params[5].value, 0, 32));
557                         retval = ERROR_FLASH_OPERATION_FAILED;
558                         break;
559                 }
560
561                 buffer  += thisrun_count * 2;
562                 address += thisrun_count * 2;
563                 count   -= thisrun_count;
564         }
565
566         target_free_working_area(target, source);
567         target_free_working_area(target, write_algorithm);
568
569         destroy_reg_param(&reg_params[0]);
570         destroy_reg_param(&reg_params[1]);
571         destroy_reg_param(&reg_params[2]);
572         destroy_reg_param(&reg_params[3]);
573         destroy_reg_param(&reg_params[4]);
574         destroy_reg_param(&reg_params[5]);
575
576         return retval;
577 }
578
579 static int fm3_probe(struct flash_bank *bank)
580 {
581         struct fm3_flash_bank *fm3_info = bank->driver_priv;
582         uint16_t num_pages;
583
584         if (bank->target->state != TARGET_HALTED) {
585                 LOG_ERROR("Target not halted");
586                 return ERROR_TARGET_NOT_HALTED;
587         }
588
589 /*
590  -- page-- start -- blocksize - mpu - totalFlash --
591         page0 0x00000   16k
592         page1 0x04000   16k
593         page2 0x08000   96k             ___ fxx3  128k Flash
594         page3 0x20000  128k             ___ fxx4  256k Flash
595         page4 0x40000  128k             ___ fxx5  384k Flash
596         page5 0x60000  128k             ___ fxx6  512k Flash
597 -----------------------
598         page6 0x80000  128k
599         page7 0xa0000  128k             ___ fxx7  256k Flash
600         page8 0xc0000  128k
601         page9 0xe0000  128k             ___ fxx8  256k Flash
602  */
603
604         num_pages = 10;                         /* max number of Flash pages for malloc */
605         fm3_info->probed = 0;
606
607         bank->sectors = malloc(sizeof(struct flash_sector) * num_pages);
608         bank->base = 0x00000000;
609         bank->size = 32 * 1024;         /* bytes */
610
611         bank->sectors[0].offset = 0;
612         bank->sectors[0].size = 16 * 1024;
613         bank->sectors[0].is_erased = -1;
614         bank->sectors[0].is_protected = -1;
615
616         bank->sectors[1].offset = 0x4000;
617         bank->sectors[1].size = 16 * 1024;
618         bank->sectors[1].is_erased = -1;
619         bank->sectors[1].is_protected = -1;
620
621         if ((fm3_info->variant == mb9bfxx1)
622             || (fm3_info->variant == mb9afxx1)) {
623                 num_pages = 3;
624                 bank->size = 64 * 1024; /* bytes */
625                 bank->num_sectors = num_pages;
626
627                 bank->sectors[2].offset = 0x8000;
628                 bank->sectors[2].size = 32 * 1024;
629                 bank->sectors[2].is_erased = -1;
630                 bank->sectors[2].is_protected = -1;
631         }
632
633         if ((fm3_info->variant == mb9bfxx2)
634                 || (fm3_info->variant == mb9bfxx4)
635                 || (fm3_info->variant == mb9bfxx5)
636                 || (fm3_info->variant == mb9bfxx6)
637                 || (fm3_info->variant == mb9bfxx7)
638                 || (fm3_info->variant == mb9bfxx8)
639                 || (fm3_info->variant == mb9afxx2)
640                 || (fm3_info->variant == mb9afxx4)
641                 || (fm3_info->variant == mb9afxx5)
642                 || (fm3_info->variant == mb9afxx6)
643                 || (fm3_info->variant == mb9afxx7)
644                 || (fm3_info->variant == mb9afxx8)) {
645                 num_pages = 3;
646                 bank->size = 128 * 1024; /* bytes */
647                 bank->num_sectors = num_pages;
648
649                 bank->sectors[2].offset = 0x8000;
650                 bank->sectors[2].size = 96 * 1024;
651                 bank->sectors[2].is_erased = -1;
652                 bank->sectors[2].is_protected = -1;
653         }
654
655         if ((fm3_info->variant == mb9bfxx4)
656                 || (fm3_info->variant == mb9bfxx5)
657                 || (fm3_info->variant == mb9bfxx6)
658                 || (fm3_info->variant == mb9bfxx7)
659                 || (fm3_info->variant == mb9bfxx8)
660                 || (fm3_info->variant == mb9afxx4)
661                 || (fm3_info->variant == mb9afxx5)
662                 || (fm3_info->variant == mb9afxx6)
663                 || (fm3_info->variant == mb9afxx7)
664                 || (fm3_info->variant == mb9afxx8)) {
665                 num_pages = 4;
666                 bank->size = 256 * 1024; /* bytes */
667                 bank->num_sectors = num_pages;
668
669                 bank->sectors[3].offset = 0x20000;
670                 bank->sectors[3].size = 128 * 1024;
671                 bank->sectors[3].is_erased = -1;
672                 bank->sectors[3].is_protected = -1;
673         }
674
675         if ((fm3_info->variant == mb9bfxx5)
676                 || (fm3_info->variant == mb9bfxx6)
677                 || (fm3_info->variant == mb9bfxx7)
678                 || (fm3_info->variant == mb9bfxx8)
679                 || (fm3_info->variant == mb9afxx5)
680                 || (fm3_info->variant == mb9afxx6)
681                 || (fm3_info->variant == mb9afxx7)
682                 || (fm3_info->variant == mb9afxx8)) {
683                 num_pages = 5;
684                 bank->size = 384 * 1024; /* bytes */
685                 bank->num_sectors = num_pages;
686
687                 bank->sectors[4].offset = 0x40000;
688                 bank->sectors[4].size = 128 * 1024;
689                 bank->sectors[4].is_erased = -1;
690                 bank->sectors[4].is_protected = -1;
691         }
692
693         if ((fm3_info->variant == mb9bfxx6)
694                 || (fm3_info->variant == mb9bfxx7)
695                 || (fm3_info->variant == mb9bfxx8)
696                 || (fm3_info->variant == mb9afxx6)
697                 || (fm3_info->variant == mb9afxx7)
698                 || (fm3_info->variant == mb9afxx8)) {
699                 num_pages = 6;
700                 bank->size = 512 * 1024; /* bytes */
701                 bank->num_sectors = num_pages;
702
703                 bank->sectors[5].offset = 0x60000;
704                 bank->sectors[5].size = 128 * 1024;
705                 bank->sectors[5].is_erased = -1;
706                 bank->sectors[5].is_protected = -1;
707         }
708
709         if ((fm3_info->variant == mb9bfxx7)
710                 || (fm3_info->variant == mb9bfxx8)
711                 || (fm3_info->variant == mb9afxx7)
712                 || (fm3_info->variant == mb9afxx8)) {
713                 num_pages = 8;
714                 bank->size = 768 * 1024; /* bytes */
715                 bank->num_sectors = num_pages;
716
717                 bank->sectors[6].offset = 0x80000;
718                 bank->sectors[6].size = 128 * 1024;
719                 bank->sectors[6].is_erased = -1;
720                 bank->sectors[6].is_protected = -1;
721
722                 bank->sectors[7].offset = 0xa0000;
723                 bank->sectors[7].size = 128 * 1024;
724                 bank->sectors[7].is_erased = -1;
725                 bank->sectors[7].is_protected = -1;
726         }
727
728         if ((fm3_info->variant == mb9bfxx8)
729                 || (fm3_info->variant == mb9afxx8)) {
730                 num_pages = 10;
731                 bank->size = 1024 * 1024; /* bytes */
732                 bank->num_sectors = num_pages;
733
734                 bank->sectors[8].offset = 0xc0000;
735                 bank->sectors[8].size = 128 * 1024;
736                 bank->sectors[8].is_erased = -1;
737                 bank->sectors[8].is_protected = -1;
738
739                 bank->sectors[9].offset = 0xe0000;
740                 bank->sectors[9].size = 128 * 1024;
741                 bank->sectors[9].is_erased = -1;
742                 bank->sectors[9].is_protected = -1;
743         }
744
745         fm3_info->probed = 1;
746
747         return ERROR_OK;
748 }
749
750 static int fm3_auto_probe(struct flash_bank *bank)
751 {
752         struct fm3_flash_bank *fm3_info = bank->driver_priv;
753         if (fm3_info->probed)
754                 return ERROR_OK;
755         return fm3_probe(bank);
756 }
757
758 /* Chip erase */
759 static int fm3_chip_erase(struct flash_bank *bank)
760 {
761         struct target *target = bank->target;
762         struct fm3_flash_bank *fm3_info2 = bank->driver_priv;
763         int retval = ERROR_OK;
764         uint32_t u32DummyRead;
765         uint32_t u32FlashType;
766         uint32_t u32FlashSeqAddress1;
767         uint32_t u32FlashSeqAddress2;
768
769         u32FlashType = (uint32_t) fm3_info2->flashtype;
770
771         if (u32FlashType == fm3_flash_type1) {
772                 LOG_INFO("*** Erasing mb9bfxxx type");
773                 u32FlashSeqAddress1 = 0x00001550;
774                 u32FlashSeqAddress2 = 0x00000AA8;
775         } else if (u32FlashType == fm3_flash_type2) {
776                 LOG_INFO("*** Erasing mb9afxxx type");
777                 u32FlashSeqAddress1 = 0x00000AA8;
778                 u32FlashSeqAddress2 = 0x00000554;
779         } else {
780                 LOG_ERROR("Flash/Device type unknown!");
781                 return ERROR_FLASH_OPERATION_FAILED;
782         }
783
784         if (target->state != TARGET_HALTED) {
785                 LOG_ERROR("Target not halted");
786                 return ERROR_TARGET_NOT_HALTED;
787         }
788
789         LOG_INFO("Fujitsu MB9[A/B]xxx: Chip Erase ... (may take several seconds)");
790
791         /* FASZR = 0x01, Enables CPU Programming Mode (16-bit Flash access) */
792         retval = target_write_u32(target, 0x40000000, 0x0001);
793         if (retval != ERROR_OK)
794                 return retval;
795
796         /* dummy read of FASZR */
797         retval = target_read_u32(target, 0x40000000, &u32DummyRead);
798         if (retval != ERROR_OK)
799                 return retval;
800
801         /* Flash unlock sequence */
802         retval = target_write_u16(target, u32FlashSeqAddress1, 0x00AA);
803         if (retval != ERROR_OK)
804                 return retval;
805
806         retval = target_write_u16(target, u32FlashSeqAddress2, 0x0055);
807         if (retval != ERROR_OK)
808                 return retval;
809
810         retval = target_write_u16(target, u32FlashSeqAddress1, 0x0080);
811         if (retval != ERROR_OK)
812                 return retval;
813
814         retval = target_write_u16(target, u32FlashSeqAddress1, 0x00AA);
815         if (retval != ERROR_OK)
816                 return retval;
817
818         retval = target_write_u16(target, u32FlashSeqAddress2, 0x0055);
819         if (retval != ERROR_OK)
820                 return retval;
821
822         /* Chip Erase command (0x0010) */
823         retval = target_write_u16(target, u32FlashSeqAddress1, 0x0010);
824         if (retval != ERROR_OK)
825                 return retval;
826
827         retval = fm3_busy_wait(target, u32FlashSeqAddress2, 20000);     /* 20s timeout */
828         if (retval != ERROR_OK)
829                 return retval;
830
831         /* FASZR = 0x02, Re-enables CPU Run Mode (32-bit Flash access) */
832         retval = target_write_u32(target, 0x40000000, 0x0002);
833         if (retval != ERROR_OK)
834                 return retval;
835
836         retval = target_read_u32(target, 0x40000000, &u32DummyRead); /* dummy read of FASZR */
837
838         return retval;
839 }
840
841 COMMAND_HANDLER(fm3_handle_chip_erase_command)
842 {
843         int i;
844
845         if (CMD_ARGC < 1)
846                 return ERROR_COMMAND_SYNTAX_ERROR;
847
848         struct flash_bank *bank;
849         int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
850         if (ERROR_OK != retval)
851                 return retval;
852
853         if (fm3_chip_erase(bank) == ERROR_OK) {
854                 /* set all sectors as erased */
855                 for (i = 0; i < bank->num_sectors; i++)
856                         bank->sectors[i].is_erased = 1;
857
858                 command_print(CMD_CTX, "fm3 chip erase complete");
859         } else {
860                 command_print(CMD_CTX, "fm3 chip erase failed");
861         }
862
863         return ERROR_OK;
864 }
865
866 static const struct command_registration fm3_exec_command_handlers[] = {
867         {
868                 .name = "chip_erase",
869                 .usage = "<bank>",
870                 .handler = fm3_handle_chip_erase_command,
871                 .mode = COMMAND_EXEC,
872                 .help = "Erase entire Flash device.",
873         },
874         COMMAND_REGISTRATION_DONE
875 };
876
877 static const struct command_registration fm3_command_handlers[] = {
878         {
879                 .name = "fm3",
880                 .mode = COMMAND_ANY,
881                 .help = "fm3 Flash command group",
882                 .usage = "",
883                 .chain = fm3_exec_command_handlers,
884         },
885         COMMAND_REGISTRATION_DONE
886 };
887
888 struct flash_driver fm3_flash = {
889         .name = "fm3",
890         .commands = fm3_command_handlers,
891         .flash_bank_command = fm3_flash_bank_command,
892         .erase = fm3_erase,
893         .write = fm3_write_block,
894         .probe = fm3_probe,
895         .auto_probe = fm3_auto_probe,
896         .erase_check = default_flash_blank_check,
897 };