kinetis flash: use longword write when writing into pflash
[openocd.git] / src / flash / nand / tcl.c
1 /***************************************************************************
2 * Copyright (C) 2007 by Dominic Rath <Dominic.Rath@gmx.de> *
3 * Copyright (C) 2002 Thomas Gleixner <tglx@linutronix.de> *
4 * Copyright (C) 2009 Zachary T Welch <zw@superlucidity.net> *
5 * *
6 * Partially based on drivers/mtd/nand_ids.c from Linux. *
7 * *
8 * This program is free software; you can redistribute it and/or modify *
9 * it under the terms of the GNU General Public License as published by *
10 * the Free Software Foundation; either version 2 of the License, or *
11 * (at your option) any later version. *
12 * *
13 * This program is distributed in the hope that it will be useful, *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16 * GNU General Public License for more details. *
17 * *
18 * You should have received a copy of the GNU General Public License *
19 * along with this program; if not, write to the *
20 * Free Software Foundation, Inc., *
21 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
22 ***************************************************************************/
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26
27 #include "core.h"
28 #include "imp.h"
29 #include "fileio.h"
30 #include <target/target.h>
31
32 // to be removed
33 extern struct nand_device *nand_devices;
34
35 COMMAND_HANDLER(handle_nand_list_command)
36 {
37 struct nand_device *p;
38 int i;
39
40 if (!nand_devices)
41 {
42 command_print(CMD_CTX, "no NAND flash devices configured");
43 return ERROR_OK;
44 }
45
46 for (p = nand_devices, i = 0; p; p = p->next, i++)
47 {
48 if (p->device)
49 command_print(CMD_CTX, "#%i: %s (%s) "
50 "pagesize: %i, buswidth: %i,\n\t"
51 "blocksize: %i, blocks: %i",
52 i, p->device->name, p->manufacturer->name,
53 p->page_size, p->bus_width,
54 p->erase_size, p->num_blocks);
55 else
56 command_print(CMD_CTX, "#%i: not probed", i);
57 }
58
59 return ERROR_OK;
60 }
61
62 COMMAND_HANDLER(handle_nand_info_command)
63 {
64 int i = 0;
65 int j = 0;
66 int first = -1;
67 int last = -1;
68
69 switch (CMD_ARGC) {
70 default:
71 return ERROR_COMMAND_SYNTAX_ERROR;
72 case 1:
73 first = 0;
74 last = INT32_MAX;
75 break;
76 case 2:
77 COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], i);
78 first = last = i;
79 i = 0;
80 break;
81 case 3:
82 COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], first);
83 COMMAND_PARSE_NUMBER(int, CMD_ARGV[2], last);
84 break;
85 }
86
87 struct nand_device *p;
88 int retval = CALL_COMMAND_HANDLER(nand_command_get_device, 0, &p);
89 if (ERROR_OK != retval)
90 return retval;
91
92 if (NULL == p->device)
93 {
94 command_print(CMD_CTX, "#%s: not probed", CMD_ARGV[0]);
95 return ERROR_OK;
96 }
97
98 if (first >= p->num_blocks)
99 first = p->num_blocks - 1;
100
101 if (last >= p->num_blocks)
102 last = p->num_blocks - 1;
103
104 command_print(CMD_CTX, "#%i: %s (%s) pagesize: %i, buswidth: %i, erasesize: %i",
105 i++, p->device->name, p->manufacturer->name, p->page_size, p->bus_width, p->erase_size);
106
107 for (j = first; j <= last; j++)
108 {
109 char *erase_state, *bad_state;
110
111 if (p->blocks[j].is_erased == 0)
112 erase_state = "not erased";
113 else if (p->blocks[j].is_erased == 1)
114 erase_state = "erased";
115 else
116 erase_state = "erase state unknown";
117
118 if (p->blocks[j].is_bad == 0)
119 bad_state = "";
120 else if (p->blocks[j].is_bad == 1)
121 bad_state = " (marked bad)";
122 else
123 bad_state = " (block condition unknown)";
124
125 command_print(CMD_CTX,
126 "\t#%i: 0x%8.8" PRIx32 " (%" PRId32 "kB) %s%s",
127 j,
128 p->blocks[j].offset,
129 p->blocks[j].size / 1024,
130 erase_state,
131 bad_state);
132 }
133
134 return ERROR_OK;
135 }
136
137 COMMAND_HANDLER(handle_nand_probe_command)
138 {
139 if (CMD_ARGC != 1)
140 {
141 return ERROR_COMMAND_SYNTAX_ERROR;
142 }
143
144 struct nand_device *p;
145 int retval = CALL_COMMAND_HANDLER(nand_command_get_device, 0, &p);
146 if (ERROR_OK != retval)
147 return retval;
148
149 if ((retval = nand_probe(p)) == ERROR_OK)
150 {
151 command_print(CMD_CTX, "NAND flash device '%s (%s)' found",
152 p->device->name, p->manufacturer->name);
153 }
154
155 return retval;
156 }
157
158 COMMAND_HANDLER(handle_nand_erase_command)
159 {
160 if (CMD_ARGC != 1 && CMD_ARGC != 3)
161 {
162 return ERROR_COMMAND_SYNTAX_ERROR;
163
164 }
165
166 struct nand_device *p;
167 int retval = CALL_COMMAND_HANDLER(nand_command_get_device, 0, &p);
168 if (ERROR_OK != retval)
169 return retval;
170
171 unsigned long offset;
172 unsigned long length;
173
174 /* erase specified part of the chip; or else everything */
175 if (CMD_ARGC == 3) {
176 unsigned long size = p->erase_size * p->num_blocks;
177
178 COMMAND_PARSE_NUMBER(ulong, CMD_ARGV[1], offset);
179 if ((offset % p->erase_size) != 0 || offset >= size)
180 return ERROR_INVALID_ARGUMENTS;
181
182 COMMAND_PARSE_NUMBER(ulong, CMD_ARGV[2], length);
183 if ((length == 0) || (length % p->erase_size) != 0
184 || (length + offset) > size)
185 return ERROR_INVALID_ARGUMENTS;
186
187 offset /= p->erase_size;
188 length /= p->erase_size;
189 } else {
190 offset = 0;
191 length = p->num_blocks;
192 }
193
194 retval = nand_erase(p, offset, offset + length - 1);
195 if (retval == ERROR_OK)
196 {
197 command_print(CMD_CTX, "erased blocks %lu to %lu "
198 "on NAND flash device #%s '%s'",
199 offset, offset + length,
200 CMD_ARGV[0], p->device->name);
201 }
202
203 return retval;
204 }
205
206 COMMAND_HANDLER(handle_nand_check_bad_blocks_command)
207 {
208 int first = -1;
209 int last = -1;
210
211 if ((CMD_ARGC < 1) || (CMD_ARGC > 3) || (CMD_ARGC == 2))
212 {
213 return ERROR_COMMAND_SYNTAX_ERROR;
214
215 }
216
217 struct nand_device *p;
218 int retval = CALL_COMMAND_HANDLER(nand_command_get_device, 0, &p);
219 if (ERROR_OK != retval)
220 return retval;
221
222 if (CMD_ARGC == 3)
223 {
224 unsigned long offset;
225 unsigned long length;
226
227 COMMAND_PARSE_NUMBER(ulong, CMD_ARGV[1], offset);
228 if (offset % p->erase_size)
229 return ERROR_INVALID_ARGUMENTS;
230 offset /= p->erase_size;
231
232 COMMAND_PARSE_NUMBER(ulong, CMD_ARGV[2], length);
233 if (length % p->erase_size)
234 return ERROR_INVALID_ARGUMENTS;
235
236 length -= 1;
237 length /= p->erase_size;
238
239 first = offset;
240 last = offset + length;
241 }
242
243 retval = nand_build_bbt(p, first, last);
244 if (retval == ERROR_OK)
245 {
246 command_print(CMD_CTX, "checked NAND flash device for bad blocks, "
247 "use \"nand info\" command to list blocks");
248 }
249
250 return retval;
251 }
252
253 COMMAND_HANDLER(handle_nand_write_command)
254 {
255 struct nand_device *nand = NULL;
256 struct nand_fileio_state s;
257 int retval = CALL_COMMAND_HANDLER(nand_fileio_parse_args,
258 &s, &nand, FILEIO_READ, false, true);
259 if (ERROR_OK != retval)
260 return retval;
261
262 uint32_t total_bytes = s.size;
263 while (s.size > 0)
264 {
265 int bytes_read = nand_fileio_read(nand, &s);
266 if (bytes_read <= 0)
267 {
268 command_print(CMD_CTX, "error while reading file");
269 return nand_fileio_cleanup(&s);
270 }
271 s.size -= bytes_read;
272
273 retval = nand_write_page(nand, s.address / nand->page_size,
274 s.page, s.page_size, s.oob, s.oob_size);
275 if (ERROR_OK != retval)
276 {
277 command_print(CMD_CTX, "failed writing file %s "
278 "to NAND flash %s at offset 0x%8.8" PRIx32,
279 CMD_ARGV[1], CMD_ARGV[0], s.address);
280 return nand_fileio_cleanup(&s);
281 }
282 s.address += s.page_size;
283 }
284
285 if (nand_fileio_finish(&s))
286 {
287 command_print(CMD_CTX, "wrote file %s to NAND flash %s up to "
288 "offset 0x%8.8" PRIx32 " in %fs (%0.3f KiB/s)",
289 CMD_ARGV[1], CMD_ARGV[0], s.address, duration_elapsed(&s.bench),
290 duration_kbps(&s.bench, total_bytes));
291 }
292 return ERROR_OK;
293 }
294
295 COMMAND_HANDLER(handle_nand_verify_command)
296 {
297 struct nand_device *nand = NULL;
298 struct nand_fileio_state file;
299 int retval = CALL_COMMAND_HANDLER(nand_fileio_parse_args,
300 &file, &nand, FILEIO_READ, false, true);
301 if (ERROR_OK != retval)
302 return retval;
303
304 struct nand_fileio_state dev;
305 nand_fileio_init(&dev);
306 dev.address = file.address;
307 dev.size = file.size;
308 dev.oob_format = file.oob_format;
309 retval = nand_fileio_start(CMD_CTX, nand, NULL, FILEIO_NONE, &dev);
310 if (ERROR_OK != retval)
311 return retval;
312
313 while (file.size > 0)
314 {
315 retval = nand_read_page(nand, dev.address / dev.page_size,
316 dev.page, dev.page_size, dev.oob, dev.oob_size);
317 if (ERROR_OK != retval)
318 {
319 command_print(CMD_CTX, "reading NAND flash page failed");
320 nand_fileio_cleanup(&dev);
321 nand_fileio_cleanup(&file);
322 return retval;
323 }
324
325 int bytes_read = nand_fileio_read(nand, &file);
326 if (bytes_read <= 0)
327 {
328 command_print(CMD_CTX, "error while reading file");
329 nand_fileio_cleanup(&dev);
330 nand_fileio_cleanup(&file);
331 return ERROR_FAIL;
332 }
333
334 if ((dev.page && memcmp(dev.page, file.page, dev.page_size)) ||
335 (dev.oob && memcmp(dev.oob, file.oob, dev.oob_size)) )
336 {
337 command_print(CMD_CTX, "NAND flash contents differ "
338 "at 0x%8.8" PRIx32, dev.address);
339 nand_fileio_cleanup(&dev);
340 nand_fileio_cleanup(&file);
341 return ERROR_FAIL;
342 }
343
344 file.size -= bytes_read;
345 dev.address += nand->page_size;
346 }
347
348 if (nand_fileio_finish(&file) == ERROR_OK)
349 {
350 command_print(CMD_CTX, "verified file %s in NAND flash %s "
351 "up to offset 0x%8.8" PRIx32 " in %fs (%0.3f KiB/s)",
352 CMD_ARGV[1], CMD_ARGV[0], dev.address, duration_elapsed(&file.bench),
353 duration_kbps(&file.bench, dev.size));
354 }
355
356 return nand_fileio_cleanup(&dev);
357 }
358
359 COMMAND_HANDLER(handle_nand_dump_command)
360 {
361 int filesize;
362 struct nand_device *nand = NULL;
363 struct nand_fileio_state s;
364 int retval = CALL_COMMAND_HANDLER(nand_fileio_parse_args,
365 &s, &nand, FILEIO_WRITE, true, false);
366 if (ERROR_OK != retval)
367 return retval;
368
369 while (s.size > 0)
370 {
371 size_t size_written;
372 retval = nand_read_page(nand, s.address / nand->page_size,
373 s.page, s.page_size, s.oob, s.oob_size);
374 if (ERROR_OK != retval)
375 {
376 command_print(CMD_CTX, "reading NAND flash page failed");
377 nand_fileio_cleanup(&s);
378 return retval;
379 }
380
381 if (NULL != s.page)
382 fileio_write(&s.fileio, s.page_size, s.page, &size_written);
383
384 if (NULL != s.oob)
385 fileio_write(&s.fileio, s.oob_size, s.oob, &size_written);
386
387 s.size -= nand->page_size;
388 s.address += nand->page_size;
389 }
390
391 retval = fileio_size(&s.fileio, &filesize);
392 if (retval != ERROR_OK)
393 return retval;
394
395 if (nand_fileio_finish(&s) == ERROR_OK)
396 {
397 command_print(CMD_CTX, "dumped %ld bytes in %fs (%0.3f KiB/s)",
398 (long)filesize, duration_elapsed(&s.bench),
399 duration_kbps(&s.bench, filesize));
400 }
401 return ERROR_OK;
402 }
403
404 COMMAND_HANDLER(handle_nand_raw_access_command)
405 {
406 if ((CMD_ARGC < 1) || (CMD_ARGC > 2))
407 {
408 return ERROR_COMMAND_SYNTAX_ERROR;
409 }
410
411 struct nand_device *p;
412 int retval = CALL_COMMAND_HANDLER(nand_command_get_device, 0, &p);
413 if (ERROR_OK != retval)
414 return retval;
415
416 if (NULL == p->device)
417 {
418 command_print(CMD_CTX, "#%s: not probed", CMD_ARGV[0]);
419 return ERROR_OK;
420 }
421
422 if (CMD_ARGC == 2)
423 COMMAND_PARSE_ENABLE(CMD_ARGV[1], p->use_raw);
424
425 const char *msg = p->use_raw ? "enabled" : "disabled";
426 command_print(CMD_CTX, "raw access is %s", msg);
427
428 return ERROR_OK;
429 }
430
431 static const struct command_registration nand_exec_command_handlers[] = {
432 {
433 .name = "list",
434 .handler = handle_nand_list_command,
435 .mode = COMMAND_EXEC,
436 .help = "list configured NAND flash devices",
437 },
438 {
439 .name = "info",
440 .handler = handle_nand_info_command,
441 .mode = COMMAND_EXEC,
442 .usage = "[banknum | first_bank_num last_bank_num]",
443 .help = "print info about one or more NAND flash devices",
444 },
445 {
446 .name = "probe",
447 .handler = handle_nand_probe_command,
448 .mode = COMMAND_EXEC,
449 .usage = "bank_id",
450 .help = "identify NAND flash device",
451 },
452 {
453 .name = "check_bad_blocks",
454 .handler = handle_nand_check_bad_blocks_command,
455 .mode = COMMAND_EXEC,
456 .usage = "bank_id [offset length]",
457 .help = "check all or part of NAND flash device for bad blocks",
458 },
459 {
460 .name = "erase",
461 .handler = handle_nand_erase_command,
462 .mode = COMMAND_EXEC,
463 .usage = "bank_id [offset length]",
464 .help = "erase all or subset of blocks on NAND flash device",
465 },
466 {
467 .name = "dump",
468 .handler = handle_nand_dump_command,
469 .mode = COMMAND_EXEC,
470 .usage = "bank_id filename offset length "
471 "['oob_raw'|'oob_only']",
472 .help = "dump from NAND flash device",
473 },
474 {
475 .name = "verify",
476 .handler = handle_nand_verify_command,
477 .mode = COMMAND_EXEC,
478 .usage = "bank_id filename offset "
479 "['oob_raw'|'oob_only'|'oob_softecc'|'oob_softecc_kw']",
480 .help = "verify NAND flash device",
481 },
482 {
483 .name = "write",
484 .handler = handle_nand_write_command,
485 .mode = COMMAND_EXEC,
486 .usage = "bank_id filename offset "
487 "['oob_raw'|'oob_only'|'oob_softecc'|'oob_softecc_kw']",
488 .help = "write to NAND flash device",
489 },
490 {
491 .name = "raw_access",
492 .handler = handle_nand_raw_access_command,
493 .mode = COMMAND_EXEC,
494 .usage = "bank_id ['enable'|'disable']",
495 .help = "raw access to NAND flash device",
496 },
497 COMMAND_REGISTRATION_DONE
498 };
499
500 static int nand_init(struct command_context *cmd_ctx)
501 {
502 if (!nand_devices)
503 return ERROR_OK;
504 struct command *parent = command_find_in_context(cmd_ctx, "nand");
505 return register_commands(cmd_ctx, parent, nand_exec_command_handlers);
506 }
507
508 COMMAND_HANDLER(handle_nand_init_command)
509 {
510 if (CMD_ARGC != 0)
511 return ERROR_COMMAND_SYNTAX_ERROR;
512
513 static bool nand_initialized = false;
514 if (nand_initialized)
515 {
516 LOG_INFO("'nand init' has already been called");
517 return ERROR_OK;
518 }
519 nand_initialized = true;
520
521 LOG_DEBUG("Initializing NAND devices...");
522 return nand_init(CMD_CTX);
523 }
524
525 static int nand_list_walker(struct nand_flash_controller *c, void *x)
526 {
527 struct command_context *cmd_ctx = (struct command_context *)x;
528 command_print(cmd_ctx, " %s", c->name);
529 return ERROR_OK;
530 }
531
532 COMMAND_HANDLER(handle_nand_list_drivers)
533 {
534 command_print(CMD_CTX, "Available NAND flash controller drivers:");
535 return nand_driver_walk(&nand_list_walker, CMD_CTX);
536 }
537
538 static COMMAND_HELPER(create_nand_device, const char *bank_name,
539 struct nand_flash_controller *controller)
540 {
541 struct nand_device *c;
542 struct target *target;
543 int retval;
544
545 if (CMD_ARGC < 2)
546 {
547 LOG_ERROR("missing target");
548 return ERROR_COMMAND_ARGUMENT_INVALID;
549 }
550 target = get_target(CMD_ARGV[1]);
551 if (!target) {
552 LOG_ERROR("invalid target %s", CMD_ARGV[1]);
553 return ERROR_COMMAND_ARGUMENT_INVALID;
554 }
555
556 if (NULL != controller->commands)
557 {
558 retval = register_commands(CMD_CTX, NULL,
559 controller->commands);
560 if (ERROR_OK != retval)
561 return retval;
562 }
563 c = malloc(sizeof(struct nand_device));
564 if (c == NULL)
565 {
566 LOG_ERROR("End of memory");
567 return ERROR_FAIL;
568 }
569
570 c->name = strdup(bank_name);
571 c->target = target;
572 c->controller = controller;
573 c->controller_priv = NULL;
574 c->manufacturer = NULL;
575 c->device = NULL;
576 c->bus_width = 0;
577 c->address_cycles = 0;
578 c->page_size = 0;
579 c->use_raw = 0;
580 c->next = NULL;
581
582 retval = CALL_COMMAND_HANDLER(controller->nand_device_command, c);
583 if (ERROR_OK != retval)
584 {
585 LOG_ERROR("'%s' driver rejected nand flash", controller->name);
586 free(c);
587 return ERROR_OK;
588 }
589
590 nand_device_add(c);
591
592 return ERROR_OK;
593 }
594
595 COMMAND_HANDLER(handle_nand_device_command)
596 {
597 if (CMD_ARGC < 2)
598 {
599 LOG_ERROR("incomplete nand device configuration");
600 return ERROR_FLASH_BANK_INVALID;
601 }
602
603 // save name and increment (for compatibility) with drivers
604 const char *bank_name = *CMD_ARGV++;
605 CMD_ARGC--;
606
607 const char *driver_name = CMD_ARGV[0];
608 struct nand_flash_controller *controller;
609 controller = nand_driver_find_by_name(CMD_ARGV[0]);
610 if (NULL == controller)
611 {
612 LOG_ERROR("No valid NAND flash driver found (%s)", driver_name);
613 return CALL_COMMAND_HANDLER(handle_nand_list_drivers);
614 }
615 return CALL_COMMAND_HANDLER(create_nand_device, bank_name, controller);
616 }
617
618 static const struct command_registration nand_config_command_handlers[] = {
619 {
620 .name = "device",
621 .handler = &handle_nand_device_command,
622 .mode = COMMAND_CONFIG,
623 .help = "defines a new NAND bank",
624 .usage = "bank_id driver target [driver_options ...]",
625 },
626 {
627 .name = "drivers",
628 .handler = &handle_nand_list_drivers,
629 .mode = COMMAND_ANY,
630 .help = "lists available NAND drivers",
631 },
632 {
633 .name = "init",
634 .mode = COMMAND_CONFIG,
635 .handler = &handle_nand_init_command,
636 .help = "initialize NAND devices",
637 },
638 COMMAND_REGISTRATION_DONE
639 };
640 static const struct command_registration nand_command_handlers[] = {
641 {
642 .name = "nand",
643 .mode = COMMAND_ANY,
644 .help = "NAND flash command group",
645 .chain = nand_config_command_handlers,
646 },
647 COMMAND_REGISTRATION_DONE
648 };
649
650 int nand_register_commands(struct command_context *cmd_ctx)
651 {
652 return register_commands(cmd_ctx, NULL, nand_command_handlers);
653 }
654
655

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)