flash/nor: consolidate flash protect/protect_check
[fw/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, see <http://www.gnu.org/licenses/>. *
26  ***************************************************************************/
27
28 #ifdef HAVE_CONFIG_H
29 #include "config.h"
30 #endif
31
32 #include "imp.h"
33 #include <helper/binarybuffer.h>
34 #include <target/algorithm.h>
35 #include <target/armv7m.h>
36
37 #define MD_RST_CLK              0x40020000
38 #define MD_PER_CLOCK            (MD_RST_CLK + 0x1C)
39 #define MD_PER_CLOCK_EEPROM     (1 << 3)
40 #define MD_PER_CLOCK_RST_CLK    (1 << 4)
41
42 #define FLASH_REG_BASE  0x40018000
43 #define FLASH_CMD       (FLASH_REG_BASE + 0x00)
44 #define FLASH_ADR       (FLASH_REG_BASE + 0x04)
45 #define FLASH_DI        (FLASH_REG_BASE + 0x08)
46 #define FLASH_DO        (FLASH_REG_BASE + 0x0C)
47 #define FLASH_KEY       (FLASH_REG_BASE + 0x10)
48
49 #define FLASH_NVSTR     (1 << 13)
50 #define FLASH_PROG      (1 << 12)
51 #define FLASH_MAS1      (1 << 11)
52 #define FLASH_ERASE     (1 << 10)
53 #define FLASH_IFREN     (1 << 9)
54 #define FLASH_SE        (1 << 8)
55 #define FLASH_YE        (1 << 7)
56 #define FLASH_XE        (1 << 6)
57 #define FLASH_RD        (1 << 2)
58 #define FLASH_WR        (1 << 1)
59 #define FLASH_CON       (1 << 0)
60 #define FLASH_DELAY_MASK        (7 << 3)
61
62 #define KEY             0x8AAA5551
63
64 struct mdr_flash_bank {
65         int probed;
66         unsigned int mem_type;
67         unsigned int page_count;
68         unsigned int sec_count;
69 };
70
71 /* flash bank <name> mdr <base> <size> 0 0 <target#> <type> <page_count> <sec_count> */
72 FLASH_BANK_COMMAND_HANDLER(mdr_flash_bank_command)
73 {
74         struct mdr_flash_bank *mdr_info;
75
76         if (CMD_ARGC < 9)
77                 return ERROR_COMMAND_SYNTAX_ERROR;
78
79         mdr_info = malloc(sizeof(struct mdr_flash_bank));
80
81         bank->driver_priv = mdr_info;
82         mdr_info->probed = 0;
83         COMMAND_PARSE_NUMBER(uint, CMD_ARGV[6], mdr_info->mem_type);
84         COMMAND_PARSE_NUMBER(uint, CMD_ARGV[7], mdr_info->page_count);
85         COMMAND_PARSE_NUMBER(uint, CMD_ARGV[8], mdr_info->sec_count);
86         return ERROR_OK;
87 }
88
89 static int mdr_mass_erase(struct flash_bank *bank)
90 {
91         struct target *target = bank->target;
92         struct mdr_flash_bank *mdr_info = bank->driver_priv;
93         uint32_t flash_cmd;
94         int retval;
95         unsigned int i;
96
97         retval = target_read_u32(target, FLASH_CMD, &flash_cmd);
98         if (retval != ERROR_OK)
99                 return retval;
100
101         for (i = 0; i < mdr_info->sec_count; i++) {
102                 retval = target_write_u32(target, FLASH_ADR, i << 2);
103                 if (retval != ERROR_OK)
104                         return retval;
105
106                 flash_cmd |= FLASH_XE | FLASH_MAS1 | FLASH_ERASE;
107                 retval = target_write_u32(target, FLASH_CMD, flash_cmd);
108                 if (retval != ERROR_OK)
109                         return retval;
110                 flash_cmd |= FLASH_NVSTR;
111                 retval = target_write_u32(target, FLASH_CMD, flash_cmd);
112                 if (retval != ERROR_OK)
113                         return retval;
114                 flash_cmd &= ~FLASH_ERASE;
115                 retval = target_write_u32(target, FLASH_CMD, flash_cmd);
116                 if (retval != ERROR_OK)
117                         return retval;
118                 flash_cmd &= ~(FLASH_XE | FLASH_MAS1 | FLASH_NVSTR);
119                 retval = target_write_u32(target, FLASH_CMD, flash_cmd);
120                 if (retval != ERROR_OK)
121                         return retval;
122         }
123
124         return retval;
125 }
126
127 static int mdr_erase(struct flash_bank *bank, int first, int last)
128 {
129         struct target *target = bank->target;
130         struct mdr_flash_bank *mdr_info = bank->driver_priv;
131         int i, retval, retval2;
132         unsigned int j;
133         uint32_t flash_cmd, cur_per_clock;
134
135         if (bank->target->state != TARGET_HALTED) {
136                 LOG_ERROR("Target not halted");
137                 return ERROR_TARGET_NOT_HALTED;
138         }
139
140         retval = target_read_u32(target, MD_PER_CLOCK, &cur_per_clock);
141         if (retval != ERROR_OK)
142                 return retval;
143
144         if (!(cur_per_clock & 0x10)) {
145                 LOG_ERROR("Target needs reset before flash operations");
146                 return ERROR_FLASH_OPERATION_FAILED;
147         }
148
149         retval = target_write_u32(target, MD_PER_CLOCK, cur_per_clock | MD_PER_CLOCK_EEPROM);
150         if (retval != ERROR_OK)
151                 return retval;
152
153         retval = target_write_u32(target, FLASH_KEY, KEY);
154         if (retval != ERROR_OK)
155                 return retval;
156
157         retval = target_read_u32(target, FLASH_CMD, &flash_cmd);
158         if (retval != ERROR_OK)
159                 goto reset_pg_and_lock;
160
161         /* Switch on register access */
162         flash_cmd = (flash_cmd & FLASH_DELAY_MASK) | FLASH_CON;
163         if (mdr_info->mem_type)
164                 flash_cmd |= FLASH_IFREN;
165         retval = target_write_u32(target, FLASH_CMD, flash_cmd);
166         if (retval != ERROR_OK)
167                 goto reset_pg_and_lock;
168
169         if ((first == 0) && (last == (bank->num_sectors - 1)) &&
170                 !mdr_info->mem_type) {
171                 retval = mdr_mass_erase(bank);
172                 goto reset_pg_and_lock;
173         }
174
175         unsigned int page_size = bank->size / mdr_info->page_count;
176         for (i = first; i <= last; i++) {
177                 for (j = 0; j < mdr_info->sec_count; j++) {
178                         retval = target_write_u32(target, FLASH_ADR, (i * page_size) | (j << 2));
179                         if (retval != ERROR_OK)
180                                 goto reset_pg_and_lock;
181
182                         flash_cmd |= FLASH_XE | FLASH_ERASE;
183                         retval = target_write_u32(target, FLASH_CMD, flash_cmd);
184                         if (retval != ERROR_OK)
185                                 goto reset_pg_and_lock;
186                         flash_cmd |= FLASH_NVSTR;
187                         retval = target_write_u32(target, FLASH_CMD, flash_cmd);
188                         if (retval != ERROR_OK)
189                                 goto reset_pg_and_lock;
190                         flash_cmd &= ~FLASH_ERASE;
191                         retval = target_write_u32(target, FLASH_CMD, flash_cmd);
192                         if (retval != ERROR_OK)
193                                 goto reset_pg_and_lock;
194                         flash_cmd &= ~(FLASH_XE | FLASH_NVSTR);
195                         retval = target_write_u32(target, FLASH_CMD, flash_cmd);
196                         if (retval != ERROR_OK)
197                                 goto reset_pg_and_lock;
198                 }
199                 bank->sectors[i].is_erased = 1;
200         }
201
202 reset_pg_and_lock:
203         flash_cmd &= FLASH_DELAY_MASK;
204         retval2 = target_write_u32(target, FLASH_CMD, flash_cmd);
205         if (retval == ERROR_OK)
206                 retval = retval2;
207
208         retval2 = target_write_u32(target, FLASH_KEY, 0);
209         if (retval == ERROR_OK)
210                 retval = retval2;
211
212         return retval;
213 }
214
215 static int mdr_write_block(struct flash_bank *bank, const uint8_t *buffer,
216                 uint32_t offset, uint32_t count)
217 {
218         struct target *target = bank->target;
219         uint32_t buffer_size = 16384;
220         struct working_area *write_algorithm;
221         struct working_area *source;
222         uint32_t address = bank->base + offset;
223         struct reg_param reg_params[5];
224         struct armv7m_algorithm armv7m_info;
225         int retval = ERROR_OK;
226
227         /* see contrib/loaders/flash/mdr32fx.S for src */
228         static const uint8_t mdr32fx_flash_write_code[] = {
229                 0x07, 0x68, 0x16, 0x68, 0x00, 0x2e, 0x2e, 0xd0, 0x55, 0x68, 0xb5, 0x42,
230                 0xf9, 0xd0, 0x2e, 0x68, 0x44, 0x60, 0x86, 0x60, 0x17, 0x4e, 0x37, 0x43,
231                 0x07, 0x60, 0x05, 0x26, 0x00, 0xf0, 0x25, 0xf8, 0x15, 0x4e, 0x37, 0x43,
232                 0x07, 0x60, 0x0d, 0x26, 0x00, 0xf0, 0x1f, 0xf8, 0x80, 0x26, 0x37, 0x43,
233                 0x07, 0x60, 0x3d, 0x26, 0x00, 0xf0, 0x19, 0xf8, 0x80, 0x26, 0xb7, 0x43,
234                 0x07, 0x60, 0x0f, 0x4e, 0xb7, 0x43, 0x07, 0x60, 0x05, 0x26, 0x00, 0xf0,
235                 0x10, 0xf8, 0x0d, 0x4e, 0xb7, 0x43, 0x07, 0x60, 0x04, 0x35, 0x04, 0x34,
236                 0x9d, 0x42, 0x01, 0xd3, 0x15, 0x46, 0x08, 0x35, 0x55, 0x60, 0x01, 0x39,
237                 0x00, 0x29, 0x00, 0xd0, 0xcd, 0xe7, 0x30, 0x46, 0x00, 0xbe, 0x01, 0x3e,
238                 0x00, 0x2e, 0xfc, 0xd1, 0x70, 0x47, 0x00, 0x00, 0x40, 0x10, 0x00, 0x00,
239                 0x00, 0x20, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x40, 0x20, 0x00, 0x00
240         };
241
242         /* flash write code */
243         if (target_alloc_working_area(target, sizeof(mdr32fx_flash_write_code),
244                         &write_algorithm) != ERROR_OK) {
245                 LOG_WARNING("no working area available, can't do block memory writes");
246                 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
247         }
248
249         retval = target_write_buffer(target, write_algorithm->address,
250                         sizeof(mdr32fx_flash_write_code), mdr32fx_flash_write_code);
251         if (retval != ERROR_OK)
252                 return retval;
253
254         /* memory buffer */
255         while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) {
256                 buffer_size /= 2;
257                 buffer_size &= ~3UL; /* Make sure it's 4 byte aligned */
258                 if (buffer_size <= 256) {
259                         /* we already allocated the writing code, but failed to get a
260                          * buffer, free the algorithm */
261                         target_free_working_area(target, write_algorithm);
262
263                         LOG_WARNING("no large enough working area available, can't do block memory writes");
264                         return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
265                 }
266         }
267
268         init_reg_param(&reg_params[0], "r0", 32, PARAM_IN_OUT); /* flash base (in), status (out) */
269         init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);    /* count (32bit) */
270         init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT);    /* buffer start */
271         init_reg_param(&reg_params[3], "r3", 32, PARAM_OUT);    /* buffer end */
272         init_reg_param(&reg_params[4], "r4", 32, PARAM_IN_OUT); /* target address */
273
274         buf_set_u32(reg_params[0].value, 0, 32, FLASH_REG_BASE);
275         buf_set_u32(reg_params[1].value, 0, 32, count);
276         buf_set_u32(reg_params[2].value, 0, 32, source->address);
277         buf_set_u32(reg_params[3].value, 0, 32, source->address + source->size);
278         buf_set_u32(reg_params[4].value, 0, 32, address);
279
280         armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
281         armv7m_info.core_mode = ARM_MODE_THREAD;
282
283         retval = target_run_flash_async_algorithm(target, buffer, count, 4,
284                         0, NULL,
285                         5, reg_params,
286                         source->address, source->size,
287                         write_algorithm->address, 0,
288                         &armv7m_info);
289
290         if (retval == ERROR_FLASH_OPERATION_FAILED)
291                 LOG_ERROR("flash write failed at address 0x%"PRIx32,
292                                 buf_get_u32(reg_params[4].value, 0, 32));
293
294         target_free_working_area(target, source);
295         target_free_working_area(target, write_algorithm);
296
297         destroy_reg_param(&reg_params[0]);
298         destroy_reg_param(&reg_params[1]);
299         destroy_reg_param(&reg_params[2]);
300         destroy_reg_param(&reg_params[3]);
301         destroy_reg_param(&reg_params[4]);
302
303         return retval;
304 }
305
306 static int mdr_write(struct flash_bank *bank, const uint8_t *buffer,
307                 uint32_t offset, uint32_t count)
308 {
309         struct target *target = bank->target;
310         struct mdr_flash_bank *mdr_info = bank->driver_priv;
311         uint8_t *new_buffer = NULL;
312
313         if (bank->target->state != TARGET_HALTED) {
314                 LOG_ERROR("Target not halted");
315                 return ERROR_TARGET_NOT_HALTED;
316         }
317
318         if (offset & 0x3) {
319                 LOG_ERROR("offset 0x%" PRIx32 " breaks required 4-byte alignment", offset);
320                 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
321         }
322
323         /* If there's an odd number of bytes, the data has to be padded. Duplicate
324          * the buffer and use the normal code path with a single block write since
325          * it's probably cheaper than to special case the last odd write using
326          * discrete accesses. */
327         int rem = count % 4;
328         if (rem) {
329                 new_buffer = malloc(count + rem);
330                 if (new_buffer == NULL) {
331                         LOG_ERROR("odd number of bytes to write and no memory for padding buffer");
332                         return ERROR_FAIL;
333                 }
334                 LOG_INFO("odd number of bytes to write, padding with 0xff");
335                 buffer = memcpy(new_buffer, buffer, count);
336                 while (rem--)
337                         new_buffer[count++] = 0xff;
338         }
339
340         uint32_t flash_cmd, cur_per_clock;
341         int retval, retval2;
342
343         retval = target_read_u32(target, MD_PER_CLOCK, &cur_per_clock);
344         if (retval != ERROR_OK)
345                 goto free_buffer;
346
347         if (!(cur_per_clock & MD_PER_CLOCK_RST_CLK)) {
348                 /* Something's very wrong if the RST_CLK module is not clocked */
349                 LOG_ERROR("Target needs reset before flash operations");
350                 retval = ERROR_FLASH_OPERATION_FAILED;
351                 goto free_buffer;
352         }
353
354         retval = target_write_u32(target, MD_PER_CLOCK, cur_per_clock | MD_PER_CLOCK_EEPROM);
355         if (retval != ERROR_OK)
356                 goto free_buffer;
357
358         retval = target_write_u32(target, FLASH_KEY, KEY);
359         if (retval != ERROR_OK)
360                 goto free_buffer;
361
362         retval = target_read_u32(target, FLASH_CMD, &flash_cmd);
363         if (retval != ERROR_OK)
364                 goto reset_pg_and_lock;
365
366         /* Switch on register access */
367         flash_cmd = (flash_cmd & FLASH_DELAY_MASK) | FLASH_CON;
368         if (mdr_info->mem_type)
369                 flash_cmd |= FLASH_IFREN;
370         retval = target_write_u32(target, FLASH_CMD, flash_cmd);
371         if (retval != ERROR_OK)
372                 goto reset_pg_and_lock;
373
374         /* try using block write */
375         retval = mdr_write_block(bank, buffer, offset, count/4);
376
377         if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) {
378                 /* if block write failed (no sufficient working area),
379                  * we use normal (slow) single halfword accesses */
380                 LOG_WARNING("Can't use block writes, falling back to single memory accesses");
381
382                 unsigned int page_size = bank->size / mdr_info->page_count;
383                 unsigned int page_mask = page_size - 1;
384                 while (count > 0) {
385                         unsigned int i, j;
386                         unsigned int cur_page = offset & ~page_mask;
387                         unsigned int bytes_to_write = cur_page + page_size - offset;
388                         if (count < bytes_to_write)
389                                 bytes_to_write = count;
390
391                         /*LOG_INFO("Selecting next page: %08x", cur_page);*/
392
393                         for (i = 0; i < mdr_info->sec_count; i++) {
394                                 retval = target_write_u32(target, FLASH_ADR, offset + i*4);
395                                 if (retval != ERROR_OK)
396                                         goto reset_pg_and_lock;
397                                 /*LOG_INFO("Selecting page/sector: %08x", offset + i*4);*/
398
399                                 flash_cmd |= FLASH_XE | FLASH_PROG;
400                                 retval = target_write_u32(target, FLASH_CMD, flash_cmd);
401                                 if (retval != ERROR_OK)
402                                         goto reset_pg_and_lock;
403
404                                 flash_cmd |= FLASH_NVSTR;
405                                 retval = target_write_u32(target, FLASH_CMD, flash_cmd);
406                                 if (retval != ERROR_OK)
407                                         goto reset_pg_and_lock;
408
409                                 for (j = 0;
410                                      (((offset + j + i*4) & ~page_mask) == cur_page) &&
411                                              (j + i*4 < count);
412                                      j += mdr_info->sec_count*4) {
413                                         uint32_t value;
414                                         memcpy(&value, buffer + j + i*4, sizeof(uint32_t));
415                                         retval = target_write_u32(target, FLASH_DI, value);
416                                         if (retval != ERROR_OK)
417                                                 goto reset_pg_and_lock;
418                                         /*LOG_INFO("Writing to addr %08x", offset + j + i*4);*/
419                                         retval = target_write_u32(target, FLASH_ADR, offset + j + i*4);
420                                         if (retval != ERROR_OK)
421                                                 goto reset_pg_and_lock;
422
423                                         flash_cmd |= FLASH_YE;
424                                         retval = target_write_u32(target, FLASH_CMD, flash_cmd);
425                                         if (retval != ERROR_OK)
426                                                 goto reset_pg_and_lock;
427                                         flash_cmd &= ~FLASH_YE;
428                                         retval = target_write_u32(target, FLASH_CMD, flash_cmd);
429                                         if (retval != ERROR_OK)
430                                                 goto reset_pg_and_lock;
431                                 }
432                                 flash_cmd &= ~FLASH_NVSTR;
433                                 retval = target_write_u32(target, FLASH_CMD, flash_cmd);
434                                 if (retval != ERROR_OK)
435                                         goto reset_pg_and_lock;
436
437                                 flash_cmd &= ~(FLASH_XE | FLASH_PROG);
438                                 retval = target_write_u32(target, FLASH_CMD, flash_cmd);
439                                 if (retval != ERROR_OK)
440                                         goto reset_pg_and_lock;
441                         }
442
443                         buffer += bytes_to_write;
444                         offset += bytes_to_write;
445                         count -= bytes_to_write;
446                 }
447         }
448
449 reset_pg_and_lock:
450         flash_cmd &= FLASH_DELAY_MASK;
451         retval2 = target_write_u32(target, FLASH_CMD, flash_cmd);
452         if (retval == ERROR_OK)
453                 retval = retval2;
454
455         retval2 = target_write_u32(target, FLASH_KEY, 0);
456         if (retval == ERROR_OK)
457                 retval = retval2;
458
459 free_buffer:
460         if (new_buffer)
461                 free(new_buffer);
462
463         /* read some bytes bytes to flush buffer in flash accelerator.
464          * See errata for 1986VE1T and 1986VE3. Error 0007 */
465         if ((retval == ERROR_OK) && (!mdr_info->mem_type)) {
466                 uint32_t tmp;
467                 target_checksum_memory(bank->target, bank->base, 64, &tmp);
468         }
469
470         return retval;
471 }
472
473 static int mdr_read(struct flash_bank *bank, uint8_t *buffer,
474                     uint32_t offset, uint32_t count)
475 {
476         struct target *target = bank->target;
477         struct mdr_flash_bank *mdr_info = bank->driver_priv;
478         int retval, retval2;
479
480         if (!mdr_info->mem_type)
481                 return default_flash_read(bank, buffer, offset, count);
482
483         if (bank->target->state != TARGET_HALTED) {
484                 LOG_ERROR("Target not halted");
485                 return ERROR_TARGET_NOT_HALTED;
486         }
487
488         if (offset & 0x3) {
489                 LOG_ERROR("offset 0x%" PRIx32 " breaks required 4-byte alignment", offset);
490                 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
491         }
492
493         if (count & 0x3) {
494                 LOG_ERROR("count 0x%" PRIx32 " breaks required 4-byte alignment", count);
495                 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
496         }
497
498         uint32_t flash_cmd, cur_per_clock;
499
500         retval = target_read_u32(target, MD_PER_CLOCK, &cur_per_clock);
501         if (retval != ERROR_OK)
502                 goto err;
503
504         if (!(cur_per_clock & MD_PER_CLOCK_RST_CLK)) {
505                 /* Something's very wrong if the RST_CLK module is not clocked */
506                 LOG_ERROR("Target needs reset before flash operations");
507                 retval = ERROR_FLASH_OPERATION_FAILED;
508                 goto err;
509         }
510
511         retval = target_write_u32(target, MD_PER_CLOCK, cur_per_clock | MD_PER_CLOCK_EEPROM);
512         if (retval != ERROR_OK)
513                 goto err;
514
515         retval = target_write_u32(target, FLASH_KEY, KEY);
516         if (retval != ERROR_OK)
517                 goto err;
518
519         retval = target_read_u32(target, FLASH_CMD, &flash_cmd);
520         if (retval != ERROR_OK)
521                 goto err_lock;
522
523         /* Switch on register access */
524         flash_cmd = (flash_cmd & FLASH_DELAY_MASK) | FLASH_CON | FLASH_IFREN;
525         retval = target_write_u32(target, FLASH_CMD, flash_cmd);
526         if (retval != ERROR_OK)
527                 goto reset_pg_and_lock;
528
529         for (uint32_t i = 0; i < count; i += 4) {
530                 retval = target_write_u32(target, FLASH_ADR, offset + i);
531                 if (retval != ERROR_OK)
532                         goto reset_pg_and_lock;
533
534                 retval = target_write_u32(target, FLASH_CMD, flash_cmd |
535                                           FLASH_XE | FLASH_YE | FLASH_SE);
536                 if (retval != ERROR_OK)
537                         goto reset_pg_and_lock;
538
539                 uint32_t buf;
540                 retval = target_read_u32(target, FLASH_DO, &buf);
541                 if (retval != ERROR_OK)
542                         goto reset_pg_and_lock;
543
544                 buf_set_u32(buffer, i * 8, 32, buf);
545
546                 retval = target_write_u32(target, FLASH_CMD, flash_cmd);
547                 if (retval != ERROR_OK)
548                         goto reset_pg_and_lock;
549
550         }
551
552 reset_pg_and_lock:
553         flash_cmd &= FLASH_DELAY_MASK;
554         retval2 = target_write_u32(target, FLASH_CMD, flash_cmd);
555         if (retval == ERROR_OK)
556                 retval = retval2;
557
558 err_lock:
559         retval2 = target_write_u32(target, FLASH_KEY, 0);
560         if (retval == ERROR_OK)
561                 retval = retval2;
562
563 err:
564         return retval;
565 }
566
567 static int mdr_probe(struct flash_bank *bank)
568 {
569         struct mdr_flash_bank *mdr_info = bank->driver_priv;
570         unsigned int page_count, page_size, i;
571
572         page_count = mdr_info->page_count;
573         page_size = bank->size / page_count;
574
575         if (bank->sectors) {
576                 free(bank->sectors);
577                 bank->sectors = NULL;
578         }
579
580         bank->num_sectors = page_count;
581         bank->sectors = malloc(sizeof(struct flash_sector) * page_count);
582
583         for (i = 0; i < page_count; i++) {
584                 bank->sectors[i].offset = i * page_size;
585                 bank->sectors[i].size = page_size;
586                 bank->sectors[i].is_erased = -1;
587                 bank->sectors[i].is_protected = 0;
588         }
589
590         mdr_info->probed = 1;
591
592         return ERROR_OK;
593 }
594
595 static int mdr_auto_probe(struct flash_bank *bank)
596 {
597         struct mdr_flash_bank *mdr_info = bank->driver_priv;
598         if (mdr_info->probed)
599                 return ERROR_OK;
600         return mdr_probe(bank);
601 }
602
603 static int get_mdr_info(struct flash_bank *bank, char *buf, int buf_size)
604 {
605         struct mdr_flash_bank *mdr_info = bank->driver_priv;
606         snprintf(buf, buf_size, "MDR32Fx - %s",
607                  mdr_info->mem_type ? "info memory" : "main memory");
608
609         return ERROR_OK;
610 }
611
612 struct flash_driver mdr_flash = {
613         .name = "mdr",
614         .usage = "flash bank <name> mdr <base> <size> 0 0 <target#> <type> <page_count> <sec_count>\n"
615         "<type>: 0 for main memory, 1 for info memory",
616         .flash_bank_command = mdr_flash_bank_command,
617         .erase = mdr_erase,
618         .write = mdr_write,
619         .read = mdr_read,
620         .probe = mdr_probe,
621         .auto_probe = mdr_auto_probe,
622         .erase_check = default_flash_blank_check,
623         .info = get_mdr_info,
624         .free_driver_priv = default_flash_free_driver_priv,
625 };