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