flash/nor/spi: add adesto AT25DF081A
[openocd.git] / src / flash / nor / bluenrg-x.c
1 /***************************************************************************
2 * Copyright (C) 2017 by Michele Sardo *
3 * msmttchr@gmail.com *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
17 ***************************************************************************/
18
19 #ifdef HAVE_CONFIG_H
20 #include "config.h"
21 #endif
22
23 #include <target/algorithm.h>
24 #include <target/armv7m.h>
25 #include <target/cortex_m.h>
26 #include "imp.h"
27
28 #define FLASH_SIZE_REG (0x40100014)
29 #define DIE_ID_REG (0x4090001C)
30 #define JTAG_IDCODE_REG (0x40900028)
31 #define BLUENRG2_IDCODE (0x0200A041)
32 #define FLASH_BASE (0x10040000)
33 #define FLASH_PAGE_SIZE (2048)
34 #define FLASH_REG_COMMAND (0x40100000)
35 #define FLASH_REG_IRQRAW (0x40100010)
36 #define FLASH_REG_ADDRESS (0x40100018)
37 #define FLASH_REG_DATA (0x40100040)
38 #define FLASH_CMD_ERASE_PAGE 0x11
39 #define FLASH_CMD_MASSERASE 0x22
40 #define FLASH_CMD_WRITE 0x33
41 #define FLASH_CMD_BURSTWRITE 0xCC
42 #define FLASH_INT_CMDDONE 0x01
43 #define FLASH_WORD_LEN 4
44
45 struct bluenrgx_flash_bank {
46 int probed;
47 uint32_t idcode;
48 uint32_t die_id;
49 };
50
51 static int bluenrgx_protect_check(struct flash_bank *bank)
52 {
53 /* Nothing to do. Protection is only handled in SW. */
54 return ERROR_OK;
55 }
56
57 /* flash_bank bluenrg-x 0 0 0 0 <target#> */
58 FLASH_BANK_COMMAND_HANDLER(bluenrgx_flash_bank_command)
59 {
60 struct bluenrgx_flash_bank *bluenrgx_info;
61 /* Create the bank structure */
62 bluenrgx_info = calloc(1, sizeof(*bluenrgx_info));
63
64 /* Check allocation */
65 if (bluenrgx_info == NULL) {
66 LOG_ERROR("failed to allocate bank structure");
67 return ERROR_FAIL;
68 }
69
70 bank->driver_priv = bluenrgx_info;
71
72 bluenrgx_info->probed = 0;
73
74 if (CMD_ARGC < 6)
75 return ERROR_COMMAND_SYNTAX_ERROR;
76
77 return ERROR_OK;
78 }
79
80 static int bluenrgx_erase(struct flash_bank *bank, int first, int last)
81 {
82 int retval = ERROR_OK;
83 struct bluenrgx_flash_bank *bluenrgx_info = bank->driver_priv;
84 int num_sectors = (last - first + 1);
85 int mass_erase = (num_sectors == bank->num_sectors);
86 struct target *target = bank->target;
87 uint32_t address, command;
88
89 /* check preconditions */
90 if (bluenrgx_info->probed == 0)
91 return ERROR_FLASH_BANK_NOT_PROBED;
92
93 if (bank->target->state != TARGET_HALTED) {
94 LOG_ERROR("Target not halted");
95 return ERROR_TARGET_NOT_HALTED;
96 }
97 /* Disable blue module */
98 if (target_write_u32(target, 0x200000c0, 0) != ERROR_OK) {
99 LOG_ERROR("Blue disable failed");
100 return ERROR_FAIL;
101 }
102
103 if (mass_erase) {
104 command = FLASH_CMD_MASSERASE;
105 address = bank->base;
106 if (target_write_u32(target, FLASH_REG_IRQRAW, 0x3f) != ERROR_OK) {
107 LOG_ERROR("Register write failed");
108 return ERROR_FAIL;
109 }
110
111 if (target_write_u32(target, FLASH_REG_ADDRESS, address >> 2) != ERROR_OK) {
112 LOG_ERROR("Register write failed");
113 return ERROR_FAIL;
114 }
115
116 if (target_write_u32(target, FLASH_REG_COMMAND, command) != ERROR_OK) {
117 LOG_ERROR("Register write failed");
118 return ERROR_FAIL;
119 }
120
121 for (int i = 0; i < 100; i++) {
122 uint32_t value;
123 if (target_read_u32(target, FLASH_REG_IRQRAW, &value)) {
124 LOG_ERROR("Register write failed");
125 return ERROR_FAIL;
126 }
127 if (value & FLASH_INT_CMDDONE)
128 break;
129 if (i == 99) {
130 LOG_ERROR("Mass erase command failed (timeout)");
131 retval = ERROR_FAIL;
132 }
133 }
134
135 } else {
136 command = FLASH_CMD_ERASE_PAGE;
137 for (int i = first; i <= last; i++) {
138 address = bank->base+i*FLASH_PAGE_SIZE;
139
140 if (target_write_u32(target, FLASH_REG_IRQRAW, 0x3f) != ERROR_OK) {
141 LOG_ERROR("Register write failed");
142 return ERROR_FAIL;
143 }
144
145 if (target_write_u32(target, FLASH_REG_ADDRESS, address >> 2) != ERROR_OK) {
146 LOG_ERROR("Register write failed");
147 return ERROR_FAIL;
148 }
149
150 if (target_write_u32(target, FLASH_REG_COMMAND, command) != ERROR_OK) {
151 LOG_ERROR("Failed");
152 return ERROR_FAIL;
153 }
154
155 for (int j = 0; j < 100; j++) {
156 uint32_t value;
157 if (target_read_u32(target, FLASH_REG_IRQRAW, &value)) {
158 LOG_ERROR("Register write failed");
159 return ERROR_FAIL;
160 }
161 if (value & FLASH_INT_CMDDONE)
162 break;
163 if (j == 99) {
164 LOG_ERROR("Erase command failed (timeout)");
165 retval = ERROR_FAIL;
166 }
167 }
168 }
169 }
170
171 return retval;
172
173 }
174
175 static int bluenrgx_protect(struct flash_bank *bank, int set, int first, int last)
176 {
177 /* Protection is only handled in software: no hardware write protection
178 available in BlueNRG-x devices */
179 int sector;
180
181 for (sector = first; sector <= last; sector++)
182 bank->sectors[sector].is_protected = set;
183 return ERROR_OK;
184 }
185 static int bluenrgx_write_word(struct target *target, uint32_t address_base, uint8_t *values, uint32_t count)
186 {
187 int retval = ERROR_OK;
188
189 retval = target_write_u32(target, FLASH_REG_IRQRAW, 0x3f);
190 if (retval != ERROR_OK) {
191 LOG_ERROR("Register write failed, error code: %d", retval);
192 return retval;
193 }
194
195 for (uint32_t i = 0; i < count; i++) {
196 uint32_t address = address_base + i * FLASH_WORD_LEN;
197
198 retval = target_write_u32(target, FLASH_REG_ADDRESS, address >> 2);
199 if (retval != ERROR_OK) {
200 LOG_ERROR("Register write failed, error code: %d", retval);
201 return retval;
202 }
203
204 retval = target_write_buffer(target, FLASH_REG_DATA, FLASH_WORD_LEN, values + i * FLASH_WORD_LEN);
205 if (retval != ERROR_OK) {
206 LOG_ERROR("Register write failed, error code: %d", retval);
207 return retval;
208 }
209
210 retval = target_write_u32(target, FLASH_REG_COMMAND, FLASH_CMD_WRITE);
211 if (retval != ERROR_OK) {
212 LOG_ERROR("Register write failed, error code: %d", retval);
213 return retval;
214 }
215
216 for (int j = 0; j < 100; j++) {
217 uint32_t reg_value;
218 retval = target_read_u32(target, FLASH_REG_IRQRAW, &reg_value);
219
220 if (retval != ERROR_OK) {
221 LOG_ERROR("Register read failed, error code: %d", retval);
222 return retval;
223 }
224
225 if (reg_value & FLASH_INT_CMDDONE)
226 break;
227
228 if (j == 99) {
229 LOG_ERROR("Write command failed (timeout)");
230 return ERROR_FAIL;
231 }
232 }
233 }
234 return retval;
235 }
236
237 static int bluenrgx_write_bytes(struct target *target, uint32_t address_base, uint8_t *buffer, uint32_t count)
238 {
239 int retval = ERROR_OK;
240 uint8_t *new_buffer = NULL;
241 uint32_t pre_bytes = 0, post_bytes = 0, pre_word, post_word, pre_address, post_address;
242
243 if (count == 0) {
244 /* Just return if there are no bytes to write */
245 return retval;
246 }
247
248 if (address_base & 3) {
249 pre_bytes = address_base & 3;
250 pre_address = address_base - pre_bytes;
251 }
252
253 if ((count + pre_bytes) & 3) {
254 post_bytes = ((count + pre_bytes + 3) & ~3) - (count + pre_bytes);
255 post_address = (address_base + count) & ~3;
256 }
257
258 if (pre_bytes || post_bytes) {
259 uint32_t old_count = count;
260
261 count = old_count + pre_bytes + post_bytes;
262
263 new_buffer = malloc(count);
264
265 if (new_buffer == NULL) {
266 LOG_ERROR("odd number of bytes to write and no memory "
267 "for padding buffer");
268 return ERROR_FAIL;
269 }
270
271 LOG_INFO("Requested number of bytes to write and/or address not word aligned (%" PRIu32 "), extending to %"
272 PRIu32 " ", old_count, count);
273
274 if (pre_bytes) {
275 if (target_read_u32(target, pre_address, &pre_word)) {
276 LOG_ERROR("Memory read failed");
277 free(new_buffer);
278 return ERROR_FAIL;
279 }
280
281 }
282
283 if (post_bytes) {
284 if (target_read_u32(target, post_address, &post_word)) {
285 LOG_ERROR("Memory read failed");
286 free(new_buffer);
287 return ERROR_FAIL;
288 }
289
290 }
291
292 memcpy(new_buffer, &pre_word, pre_bytes);
293 memcpy((new_buffer+((pre_bytes+old_count) & ~3)), &post_word, 4);
294 memcpy(new_buffer+pre_bytes, buffer, old_count);
295 buffer = new_buffer;
296 }
297
298 retval = bluenrgx_write_word(target, address_base - pre_bytes, buffer, count/4);
299
300 if (new_buffer)
301 free(new_buffer);
302
303 return retval;
304 }
305
306 static int bluenrgx_write(struct flash_bank *bank, const uint8_t *buffer,
307 uint32_t offset, uint32_t count)
308 {
309 struct target *target = bank->target;
310 uint32_t buffer_size = 16384 + 8;
311 struct working_area *write_algorithm;
312 struct working_area *write_algorithm_sp;
313 struct working_area *source;
314 uint32_t address = bank->base + offset;
315 struct reg_param reg_params[5];
316 struct armv7m_algorithm armv7m_info;
317 int retval = ERROR_OK;
318 uint32_t pre_size = 0, fast_size = 0, post_size = 0;
319 uint32_t pre_offset = 0, fast_offset = 0, post_offset = 0;
320
321 /* See contrib/loaders/flash/bluenrg-x/bluenrg-x_write.c for source and
322 * hints how to generate the data!
323 */
324 static const uint8_t bluenrgx_flash_write_code[] = {
325 #include "../../../contrib/loaders/flash/bluenrg-x/bluenrg-x_write.inc"
326 };
327
328 if ((offset + count) > bank->size) {
329 LOG_ERROR("Requested write past beyond of flash size: (offset+count) = %d, size=%d",
330 (offset + count),
331 bank->size);
332 return ERROR_FLASH_DST_OUT_OF_BANK;
333 }
334
335 if (bank->target->state != TARGET_HALTED) {
336 LOG_ERROR("Target not halted");
337 return ERROR_TARGET_NOT_HALTED;
338 }
339
340 /* We are good here and we need to compute pre_size, fast_size, post_size */
341 pre_size = MIN(count, ((offset+0xF) & ~0xF) - offset);
342 pre_offset = offset;
343 fast_size = 16*((count - pre_size) / 16);
344 fast_offset = offset + pre_size;
345 post_size = (count-pre_size-fast_size) % 16;
346 post_offset = fast_offset + fast_size;
347
348 LOG_DEBUG("pre_size = %08x, pre_offset=%08x", pre_size, pre_offset);
349 LOG_DEBUG("fast_size = %08x, fast_offset=%08x", fast_size, fast_offset);
350 LOG_DEBUG("post_size = %08x, post_offset=%08x", post_size, post_offset);
351
352 /* Program initial chunk not 16 bytes aligned */
353 retval = bluenrgx_write_bytes(target, bank->base+pre_offset, (uint8_t *) buffer, pre_size);
354 if (retval) {
355 LOG_ERROR("bluenrgx_write_bytes failed %d", retval);
356 return ERROR_FAIL;
357 }
358
359 /* Program chunk 16 bytes aligned in fast mode */
360 if (fast_size) {
361
362 if (target_alloc_working_area(target, sizeof(bluenrgx_flash_write_code),
363 &write_algorithm) != ERROR_OK) {
364 LOG_WARNING("no working area available, can't do block memory writes");
365 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
366 }
367
368 retval = target_write_buffer(target, write_algorithm->address,
369 sizeof(bluenrgx_flash_write_code),
370 bluenrgx_flash_write_code);
371 if (retval != ERROR_OK)
372 return retval;
373
374 /* memory buffer */
375 if (target_alloc_working_area(target, buffer_size, &source)) {
376 LOG_WARNING("no large enough working area available");
377 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
378 }
379
380 /* Stack pointer area */
381 if (target_alloc_working_area(target, 64,
382 &write_algorithm_sp) != ERROR_OK) {
383 LOG_DEBUG("no working area for write code stack pointer");
384 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
385 }
386
387 armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
388 armv7m_info.core_mode = ARM_MODE_THREAD;
389
390 init_reg_param(&reg_params[0], "r0", 32, PARAM_IN_OUT);
391 init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
392 init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT);
393 init_reg_param(&reg_params[3], "r3", 32, PARAM_OUT);
394 init_reg_param(&reg_params[4], "sp", 32, PARAM_OUT);
395
396 /* FIFO start address (first two words used for write and read pointers) */
397 buf_set_u32(reg_params[0].value, 0, 32, source->address);
398 /* FIFO end address (first two words used for write and read pointers) */
399 buf_set_u32(reg_params[1].value, 0, 32, source->address + source->size);
400 /* Flash memory address */
401 buf_set_u32(reg_params[2].value, 0, 32, address+pre_size);
402 /* Number of bytes */
403 buf_set_u32(reg_params[3].value, 0, 32, fast_size);
404 /* Stack pointer for program working area */
405 buf_set_u32(reg_params[4].value, 0, 32, write_algorithm_sp->address);
406
407 LOG_DEBUG("source->address = %08" TARGET_PRIxADDR, source->address);
408 LOG_DEBUG("source->address+ source->size = %08" TARGET_PRIxADDR, source->address+source->size);
409 LOG_DEBUG("write_algorithm_sp->address = %08" TARGET_PRIxADDR, write_algorithm_sp->address);
410 LOG_DEBUG("address = %08x", address+pre_size);
411 LOG_DEBUG("count = %08x", count);
412
413 retval = target_run_flash_async_algorithm(target,
414 buffer+pre_size,
415 fast_size/16,
416 16, /* Block size: we write in block of 16 bytes to enjoy burstwrite speed */
417 0,
418 NULL,
419 5,
420 reg_params,
421 source->address,
422 source->size,
423 write_algorithm->address,
424 0,
425 &armv7m_info);
426
427 if (retval == ERROR_FLASH_OPERATION_FAILED) {
428 LOG_ERROR("error executing bluenrg-x flash write algorithm");
429
430 uint32_t error = buf_get_u32(reg_params[0].value, 0, 32);
431
432 if (error != 0)
433 LOG_ERROR("flash write failed = %08" PRIx32, error);
434 }
435 if (retval == ERROR_OK) {
436 uint32_t rp;
437 /* Read back rp and check that is valid */
438 retval = target_read_u32(target, source->address+4, &rp);
439 if (retval == ERROR_OK) {
440 if ((rp < source->address+8) || (rp > (source->address + source->size))) {
441 LOG_ERROR("flash write failed = %08" PRIx32, rp);
442 retval = ERROR_FLASH_OPERATION_FAILED;
443 }
444 }
445 }
446 target_free_working_area(target, source);
447 target_free_working_area(target, write_algorithm);
448 target_free_working_area(target, write_algorithm_sp);
449
450 destroy_reg_param(&reg_params[0]);
451 destroy_reg_param(&reg_params[1]);
452 destroy_reg_param(&reg_params[2]);
453 destroy_reg_param(&reg_params[3]);
454 destroy_reg_param(&reg_params[4]);
455 if (retval != ERROR_OK)
456 return retval;
457
458 }
459
460 /* Program chunk at end, not addressable by fast burst write algorithm */
461 retval = bluenrgx_write_bytes(target, bank->base+post_offset, (uint8_t *) (buffer+pre_size+fast_size), post_size);
462 if (retval) {
463 LOG_ERROR("bluenrgx_write_bytes failed %d", retval);
464 return ERROR_FAIL;
465 }
466 return retval;
467 }
468
469 static int bluenrgx_probe(struct flash_bank *bank)
470 {
471 struct bluenrgx_flash_bank *bluenrgx_info = bank->driver_priv;
472 uint32_t idcode, size_info, die_id;
473 int i;
474 int retval = target_read_u32(bank->target, JTAG_IDCODE_REG, &idcode);
475 if (retval != ERROR_OK)
476 return retval;
477 retval = target_read_u32(bank->target, FLASH_SIZE_REG, &size_info);
478 if (retval != ERROR_OK)
479 return retval;
480
481 retval = target_read_u32(bank->target, DIE_ID_REG, &die_id);
482 if (retval != ERROR_OK)
483 return retval;
484
485 bank->size = (size_info + 1) * 4;
486 bank->base = FLASH_BASE;
487 bank->num_sectors = bank->size/FLASH_PAGE_SIZE;
488 bank->sectors = realloc(bank->sectors, sizeof(struct flash_sector) * bank->num_sectors);
489
490 for (i = 0; i < bank->num_sectors; i++) {
491 bank->sectors[i].offset = i * FLASH_PAGE_SIZE;
492 bank->sectors[i].size = FLASH_PAGE_SIZE;
493 bank->sectors[i].is_erased = -1;
494 bank->sectors[i].is_protected = 0;
495 }
496
497 bluenrgx_info->probed = 1;
498 bluenrgx_info->die_id = die_id;
499 bluenrgx_info->idcode = idcode;
500 return ERROR_OK;
501 }
502
503 static int bluenrgx_auto_probe(struct flash_bank *bank)
504 {
505 struct bluenrgx_flash_bank *bluenrgx_info = bank->driver_priv;
506
507 if (bluenrgx_info->probed)
508 return ERROR_OK;
509
510 return bluenrgx_probe(bank);
511 }
512
513 /* This method must return a string displaying information about the bank */
514 static int bluenrgx_get_info(struct flash_bank *bank, char *buf, int buf_size)
515 {
516 struct bluenrgx_flash_bank *bluenrgx_info = bank->driver_priv;
517 int mask_number, cut_number;
518 char *part_name;
519
520 if (!bluenrgx_info->probed) {
521 int retval = bluenrgx_probe(bank);
522 if (retval != ERROR_OK) {
523 snprintf(buf, buf_size,
524 "Unable to find bank information.");
525 return retval;
526 }
527 }
528
529 if (bluenrgx_info->idcode == BLUENRG2_IDCODE)
530 part_name = "BLUENRG-2";
531 else
532 part_name = "BLUENRG-1";
533
534 mask_number = (bluenrgx_info->die_id >> 4) & 0xF;
535 cut_number = bluenrgx_info->die_id & 0xF;
536
537 snprintf(buf, buf_size,
538 "%s - Rev: %d.%d", part_name, mask_number, cut_number);
539 return ERROR_OK;
540 }
541
542 struct flash_driver bluenrgx_flash = {
543 .name = "bluenrg-x",
544 .flash_bank_command = bluenrgx_flash_bank_command,
545 .erase = bluenrgx_erase,
546 .protect = bluenrgx_protect,
547 .write = bluenrgx_write,
548 .read = default_flash_read,
549 .probe = bluenrgx_probe,
550 .erase_check = default_flash_blank_check,
551 .protect_check = bluenrgx_protect_check,
552 .auto_probe = bluenrgx_auto_probe,
553 .info = bluenrgx_get_info,
554 };

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)