46ad75281065a057fe57c43de2997c033c4bed08
[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, 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 goto reset_pg_and_lock;
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, 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), (uint8_t *)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, 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 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 return retval;
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 return ERROR_FLASH_OPERATION_FAILED;
362 }
363
364 retval = target_write_u32(target, MD_PER_CLOCK, cur_per_clock | MD_PER_CLOCK_EEPROM);
365 if (retval != ERROR_OK)
366 return retval;
367
368 retval = target_write_u32(target, FLASH_KEY, KEY);
369 if (retval != ERROR_OK)
370 goto reset_pg_and_lock;
371
372 retval = target_read_u32(target, FLASH_CMD, &flash_cmd);
373 if (retval != ERROR_OK)
374 goto reset_pg_and_lock;
375
376 /* Switch on register access */
377 flash_cmd = (flash_cmd & FLASH_DELAY_MASK) | FLASH_CON;
378 if (mdr_info->mem_type)
379 flash_cmd |= FLASH_IFREN;
380 retval = target_write_u32(target, FLASH_CMD, flash_cmd);
381 if (retval != ERROR_OK)
382 goto reset_pg_and_lock;
383
384 /* try using block write */
385 retval = mdr_write_block(bank, buffer, offset, count/4);
386
387 if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) {
388 /* if block write failed (no sufficient working area),
389 * we use normal (slow) single halfword accesses */
390 LOG_WARNING("Can't use block writes, falling back to single memory accesses");
391
392 unsigned int page_size = bank->size / mdr_info->page_count;
393 unsigned int page_mask = page_size - 1;
394 while (count > 0) {
395 unsigned int i, j;
396 unsigned int cur_page = offset & ~page_mask;
397 unsigned int bytes_to_write = cur_page + page_size - offset;
398 if (count < bytes_to_write)
399 bytes_to_write = count;
400
401 /*LOG_INFO("Selecting next page: %08x", cur_page);*/
402
403 for (i = 0; i < mdr_info->sec_count; i++) {
404 retval = target_write_u32(target, FLASH_ADR, offset + i*4);
405 if (retval != ERROR_OK)
406 goto reset_pg_and_lock;
407 /*LOG_INFO("Selecting page/sector: %08x", offset + i*4);*/
408
409 flash_cmd |= FLASH_XE | FLASH_PROG;
410 retval = target_write_u32(target, FLASH_CMD, flash_cmd);
411 if (retval != ERROR_OK)
412 goto reset_pg_and_lock;
413
414 flash_cmd |= FLASH_NVSTR;
415 retval = target_write_u32(target, FLASH_CMD, flash_cmd);
416 if (retval != ERROR_OK)
417 goto reset_pg_and_lock;
418
419 for (j = 0;
420 (((offset + j + i*4) & ~page_mask) == cur_page) &&
421 (j + i*4 < count);
422 j += mdr_info->sec_count*4) {
423 uint32_t value;
424 memcpy(&value, buffer + j + i*4, sizeof(uint32_t));
425 retval = target_write_u32(target, FLASH_DI, value);
426 if (retval != ERROR_OK)
427 goto reset_pg_and_lock;
428 /*LOG_INFO("Writing to addr %08x", offset + j + i*4);*/
429 retval = target_write_u32(target, FLASH_ADR, offset + j + i*4);
430 if (retval != ERROR_OK)
431 goto reset_pg_and_lock;
432
433 flash_cmd |= FLASH_YE;
434 retval = target_write_u32(target, FLASH_CMD, flash_cmd);
435 if (retval != ERROR_OK)
436 goto reset_pg_and_lock;
437 flash_cmd &= ~FLASH_YE;
438 retval = target_write_u32(target, FLASH_CMD, flash_cmd);
439 if (retval != ERROR_OK)
440 goto reset_pg_and_lock;
441 }
442 flash_cmd &= ~FLASH_NVSTR;
443 retval = target_write_u32(target, FLASH_CMD, flash_cmd);
444 if (retval != ERROR_OK)
445 goto reset_pg_and_lock;
446
447 flash_cmd &= ~(FLASH_XE | FLASH_PROG);
448 retval = target_write_u32(target, FLASH_CMD, flash_cmd);
449 if (retval != ERROR_OK)
450 goto reset_pg_and_lock;
451 }
452
453 buffer += bytes_to_write;
454 offset += bytes_to_write;
455 count -= bytes_to_write;
456 }
457 }
458
459 reset_pg_and_lock:
460 flash_cmd &= FLASH_DELAY_MASK;
461 retval2 = target_write_u32(target, FLASH_CMD, flash_cmd);
462 if (retval == ERROR_OK)
463 retval = retval2;
464
465 retval2 = target_write_u32(target, FLASH_KEY, 0);
466 if (retval == ERROR_OK)
467 retval = retval2;
468
469 if (new_buffer)
470 free(new_buffer);
471
472 return retval;
473 }
474
475 static int mdr_probe(struct flash_bank *bank)
476 {
477 struct mdr_flash_bank *mdr_info = bank->driver_priv;
478 unsigned int page_count, page_size, i;
479
480 page_count = mdr_info->page_count;
481 page_size = bank->size / page_count;
482
483 bank->num_sectors = page_count;
484 bank->sectors = malloc(sizeof(struct flash_sector) * page_count);
485
486 for (i = 0; i < page_count; i++) {
487 bank->sectors[i].offset = i * page_size;
488 bank->sectors[i].size = page_size;
489 bank->sectors[i].is_erased = -1;
490 bank->sectors[i].is_protected = 0;
491 }
492
493 mdr_info->probed = 1;
494
495 return ERROR_OK;
496 }
497
498 static int mdr_auto_probe(struct flash_bank *bank)
499 {
500 struct mdr_flash_bank *mdr_info = bank->driver_priv;
501 if (mdr_info->probed)
502 return ERROR_OK;
503 return mdr_probe(bank);
504 }
505
506 static int get_mdr_info(struct flash_bank *bank, char *buf, int buf_size)
507 {
508 struct mdr_flash_bank *mdr_info = bank->driver_priv;
509 snprintf(buf, buf_size, "MDR32Fx - %s",
510 mdr_info->mem_type ? "info memory" : "main memory");
511
512 return ERROR_OK;
513 }
514
515 struct flash_driver mdr_flash = {
516 .name = "mdr",
517 .flash_bank_command = mdr_flash_bank_command,
518 .erase = mdr_erase,
519 .protect = mdr_protect,
520 .write = mdr_write,
521 .read = default_flash_read,
522 .probe = mdr_probe,
523 .auto_probe = mdr_auto_probe,
524 .erase_check = default_flash_blank_check,
525 .protect_check = mdr_protect_check,
526 .info = get_mdr_info,
527 };