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