2 * Copyright (C) 2011-2014 Lothar Waßmann <LW@KARO-electronics.de>
4 * See file CREDITS for list of people who contributed to this
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * version 2 as published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
23 #include <linux/err.h>
24 #include <jffs2/load_kernel.h>
27 #include <linux/sizes.h>
28 #include <asm/arch/regs-base.h>
29 #include <asm/imx-common/regs-gpmi.h>
30 #include <asm/imx-common/regs-bch.h>
32 struct mx28_nand_timing {
47 struct mx28_nand_timing timing;
50 u32 sectors_per_block;
51 u32 number_of_nands; /* not used by ROM code */
52 u32 total_internal_die; /* not used by ROM code */
53 u32 cell_type; /* not used by ROM code */
59 u32 ecc_blocks_per_page;
60 u32 rsrvd[6]; /* not used by ROM code */
71 u32 bb_mark_phys_offset;
74 #define BF_VAL(v, bf) (((v) & bf##_MASK) >> bf##_OFFSET)
76 static nand_info_t *mtd = &nand_info[0];
79 #define BIT(v,n) (((v) >> (n)) & 0x1)
81 static u8 calculate_parity_13_8(u8 d)
85 p |= (BIT(d, 6) ^ BIT(d, 5) ^ BIT(d, 3) ^ BIT(d, 2)) << 0;
86 p |= (BIT(d, 7) ^ BIT(d, 5) ^ BIT(d, 4) ^ BIT(d, 2) ^ BIT(d, 1)) << 1;
87 p |= (BIT(d, 7) ^ BIT(d, 6) ^ BIT(d, 5) ^ BIT(d, 1) ^ BIT(d, 0)) << 2;
88 p |= (BIT(d, 7) ^ BIT(d, 4) ^ BIT(d, 3) ^ BIT(d, 0)) << 3;
89 p |= (BIT(d, 6) ^ BIT(d, 4) ^ BIT(d, 3) ^ BIT(d, 2) ^ BIT(d, 1) ^ BIT(d, 0)) << 4;
93 static void encode_hamming_13_8(void *_src, void *_ecc, size_t size)
99 for (i = 0; i < size; i++)
100 ecc[i] = calculate_parity_13_8(src[i]);
103 static u32 calc_chksum(void *buf, size_t size)
109 for (i = 0; i < size; i++) {
116 Physical organisation of data in NAND flash:
118 payload chunk 0 (may be empty)
119 ecc for metadata + payload chunk 0
121 ecc for payload chunk 1
124 ecc for payload chunk n
127 static int calc_bb_offset(nand_info_t *mtd, struct mx28_fcb *fcb)
130 int chunk_data_size = fcb->ecc_blockn_size * 8;
131 int chunk_ecc_size = (fcb->ecc_blockn_type << 1) * 13;
132 int chunk_total_size = chunk_data_size + chunk_ecc_size;
133 int bb_mark_chunk, bb_mark_chunk_offs;
135 bb_mark_offset = (mtd->writesize - fcb->metadata_size) * 8;
136 if (fcb->ecc_block0_size == 0)
137 bb_mark_offset -= (fcb->ecc_block0_type << 1) * 13;
139 bb_mark_chunk = bb_mark_offset / chunk_total_size;
140 bb_mark_chunk_offs = bb_mark_offset - (bb_mark_chunk * chunk_total_size);
141 if (bb_mark_chunk_offs > chunk_data_size) {
142 printf("Unsupported ECC layout; BB mark resides in ECC data: %u\n",
146 bb_mark_offset -= bb_mark_chunk * chunk_ecc_size;
147 return bb_mark_offset;
151 * return number of blocks to skip for a contiguous partition
154 static int find_contig_space(int block, int num_blocks, int max_blocks)
158 int last = block + max_blocks;
160 debug("Searching %u contiguous blocks from %d..%d\n",
161 num_blocks, block, block + max_blocks - 1);
162 for (; block < last; block++) {
163 if (nand_block_isbad(mtd, block * mtd->erasesize)) {
166 debug("Skipping %u blocks to %u\n",
170 if (found >= num_blocks) {
171 debug("Found %u good blocks from %d..%d\n",
172 found, block - found + 1, block);
180 #define pr_fcb_val(p, n) debug("%s=%08x(%d)\n", #n, (p)->n, (p)->n)
182 static struct mx28_fcb *create_fcb(void *buf, int fw1_start_block,
183 int fw2_start_block, int fw_num_blocks)
185 struct gpmi_regs *gpmi_base = (void *)GPMI_BASE_ADDRESS;
186 struct bch_regs *bch_base = (void *)BCH_BASE_ADDRESS;
190 int bb_mark_bit_offs;
191 struct mx28_fcb *fcb;
194 if (gpmi_base == NULL || bch_base == NULL) {
195 return ERR_PTR(-ENOMEM);
198 fl0 = readl(&bch_base->hw_bch_flash0layout0);
199 fl1 = readl(&bch_base->hw_bch_flash0layout1);
200 t0 = readl(&gpmi_base->hw_gpmi_timing0);
202 metadata_size = BF_VAL(fl0, BCH_FLASHLAYOUT0_META_SIZE);
204 fcb = buf + ALIGN(metadata_size, 4);
205 fcb_offs = (void *)fcb - buf;
207 memset(buf, 0xff, fcb_offs);
208 memset(fcb, 0x00, sizeof(*fcb));
209 memset(fcb + 1, 0xff, mtd->erasesize - fcb_offs - sizeof(*fcb));
211 strncpy((char *)&fcb->fingerprint, "FCB ", 4);
212 fcb->version = cpu_to_be32(1);
214 /* ROM code assumes GPMI clock of 25 MHz */
215 fcb->timing.data_setup = BF_VAL(t0, GPMI_TIMING0_DATA_SETUP) * 40;
216 fcb->timing.data_hold = BF_VAL(t0, GPMI_TIMING0_DATA_HOLD) * 40;
217 fcb->timing.address_setup = BF_VAL(t0, GPMI_TIMING0_ADDRESS_SETUP) * 40;
219 fcb->page_data_size = mtd->writesize;
220 fcb->total_page_size = mtd->writesize + mtd->oobsize;
221 fcb->sectors_per_block = mtd->erasesize / mtd->writesize;
223 fcb->ecc_block0_type = BF_VAL(fl0, BCH_FLASHLAYOUT0_ECC0);
224 fcb->ecc_block0_size = BF_VAL(fl0, BCH_FLASHLAYOUT0_DATA0_SIZE);
225 fcb->ecc_blockn_type = BF_VAL(fl1, BCH_FLASHLAYOUT1_ECCN);
226 fcb->ecc_blockn_size = BF_VAL(fl1, BCH_FLASHLAYOUT1_DATAN_SIZE);
228 pr_fcb_val(fcb, ecc_block0_type);
229 pr_fcb_val(fcb, ecc_blockn_type);
230 pr_fcb_val(fcb, ecc_block0_size);
231 pr_fcb_val(fcb, ecc_blockn_size);
233 fcb->metadata_size = BF_VAL(fl0, BCH_FLASHLAYOUT0_META_SIZE);
234 fcb->ecc_blocks_per_page = BF_VAL(fl0, BCH_FLASHLAYOUT0_NBLOCKS);
235 fcb->bch_mode = readl(&bch_base->hw_bch_mode);
237 fcb->fw1_start_page = fw1_start_block * fcb->sectors_per_block;
238 fcb->fw1_sectors = fw_num_blocks * fcb->sectors_per_block;
239 pr_fcb_val(fcb, fw1_start_page);
240 pr_fcb_val(fcb, fw1_sectors);
242 if (fw2_start_block != 0 && fw2_start_block < mtd->size / mtd->erasesize) {
243 fcb->fw2_start_page = fw2_start_block * fcb->sectors_per_block;
244 fcb->fw2_sectors = fcb->fw1_sectors;
245 pr_fcb_val(fcb, fw2_start_page);
246 pr_fcb_val(fcb, fw2_sectors);
249 fcb->dbbt_search_area = 1;
251 bb_mark_bit_offs = calc_bb_offset(mtd, fcb);
252 if (bb_mark_bit_offs < 0)
253 return ERR_PTR(bb_mark_bit_offs);
254 fcb->bb_mark_byte = bb_mark_bit_offs / 8;
255 fcb->bb_mark_startbit = bb_mark_bit_offs % 8;
256 fcb->bb_mark_phys_offset = mtd->writesize;
258 pr_fcb_val(fcb, bb_mark_byte);
259 pr_fcb_val(fcb, bb_mark_startbit);
260 pr_fcb_val(fcb, bb_mark_phys_offset);
262 fcb->checksum = calc_chksum(&fcb->fingerprint, 512 - 4);
266 static int find_fcb(void *ref, int page)
269 struct nand_chip *chip = mtd->priv;
270 void *buf = malloc(mtd->erasesize);
275 chip->select_chip(mtd, 0);
276 chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page);
277 ret = chip->ecc.read_page_raw(mtd, chip, buf, 1, page);
279 printf("Failed to read FCB from page %u: %d\n", page, ret);
282 if (memcmp(buf, ref, mtd->writesize) == 0) {
283 debug("Found FCB in page %u (%08x)\n",
284 page, page * mtd->writesize);
288 chip->select_chip(mtd, -1);
293 static int write_fcb(void *buf, int block)
296 struct nand_chip *chip = mtd->priv;
297 int page = block * mtd->erasesize / mtd->writesize;
299 ret = find_fcb(buf, page);
301 printf("FCB at block %d is up to date\n", block);
306 ret = nand_erase(mtd, block * mtd->erasesize, mtd->erasesize);
308 printf("Failed to erase FCB block %u\n", block);
313 printf("Writing FCB to block %d @ %08llx\n", block,
314 (u64)block * mtd->erasesize);
316 chip->select_chip(mtd, 0);
317 ret = chip->write_page(mtd, chip, 0, mtd->writesize,
320 printf("Failed to write FCB to block %u: %d\n", block, ret);
322 chip->select_chip(mtd, -1);
327 #define chk_overlap(a,b) \
328 ((a##_start_block <= b##_end_block && \
329 a##_end_block >= b##_start_block) || \
330 (b##_start_block <= a##_end_block && \
331 b##_end_block >= a##_start_block))
333 #define fail_if_overlap(a,b,m1,m2) do { \
335 printf("check: %s[%lu..%lu] <> %s[%lu..%lu]\n", \
336 m1, a##_start_block, a##_end_block, \
337 m2, b##_start_block, b##_end_block); \
338 if (a##_end_block < a##_start_block) \
339 printf("Invalid start/end block # for %s\n", m1); \
340 if (b##_end_block < b##_start_block) \
341 printf("Invalid start/end block # for %s\n", m2); \
342 if (chk_overlap(a, b)) { \
343 printf("%s blocks %lu..%lu overlap %s in blocks %lu..%lu!\n", \
344 m1, a##_start_block, a##_end_block, \
345 m2, b##_start_block, b##_end_block); \
350 static int tx28_prog_uboot(void *addr, int start_block, int skip,
351 size_t size, size_t max_len)
354 nand_erase_options_t erase_opts = { 0, };
356 size_t prg_length = max_len - skip * mtd->erasesize;
357 int prg_start = (start_block + skip) * mtd->erasesize;
359 erase_opts.offset = start_block * mtd->erasesize;
360 erase_opts.length = max_len;
361 erase_opts.quiet = 1;
363 printf("Erasing flash @ %08llx..%08llx\n", erase_opts.offset,
364 erase_opts.offset + erase_opts.length - 1);
366 ret = nand_erase_opts(mtd, &erase_opts);
368 printf("Failed to erase flash: %d\n", ret);
373 printf("Programming flash @ %08x..%08x from %p\n",
374 prg_start, prg_start + size - 1, addr);
377 ret = nand_write_skip_bad(mtd, prg_start, &actual, NULL,
378 prg_length, addr, 0);
380 printf("Failed to program flash: %d\n", ret);
384 printf("Could only write %u of %u bytes\n", actual, size);
391 #ifdef CONFIG_ENV_IS_IN_NAND
392 #ifndef CONFIG_ENV_OFFSET_REDUND
393 #define TOTAL_ENV_SIZE CONFIG_ENV_RANGE
395 #define TOTAL_ENV_SIZE (CONFIG_ENV_RANGE * 2)
399 int do_update(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
402 const unsigned long fcb_start_block = 0, fcb_end_block = 0;
403 int erase_size = mtd->erasesize;
409 struct mx28_fcb *fcb;
410 unsigned long mtd_num_blocks = lldiv(mtd->size, mtd->erasesize);
411 #ifdef CONFIG_ENV_IS_IN_NAND
412 unsigned long env_start_block = CONFIG_ENV_OFFSET / mtd->erasesize;
413 unsigned long env_end_block = env_start_block +
414 DIV_ROUND_UP(TOTAL_ENV_SIZE, mtd->erasesize) - 1;
418 unsigned long fw1_start_block = 0, fw1_end_block;
419 unsigned long fw2_start_block = 0, fw2_end_block;
420 unsigned long fw_num_blocks;
421 int fw1_skip, fw2_skip;
422 unsigned long extra_blocks = 0;
423 u64 max_len1, max_len2;
424 struct mtd_device *dev;
425 struct part_info *part_info;
426 struct part_info *redund_part_info;
427 const char *uboot_part = "u-boot";
428 const char *redund_part = NULL;
432 ret = mtdparts_init();
437 for (optind = 1; optind < argc; optind++) {
440 if (strcmp(argv[optind], "-f") == 0) {
441 if (optind >= argc - 1) {
442 printf("Option %s requires an argument\n",
447 fw1_start_block = simple_strtoul(argv[optind], &endp, 0);
449 uboot_part = argv[optind];
453 if (fw1_start_block >= mtd_num_blocks) {
454 printf("Block number %lu is out of range: 0..%lu\n",
455 fw1_start_block, mtd_num_blocks - 1);
458 } else if (strcmp(argv[optind], "-r") == 0) {
460 if (optind < argc - 1 && argv[optind + 1][0] != '-') {
462 fw2_start_block = simple_strtoul(argv[optind],
465 redund_part = argv[optind];
468 if (fw2_start_block >= mtd_num_blocks) {
469 printf("Block number %lu is out of range: 0..%lu\n",
475 } else if (strcmp(argv[optind], "-e") == 0) {
476 if (optind >= argc - 1) {
477 printf("Option %s requires an argument\n",
482 extra_blocks = simple_strtoul(argv[optind], NULL, 0);
483 if (extra_blocks >= mtd_num_blocks) {
484 printf("Extra block count %lu is out of range: 0..%lu\n",
489 } else if (strcmp(argv[optind], "-n") == 0) {
491 } else if (argv[optind][0] == '-') {
492 printf("Unrecognized option %s\n", argv[optind]);
499 load_addr = getenv("fileaddr");
500 file_size = getenv("filesize");
502 if (argc - optind < 1 && load_addr == NULL) {
503 printf("Load address not specified\n");
506 if (argc - optind < 2 && file_size == NULL) {
508 printf("WARNING: Image size not specified; overwriting whole '%s' partition\n",
510 printf("This will only work, if there are no bad blocks inside this partition!\n");
512 printf("ERROR: Image size must be specified\n");
518 addr = (void *)simple_strtoul(argv[optind], NULL, 16);
523 size = simple_strtoul(argv[optind], NULL, 16);
526 if (load_addr != NULL) {
527 addr = (void *)simple_strtoul(load_addr, NULL, 16);
528 printf("Using default load address %p\n", addr);
530 if (file_size != NULL) {
531 size = simple_strtoul(file_size, NULL, 16);
532 printf("Using default file size %08x\n", size);
535 fw_num_blocks = DIV_ROUND_UP(size, mtd->erasesize);
540 ret = find_dev_and_part(uboot_part, &dev, &part_num,
543 printf("Failed to find '%s' partition: %d\n",
547 fw1_start_block = lldiv(part_info->offset, mtd->erasesize);
548 max_len1 = part_info->size;
550 fw_num_blocks = lldiv(max_len1, mtd->erasesize);
552 max_len1 = (u64)(fw_num_blocks + extra_blocks) * mtd->erasesize;
556 ret = find_dev_and_part(redund_part, &dev, &redund_part_num,
559 printf("Failed to find '%s' partition: %d\n",
563 fw2_start_block = lldiv(redund_part_info->offset, mtd->erasesize);
564 max_len2 = redund_part_info->size;
565 if (fw2_start_block == fcb_start_block) {
567 max_len2 -= mtd->erasesize;
570 fw_num_blocks = lldiv(max_len2, mtd->erasesize);
571 } else if (fw2_set) {
572 max_len2 = (u64)(fw_num_blocks + extra_blocks) * mtd->erasesize;
577 fw1_skip = find_contig_space(fw1_start_block, fw_num_blocks,
578 lldiv(max_len1, mtd->erasesize));
580 printf("Could not find %lu contiguous good blocks for fw image in blocks %lu..%llu\n",
581 fw_num_blocks, fw1_start_block,
582 fw1_start_block + lldiv(max_len1, mtd->erasesize) - 1);
584 #ifdef CONFIG_ENV_IS_IN_NAND
585 if (part_info->offset <= CONFIG_ENV_OFFSET + TOTAL_ENV_SIZE) {
586 printf("Use a different partition\n");
588 printf("Increase the size of the '%s' partition\n",
592 printf("Increase the size of the '%s' partition\n",
596 printf("Increase the number of spare blocks to use with the '-e' option\n");
601 fw1_end_block = fw1_start_block + fw_num_blocks + extra_blocks - 1;
603 fw1_end_block = fw1_start_block + fw_num_blocks + fw1_skip - 1;
605 if (fw2_set && fw2_start_block == 0)
606 fw2_start_block = fw1_end_block + 1;
607 if (fw2_start_block > 0) {
608 fw2_skip = find_contig_space(fw2_start_block, fw_num_blocks,
609 lldiv(max_len2, mtd->erasesize));
611 printf("Could not find %lu contiguous good blocks for redundant fw image in blocks %lu..%llu\n",
612 fw_num_blocks, fw2_start_block,
613 fw2_start_block + lldiv(max_len2, mtd->erasesize) - 1);
615 printf("Increase the size of the '%s' partition or use a different partition\n",
618 printf("Increase the number of spare blocks to use with the '-e' option\n");
626 fw2_end_block = fw2_start_block + fw_num_blocks + extra_blocks - 1;
628 fw2_end_block = fw2_start_block + fw_num_blocks + fw2_skip - 1;
630 #ifdef CONFIG_ENV_IS_IN_NAND
631 fail_if_overlap(fcb, env, "FCB", "Environment");
632 fail_if_overlap(fw1, env, "FW1", "Environment");
634 fail_if_overlap(fcb, fw1, "FCB", "FW1");
636 fail_if_overlap(fcb, fw2, "FCB", "FW2");
637 #ifdef CONFIG_ENV_IS_IN_NAND
638 fail_if_overlap(fw2, env, "FW2", "Environment");
640 fail_if_overlap(fw1, fw2, "FW1", "FW2");
642 fw1_start_block += fw1_skip;
643 fw2_start_block += fw2_skip;
645 buf = memalign(SZ_128K, erase_size);
647 printf("Failed to allocate buffer\n");
651 fcb = create_fcb(buf, fw1_start_block,
652 fw2_start_block, fw_num_blocks);
654 printf("Failed to initialize FCB: %ld\n", PTR_ERR(fcb));
658 encode_hamming_13_8(fcb, (void *)fcb + 512, 512);
660 ret = write_fcb(buf, fcb_start_block);
662 printf("Failed to write FCB to block %lu\n", fcb_start_block);
666 printf("Programming U-Boot image from %p to block %lu @ %08llx\n",
667 addr, fw1_start_block, (u64)fw1_start_block * mtd->erasesize);
668 ret = tx28_prog_uboot(addr, fw1_start_block, fw1_skip, size,
671 if (ret || fw2_start_block == 0)
674 printf("Programming redundant U-Boot image to block %lu @ %08llx\n",
675 fw2_start_block, (u64)fw2_start_block * mtd->erasesize);
676 ret = tx28_prog_uboot(addr, fw2_start_block, fw2_skip, fw_num_blocks,
683 U_BOOT_CMD(romupdate, 11, 0, do_update,
684 "Creates an FCB data structure and writes an U-Boot image to flash",
685 "[-f {<part>|block#}] [-r [{<part>|block#}]] [-e #] [<address>] [<length>]\n"
686 "\t-f <part>\twrite bootloader image to partition <part>\n"
687 "\t-f #\t\twrite bootloader image at block # (decimal)\n"
688 "\t-r\t\twrite redundant bootloader image at next free block after first image\n"
689 "\t-r <part>\twrite redundant bootloader image to partition <part>\n"
690 "\t-r #\t\twrite redundant bootloader image at block # (decimal)\n"
691 "\t-e #\t\tspecify number of redundant blocks per boot loader image\n"
692 "\t\t\t(only valid if -f or -r specify a flash address rather than a partition name)\n"
693 "\t-n\t\tshow what would be done without actually updating the flash\n"
694 "\t<address>\tRAM address of bootloader image (default: ${fileaddr})\n"
695 "\t<length>\tlength of bootloader image in RAM (default: ${filesize})"