]> git.sur5r.net Git - openocd/blob - src/flash/nor/mdr.c
ed76aab097cb78b0ee45bbfbefd187188eb71b1b
[openocd] / src / flash / nor / mdr.c
1 /***************************************************************************
2  *   Copyright (C) 2005 by Dominic Rath                                    *
3  *   Dominic.Rath@gmx.de                                                   *
4  *                                                                         *
5  *   Copyright (C) 2008 by Spencer Oliver                                  *
6  *   spen@spen-soft.co.uk                                                  *
7  *                                                                         *
8  *   Copyright (C) 2011 by Andreas Fritiofson                              *
9  *   andreas.fritiofson@gmail.com                                          *
10  *                                                                         *
11  *   Copyright (C) 2013 by Paul Fertser                                    *
12  *   fercerpav@gmail.com                                                   *
13  *                                                                         *
14  *   This program is free software; you can redistribute it and/or modify  *
15  *   it under the terms of the GNU General Public License as published by  *
16  *   the Free Software Foundation; either version 2 of the License, or     *
17  *   (at your option) any later version.                                   *
18  *                                                                         *
19  *   This program is distributed in the hope that it will be useful,       *
20  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
21  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
22  *   GNU General Public License for more details.                          *
23  *                                                                         *
24  *   You should have received a copy of the GNU General Public License     *
25  *   along with this program; if not, write to the                         *
26  *   Free Software Foundation, Inc.,                                       *
27  *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.           *
28  ***************************************************************************/
29
30 #ifdef HAVE_CONFIG_H
31 #include "config.h"
32 #endif
33
34 #include "imp.h"
35 #include <helper/binarybuffer.h>
36 #include <target/algorithm.h>
37 #include <target/armv7m.h>
38
39 #define MD_RST_CLK              0x40020000
40 #define MD_PER_CLOCK            (MD_RST_CLK + 0x1C)
41 #define MD_PER_CLOCK_EEPROM     (1 << 3)
42 #define MD_PER_CLOCK_RST_CLK    (1 << 4)
43
44 #define FLASH_REG_BASE  0x40018000
45 #define FLASH_CMD       (FLASH_REG_BASE + 0x00)
46 #define FLASH_ADR       (FLASH_REG_BASE + 0x04)
47 #define FLASH_DI        (FLASH_REG_BASE + 0x08)
48 #define FLASH_DO        (FLASH_REG_BASE + 0x0C)
49 #define FLASH_KEY       (FLASH_REG_BASE + 0x10)
50
51 #define FLASH_NVSTR     (1 << 13)
52 #define FLASH_PROG      (1 << 12)
53 #define FLASH_MAS1      (1 << 11)
54 #define FLASH_ERASE     (1 << 10)
55 #define FLASH_IFREN     (1 << 9)
56 #define FLASH_SE        (1 << 8)
57 #define FLASH_YE        (1 << 7)
58 #define FLASH_XE        (1 << 6)
59 #define FLASH_RD        (1 << 2)
60 #define FLASH_WR        (1 << 1)
61 #define FLASH_CON       (1 << 0)
62 #define FLASH_DELAY_MASK        (7 << 3)
63
64 #define KEY             0x8AAA5551
65
66 struct mdr_flash_bank {
67         int probed;
68         unsigned int mem_type;
69         unsigned int page_count;
70         unsigned int sec_count;
71 };
72
73 /* flash bank <name> mdr <base> <size> 0 0 <target#> <type> <page_count> <sec_count> */
74 FLASH_BANK_COMMAND_HANDLER(mdr_flash_bank_command)
75 {
76         struct mdr_flash_bank *mdr_info;
77
78         if (CMD_ARGC < 9)
79                 return ERROR_COMMAND_SYNTAX_ERROR;
80
81         mdr_info = malloc(sizeof(struct mdr_flash_bank));
82
83         bank->driver_priv = mdr_info;
84         mdr_info->probed = 0;
85         COMMAND_PARSE_NUMBER(uint, CMD_ARGV[6], mdr_info->mem_type);
86         COMMAND_PARSE_NUMBER(uint, CMD_ARGV[7], mdr_info->page_count);
87         COMMAND_PARSE_NUMBER(uint, CMD_ARGV[8], mdr_info->sec_count);
88         return ERROR_OK;
89 }
90
91 static int mdr_protect_check(struct flash_bank *bank)
92 {
93         return ERROR_OK;
94 }
95
96 static int mdr_mass_erase(struct flash_bank *bank)
97 {
98         struct target *target = bank->target;
99         struct mdr_flash_bank *mdr_info = bank->driver_priv;
100         uint32_t flash_cmd;
101         int retval;
102         unsigned int i;
103
104         retval = target_read_u32(target, FLASH_CMD, &flash_cmd);
105         if (retval != ERROR_OK)
106                 return retval;
107
108         for (i = 0; i < mdr_info->sec_count; i++) {
109                 retval = target_write_u32(target, FLASH_ADR, i << 2);
110                 if (retval != ERROR_OK)
111                         return retval;
112
113                 flash_cmd |= FLASH_XE | FLASH_MAS1 | FLASH_ERASE;
114                 retval = target_write_u32(target, FLASH_CMD, flash_cmd);
115                 if (retval != ERROR_OK)
116                         return retval;
117                 flash_cmd |= FLASH_NVSTR;
118                 retval = target_write_u32(target, FLASH_CMD, flash_cmd);
119                 if (retval != ERROR_OK)
120                         return retval;
121                 flash_cmd &= ~FLASH_ERASE;
122                 retval = target_write_u32(target, FLASH_CMD, flash_cmd);
123                 if (retval != ERROR_OK)
124                         return retval;
125                 flash_cmd &= ~(FLASH_XE | FLASH_MAS1 | FLASH_NVSTR);
126                 retval = target_write_u32(target, FLASH_CMD, flash_cmd);
127                 if (retval != ERROR_OK)
128                         return retval;
129         }
130
131         return retval;
132 }
133
134 static int mdr_erase(struct flash_bank *bank, int first, int last)
135 {
136         struct target *target = bank->target;
137         struct mdr_flash_bank *mdr_info = bank->driver_priv;
138         int i, retval, retval2;
139         unsigned int j;
140         uint32_t flash_cmd, cur_per_clock;
141
142         if (bank->target->state != TARGET_HALTED) {
143                 LOG_ERROR("Target not halted");
144                 return ERROR_TARGET_NOT_HALTED;
145         }
146
147         retval = target_read_u32(target, MD_PER_CLOCK, &cur_per_clock);
148         if (retval != ERROR_OK)
149                 return retval;
150
151         if (!(cur_per_clock & 0x10)) {
152                 LOG_ERROR("Target needs reset before flash operations");
153                 return ERROR_FLASH_OPERATION_FAILED;
154         }
155
156         retval = target_write_u32(target, MD_PER_CLOCK, cur_per_clock | MD_PER_CLOCK_EEPROM);
157         if (retval != ERROR_OK)
158                 return retval;
159
160         retval = target_write_u32(target, FLASH_KEY, KEY);
161         if (retval != ERROR_OK)
162                 return retval;
163
164         retval = target_read_u32(target, FLASH_CMD, &flash_cmd);
165         if (retval != ERROR_OK)
166                 goto reset_pg_and_lock;
167
168         /* Switch on register access */
169         flash_cmd = (flash_cmd & FLASH_DELAY_MASK) | FLASH_CON;
170         if (mdr_info->mem_type)
171                 flash_cmd |= FLASH_IFREN;
172         retval = target_write_u32(target, FLASH_CMD, flash_cmd);
173         if (retval != ERROR_OK)
174                 goto reset_pg_and_lock;
175
176         if ((first == 0) && (last == (bank->num_sectors - 1))) {
177                 retval = mdr_mass_erase(bank);
178                 goto reset_pg_and_lock;
179         }
180
181         unsigned int page_size = bank->size / mdr_info->page_count;
182         for (i = first; i <= last; i++) {
183                 for (j = 0; j < mdr_info->sec_count; j++) {
184                         retval = target_write_u32(target, FLASH_ADR, (i * page_size) | (j << 2));
185                         if (retval != ERROR_OK)
186                                 goto reset_pg_and_lock;
187
188                         flash_cmd |= FLASH_XE | FLASH_ERASE;
189                         retval = target_write_u32(target, FLASH_CMD, flash_cmd);
190                         if (retval != ERROR_OK)
191                                 goto reset_pg_and_lock;
192                         flash_cmd |= FLASH_NVSTR;
193                         retval = target_write_u32(target, FLASH_CMD, flash_cmd);
194                         if (retval != ERROR_OK)
195                                 goto reset_pg_and_lock;
196                         flash_cmd &= ~FLASH_ERASE;
197                         retval = target_write_u32(target, FLASH_CMD, flash_cmd);
198                         if (retval != ERROR_OK)
199                                 goto reset_pg_and_lock;
200                         flash_cmd &= ~(FLASH_XE | FLASH_NVSTR);
201                         retval = target_write_u32(target, FLASH_CMD, flash_cmd);
202                         if (retval != ERROR_OK)
203                                 goto reset_pg_and_lock;
204                 }
205                 bank->sectors[i].is_erased = 1;
206         }
207
208 reset_pg_and_lock:
209         flash_cmd &= FLASH_DELAY_MASK;
210         retval2 = target_write_u32(target, FLASH_CMD, flash_cmd);
211         if (retval == ERROR_OK)
212                 retval = retval2;
213
214         retval2 = target_write_u32(target, FLASH_KEY, 0);
215         if (retval == ERROR_OK)
216                 retval = retval2;
217
218         return retval;
219 }
220
221 static int mdr_protect(struct flash_bank *bank, int set, int first, int last)
222 {
223         return ERROR_OK;
224 }
225
226 static int mdr_write_block(struct flash_bank *bank, const uint8_t *buffer,
227                 uint32_t offset, uint32_t count)
228 {
229         struct target *target = bank->target;
230         uint32_t buffer_size = 16384;
231         struct working_area *write_algorithm;
232         struct working_area *source;
233         uint32_t address = bank->base + offset;
234         struct reg_param reg_params[5];
235         struct armv7m_algorithm armv7m_info;
236         int retval = ERROR_OK;
237
238         /* see contrib/loaders/flash/mdr32fx.S for src */
239         static const uint8_t mdr32fx_flash_write_code[] = {
240                 0x07, 0x68, 0x16, 0x68, 0x00, 0x2e, 0x2e, 0xd0, 0x55, 0x68, 0xb5, 0x42,
241                 0xf9, 0xd0, 0x2e, 0x68, 0x44, 0x60, 0x86, 0x60, 0x17, 0x4e, 0x37, 0x43,
242                 0x07, 0x60, 0x05, 0x26, 0x00, 0xf0, 0x25, 0xf8, 0x15, 0x4e, 0x37, 0x43,
243                 0x07, 0x60, 0x0d, 0x26, 0x00, 0xf0, 0x1f, 0xf8, 0x80, 0x26, 0x37, 0x43,
244                 0x07, 0x60, 0x3d, 0x26, 0x00, 0xf0, 0x19, 0xf8, 0x80, 0x26, 0xb7, 0x43,
245                 0x07, 0x60, 0x0f, 0x4e, 0xb7, 0x43, 0x07, 0x60, 0x05, 0x26, 0x00, 0xf0,
246                 0x10, 0xf8, 0x0d, 0x4e, 0xb7, 0x43, 0x07, 0x60, 0x04, 0x35, 0x04, 0x34,
247                 0x9d, 0x42, 0x01, 0xd3, 0x15, 0x46, 0x08, 0x35, 0x55, 0x60, 0x01, 0x39,
248                 0x00, 0x29, 0x00, 0xd0, 0xcd, 0xe7, 0x30, 0x46, 0x00, 0xbe, 0x01, 0x3e,
249                 0x00, 0x2e, 0xfc, 0xd1, 0x70, 0x47, 0x00, 0x00, 0x40, 0x10, 0x00, 0x00,
250                 0x00, 0x20, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x40, 0x20, 0x00, 0x00
251         };
252
253         /* flash write code */
254         if (target_alloc_working_area(target, sizeof(mdr32fx_flash_write_code),
255                         &write_algorithm) != ERROR_OK) {
256                 LOG_WARNING("no working area available, can't do block memory writes");
257                 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
258         };
259
260         retval = target_write_buffer(target, write_algorithm->address,
261                         sizeof(mdr32fx_flash_write_code), mdr32fx_flash_write_code);
262         if (retval != ERROR_OK)
263                 return retval;
264
265         /* memory buffer */
266         while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) {
267                 buffer_size /= 2;
268                 buffer_size &= ~3UL; /* Make sure it's 4 byte aligned */
269                 if (buffer_size <= 256) {
270                         /* we already allocated the writing code, but failed to get a
271                          * buffer, free the algorithm */
272                         target_free_working_area(target, write_algorithm);
273
274                         LOG_WARNING("no large enough working area available, can't do block memory writes");
275                         return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
276                 }
277         };
278
279         init_reg_param(&reg_params[0], "r0", 32, PARAM_IN_OUT); /* flash base (in), status (out) */
280         init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);    /* count (32bit) */
281         init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT);    /* buffer start */
282         init_reg_param(&reg_params[3], "r3", 32, PARAM_OUT);    /* buffer end */
283         init_reg_param(&reg_params[4], "r4", 32, PARAM_IN_OUT); /* target address */
284
285         buf_set_u32(reg_params[0].value, 0, 32, FLASH_REG_BASE);
286         buf_set_u32(reg_params[1].value, 0, 32, count);
287         buf_set_u32(reg_params[2].value, 0, 32, source->address);
288         buf_set_u32(reg_params[3].value, 0, 32, source->address + source->size);
289         buf_set_u32(reg_params[4].value, 0, 32, address);
290
291         armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
292         armv7m_info.core_mode = ARM_MODE_THREAD;
293
294         retval = target_run_flash_async_algorithm(target, buffer, count, 4,
295                         0, NULL,
296                         5, reg_params,
297                         source->address, source->size,
298                         write_algorithm->address, 0,
299                         &armv7m_info);
300
301         if (retval == ERROR_FLASH_OPERATION_FAILED)
302                 LOG_ERROR("flash write failed at address 0x%"PRIx32,
303                                 buf_get_u32(reg_params[4].value, 0, 32));
304
305         target_free_working_area(target, source);
306         target_free_working_area(target, write_algorithm);
307
308         destroy_reg_param(&reg_params[0]);
309         destroy_reg_param(&reg_params[1]);
310         destroy_reg_param(&reg_params[2]);
311         destroy_reg_param(&reg_params[3]);
312         destroy_reg_param(&reg_params[4]);
313
314         return retval;
315 }
316
317 static int mdr_write(struct flash_bank *bank, const uint8_t *buffer,
318                 uint32_t offset, uint32_t count)
319 {
320         struct target *target = bank->target;
321         struct mdr_flash_bank *mdr_info = bank->driver_priv;
322         uint8_t *new_buffer = NULL;
323
324         if (bank->target->state != TARGET_HALTED) {
325                 LOG_ERROR("Target not halted");
326                 return ERROR_TARGET_NOT_HALTED;
327         }
328
329         if (offset & 0x3) {
330                 LOG_ERROR("offset 0x%" PRIx32 " breaks required 4-byte alignment", offset);
331                 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
332         }
333
334         /* If there's an odd number of bytes, the data has to be padded. Duplicate
335          * the buffer and use the normal code path with a single block write since
336          * it's probably cheaper than to special case the last odd write using
337          * discrete accesses. */
338         int rem = count % 4;
339         if (rem) {
340                 new_buffer = malloc(count + rem);
341                 if (new_buffer == NULL) {
342                         LOG_ERROR("odd number of bytes to write and no memory for padding buffer");
343                         return ERROR_FAIL;
344                 }
345                 LOG_INFO("odd number of bytes to write, padding with 0xff");
346                 buffer = memcpy(new_buffer, buffer, count);
347                 while (rem--)
348                         new_buffer[count++] = 0xff;
349         }
350
351         uint32_t flash_cmd, cur_per_clock;
352         int retval, retval2;
353
354         retval = target_read_u32(target, MD_PER_CLOCK, &cur_per_clock);
355         if (retval != ERROR_OK)
356                 goto free_buffer;
357
358         if (!(cur_per_clock & MD_PER_CLOCK_RST_CLK)) {
359                 /* Something's very wrong if the RST_CLK module is not clocked */
360                 LOG_ERROR("Target needs reset before flash operations");
361                 retval = ERROR_FLASH_OPERATION_FAILED;
362                 goto free_buffer;
363         }
364
365         retval = target_write_u32(target, MD_PER_CLOCK, cur_per_clock | MD_PER_CLOCK_EEPROM);
366         if (retval != ERROR_OK)
367                 goto free_buffer;
368
369         retval = target_write_u32(target, FLASH_KEY, KEY);
370         if (retval != ERROR_OK)
371                 goto free_buffer;
372
373         retval = target_read_u32(target, FLASH_CMD, &flash_cmd);
374         if (retval != ERROR_OK)
375                 goto reset_pg_and_lock;
376
377         /* Switch on register access */
378         flash_cmd = (flash_cmd & FLASH_DELAY_MASK) | FLASH_CON;
379         if (mdr_info->mem_type)
380                 flash_cmd |= FLASH_IFREN;
381         retval = target_write_u32(target, FLASH_CMD, flash_cmd);
382         if (retval != ERROR_OK)
383                 goto reset_pg_and_lock;
384
385         /* try using block write */
386         retval = mdr_write_block(bank, buffer, offset, count/4);
387
388         if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) {
389                 /* if block write failed (no sufficient working area),
390                  * we use normal (slow) single halfword accesses */
391                 LOG_WARNING("Can't use block writes, falling back to single memory accesses");
392
393                 unsigned int page_size = bank->size / mdr_info->page_count;
394                 unsigned int page_mask = page_size - 1;
395                 while (count > 0) {
396                         unsigned int i, j;
397                         unsigned int cur_page = offset & ~page_mask;
398                         unsigned int bytes_to_write = cur_page + page_size - offset;
399                         if (count < bytes_to_write)
400                                 bytes_to_write = count;
401
402                         /*LOG_INFO("Selecting next page: %08x", cur_page);*/
403
404                         for (i = 0; i < mdr_info->sec_count; i++) {
405                                 retval = target_write_u32(target, FLASH_ADR, offset + i*4);
406                                 if (retval != ERROR_OK)
407                                         goto reset_pg_and_lock;
408                                 /*LOG_INFO("Selecting page/sector: %08x", offset + i*4);*/
409
410                                 flash_cmd |= FLASH_XE | FLASH_PROG;
411                                 retval = target_write_u32(target, FLASH_CMD, flash_cmd);
412                                 if (retval != ERROR_OK)
413                                         goto reset_pg_and_lock;
414
415                                 flash_cmd |= FLASH_NVSTR;
416                                 retval = target_write_u32(target, FLASH_CMD, flash_cmd);
417                                 if (retval != ERROR_OK)
418                                         goto reset_pg_and_lock;
419
420                                 for (j = 0;
421                                      (((offset + j + i*4) & ~page_mask) == cur_page) &&
422                                              (j + i*4 < count);
423                                      j += mdr_info->sec_count*4) {
424                                         uint32_t value;
425                                         memcpy(&value, buffer + j + i*4, sizeof(uint32_t));
426                                         retval = target_write_u32(target, FLASH_DI, value);
427                                         if (retval != ERROR_OK)
428                                                 goto reset_pg_and_lock;
429                                         /*LOG_INFO("Writing to addr %08x", offset + j + i*4);*/
430                                         retval = target_write_u32(target, FLASH_ADR, offset + j + i*4);
431                                         if (retval != ERROR_OK)
432                                                 goto reset_pg_and_lock;
433
434                                         flash_cmd |= FLASH_YE;
435                                         retval = target_write_u32(target, FLASH_CMD, flash_cmd);
436                                         if (retval != ERROR_OK)
437                                                 goto reset_pg_and_lock;
438                                         flash_cmd &= ~FLASH_YE;
439                                         retval = target_write_u32(target, FLASH_CMD, flash_cmd);
440                                         if (retval != ERROR_OK)
441                                                 goto reset_pg_and_lock;
442                                 }
443                                 flash_cmd &= ~FLASH_NVSTR;
444                                 retval = target_write_u32(target, FLASH_CMD, flash_cmd);
445                                 if (retval != ERROR_OK)
446                                         goto reset_pg_and_lock;
447
448                                 flash_cmd &= ~(FLASH_XE | FLASH_PROG);
449                                 retval = target_write_u32(target, FLASH_CMD, flash_cmd);
450                                 if (retval != ERROR_OK)
451                                         goto reset_pg_and_lock;
452                         }
453
454                         buffer += bytes_to_write;
455                         offset += bytes_to_write;
456                         count -= bytes_to_write;
457                 }
458         }
459
460 reset_pg_and_lock:
461         flash_cmd &= FLASH_DELAY_MASK;
462         retval2 = target_write_u32(target, FLASH_CMD, flash_cmd);
463         if (retval == ERROR_OK)
464                 retval = retval2;
465
466         retval2 = target_write_u32(target, FLASH_KEY, 0);
467         if (retval == ERROR_OK)
468                 retval = retval2;
469
470 free_buffer:
471         if (new_buffer)
472                 free(new_buffer);
473
474         return retval;
475 }
476
477 static int mdr_probe(struct flash_bank *bank)
478 {
479         struct mdr_flash_bank *mdr_info = bank->driver_priv;
480         unsigned int page_count, page_size, i;
481
482         page_count = mdr_info->page_count;
483         page_size = bank->size / page_count;
484
485         bank->num_sectors = page_count;
486         bank->sectors = malloc(sizeof(struct flash_sector) * page_count);
487
488         for (i = 0; i < page_count; i++) {
489                 bank->sectors[i].offset = i * page_size;
490                 bank->sectors[i].size = page_size;
491                 bank->sectors[i].is_erased = -1;
492                 bank->sectors[i].is_protected = 0;
493         }
494
495         mdr_info->probed = 1;
496
497         return ERROR_OK;
498 }
499
500 static int mdr_auto_probe(struct flash_bank *bank)
501 {
502         struct mdr_flash_bank *mdr_info = bank->driver_priv;
503         if (mdr_info->probed)
504                 return ERROR_OK;
505         return mdr_probe(bank);
506 }
507
508 static int get_mdr_info(struct flash_bank *bank, char *buf, int buf_size)
509 {
510         struct mdr_flash_bank *mdr_info = bank->driver_priv;
511         snprintf(buf, buf_size, "MDR32Fx - %s",
512                  mdr_info->mem_type ? "info memory" : "main memory");
513
514         return ERROR_OK;
515 }
516
517 struct flash_driver mdr_flash = {
518         .name = "mdr",
519         .flash_bank_command = mdr_flash_bank_command,
520         .erase = mdr_erase,
521         .protect = mdr_protect,
522         .write = mdr_write,
523         .read = default_flash_read,
524         .probe = mdr_probe,
525         .auto_probe = mdr_auto_probe,
526         .erase_check = default_flash_blank_check,
527         .protect_check = mdr_protect_check,
528         .info = get_mdr_info,
529 };