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