mdr32fx: support for Milandr's MDR32Fx internal flash memory
[openocd.git] / src / flash / nor / mdr.c
blob46ad75281065a057fe57c43de2997c033c4bed08
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 ***************************************************************************/
30 #ifdef HAVE_CONFIG_H
31 #include "config.h"
32 #endif
34 #include "imp.h"
35 #include <helper/binarybuffer.h>
36 #include <target/algorithm.h>
37 #include <target/armv7m.h>
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)
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)
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)
64 #define KEY 0x8AAA5551
66 struct mdr_flash_bank {
67 int probed;
68 unsigned int mem_type;
69 unsigned int page_count;
70 unsigned int sec_count;
73 /* flash bank <name> mdr <base> <size> 0 0 <target#> <type> <page_count> <sec_count> */
74 FLASH_BANK_COMMAND_HANDLER(mdr_flash_bank_command)
76 struct mdr_flash_bank *mdr_info;
78 if (CMD_ARGC < 9)
79 return ERROR_COMMAND_SYNTAX_ERROR;
81 mdr_info = malloc(sizeof(struct mdr_flash_bank));
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;
91 static int mdr_protect_check(struct flash_bank *bank)
93 return ERROR_OK;
96 static int mdr_mass_erase(struct flash_bank *bank)
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;
104 retval = target_read_u32(target, FLASH_CMD, &flash_cmd);
105 if (retval != ERROR_OK)
106 return retval;
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;
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;
131 return retval;
134 static int mdr_erase(struct flash_bank *bank, int first, int last)
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;
142 if (bank->target->state != TARGET_HALTED) {
143 LOG_ERROR("Target not halted");
144 return ERROR_TARGET_NOT_HALTED;
147 retval = target_read_u32(target, MD_PER_CLOCK, &cur_per_clock);
148 if (retval != ERROR_OK)
149 return retval;
151 if (!(cur_per_clock & 0x10)) {
152 LOG_ERROR("Target needs reset before flash operations");
153 return ERROR_FLASH_OPERATION_FAILED;
156 retval = target_write_u32(target, MD_PER_CLOCK, cur_per_clock | MD_PER_CLOCK_EEPROM);
157 if (retval != ERROR_OK)
158 return retval;
160 retval = target_write_u32(target, FLASH_KEY, KEY);
161 if (retval != ERROR_OK)
162 goto reset_pg_and_lock;
164 retval = target_read_u32(target, FLASH_CMD, &flash_cmd);
165 if (retval != ERROR_OK)
166 goto reset_pg_and_lock;
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;
176 if ((first == 0) && (last == (bank->num_sectors - 1))) {
177 retval = mdr_mass_erase(bank);
178 goto reset_pg_and_lock;
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;
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;
205 bank->sectors[i].is_erased = 1;
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;
214 retval2 = target_write_u32(target, FLASH_KEY, 0);
215 if (retval == ERROR_OK)
216 retval = retval2;
218 return retval;
221 static int mdr_protect(struct flash_bank *bank, int set, int first, int last)
223 return ERROR_OK;
226 static int mdr_write_block(struct flash_bank *bank, uint8_t *buffer,
227 uint32_t offset, uint32_t count)
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;
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
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;
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;
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);
274 LOG_WARNING("no large enough working area available, can't do block memory writes");
275 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
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 */
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);
291 armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
292 armv7m_info.core_mode = ARM_MODE_THREAD;
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);
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));
305 target_free_working_area(target, source);
306 target_free_working_area(target, write_algorithm);
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]);
314 return retval;
317 static int mdr_write(struct flash_bank *bank, uint8_t *buffer,
318 uint32_t offset, uint32_t count)
320 struct target *target = bank->target;
321 struct mdr_flash_bank *mdr_info = bank->driver_priv;
322 uint8_t *new_buffer = NULL;
324 if (bank->target->state != TARGET_HALTED) {
325 LOG_ERROR("Target not halted");
326 return ERROR_TARGET_NOT_HALTED;
329 if (offset & 0x3) {
330 LOG_ERROR("offset 0x%" PRIx32 " breaks required 4-byte alignment", offset);
331 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
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;
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;
351 uint32_t flash_cmd, cur_per_clock;
352 int retval, retval2;
354 retval = target_read_u32(target, MD_PER_CLOCK, &cur_per_clock);
355 if (retval != ERROR_OK)
356 return retval;
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;
364 retval = target_write_u32(target, MD_PER_CLOCK, cur_per_clock | MD_PER_CLOCK_EEPROM);
365 if (retval != ERROR_OK)
366 return retval;
368 retval = target_write_u32(target, FLASH_KEY, KEY);
369 if (retval != ERROR_OK)
370 goto reset_pg_and_lock;
372 retval = target_read_u32(target, FLASH_CMD, &flash_cmd);
373 if (retval != ERROR_OK)
374 goto reset_pg_and_lock;
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;
384 /* try using block write */
385 retval = mdr_write_block(bank, buffer, offset, count/4);
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");
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;
401 /*LOG_INFO("Selecting next page: %08x", cur_page);*/
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);*/
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;
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;
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;
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;
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;
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;
453 buffer += bytes_to_write;
454 offset += bytes_to_write;
455 count -= bytes_to_write;
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;
465 retval2 = target_write_u32(target, FLASH_KEY, 0);
466 if (retval == ERROR_OK)
467 retval = retval2;
469 if (new_buffer)
470 free(new_buffer);
472 return retval;
475 static int mdr_probe(struct flash_bank *bank)
477 struct mdr_flash_bank *mdr_info = bank->driver_priv;
478 unsigned int page_count, page_size, i;
480 page_count = mdr_info->page_count;
481 page_size = bank->size / page_count;
483 bank->num_sectors = page_count;
484 bank->sectors = malloc(sizeof(struct flash_sector) * page_count);
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;
493 mdr_info->probed = 1;
495 return ERROR_OK;
498 static int mdr_auto_probe(struct flash_bank *bank)
500 struct mdr_flash_bank *mdr_info = bank->driver_priv;
501 if (mdr_info->probed)
502 return ERROR_OK;
503 return mdr_probe(bank);
506 static int get_mdr_info(struct flash_bank *bank, char *buf, int buf_size)
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");
512 return ERROR_OK;
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,