Lines Matching +full:avg +full:- +full:pos +full:- +full:strength

1 // SPDX-License-Identifier: GPL-2.0-or-later
142 MODULE_PARM_DESC(bus_width, "Chip's bus width (8- or 16-bit)");
143 MODULE_PARM_DESC(do_delays, "Simulate NAND delays using busy-waits if not zero");
165 "be correctable in 512-byte blocks");
182 /* Busy-wait delay macros (microseconds, milliseconds) */
189 #define NS_IS_INITIALIZED(ns) ((ns)->geom.totsz != 0)
192 #define NS_STATUS_OK(ns) (NAND_STATUS_READY | (NAND_STATUS_WP * ((ns)->lines.wp == 0)))
199 (((ns)->regs.row * (ns)->geom.pgszoob) + (ns)->regs.column)
202 #define NS_RAW_OFFSET_OOB(ns) (NS_RAW_OFFSET(ns) + ns->geom.pgsz)
255 #define OPT_PAGE512 0x00000002 /* 512-byte page chips */
256 #define OPT_PAGE2048 0x00000008 /* 2048-byte page chips */
257 #define OPT_PAGE512_8BIT 0x00000040 /* 512-byte page chips with 8-bit bus width */
258 #define OPT_PAGE4096 0x00000080 /* 4096-byte page chips */
259 #define OPT_LARGEPAGE (OPT_PAGE2048 | OPT_PAGE4096) /* 2048 & 4096-byte page chips */
260 #define OPT_SMALLPAGE (OPT_PAGE512) /* 512-byte page chips */
268 * (which is only valid for 512-byte pages).
280 uint16_t *word; /* for 16-bit word access */
439 unsigned long wmin = -1, wmax = 0, avg; in ns_show() local
468 avg = tot / wear_eb_count; in ns_show()
473 seq_printf(m, "Average number of erases: %lu\n", avg); in ns_show()
477 unsigned long from = (i ? decile_max[i - 1] + 1 : 0); in ns_show()
491 * ns_debugfs_create - initialize debugfs
499 struct dentry *root = nsmtd->dbg.dfs_dir; in ns_debugfs_create()
512 ns->dent = debugfs_create_file("nandsim_wear_report", 0400, root, ns, in ns_debugfs_create()
514 if (IS_ERR_OR_NULL(ns->dent)) { in ns_debugfs_create()
516 return -1; in ns_debugfs_create()
524 debugfs_remove_recursive(ns->dent); in ns_debugfs_remove()
531 * RETURNS: 0 if success, -ENOMEM if memory alloc fails.
542 if (!(cfile->f_mode & FMODE_CAN_READ)) { in ns_alloc_device()
544 err = -EINVAL; in ns_alloc_device()
547 if (!(cfile->f_mode & FMODE_CAN_WRITE)) { in ns_alloc_device()
549 err = -EINVAL; in ns_alloc_device()
552 ns->pages_written = in ns_alloc_device()
554 BITS_TO_LONGS(ns->geom.pgnum))); in ns_alloc_device()
555 if (!ns->pages_written) { in ns_alloc_device()
557 err = -ENOMEM; in ns_alloc_device()
560 ns->file_buf = kmalloc(ns->geom.pgszoob, GFP_KERNEL); in ns_alloc_device()
561 if (!ns->file_buf) { in ns_alloc_device()
563 err = -ENOMEM; in ns_alloc_device()
566 ns->cfile = cfile; in ns_alloc_device()
571 vfree(ns->pages_written); in ns_alloc_device()
578 ns->pages = vmalloc(array_size(sizeof(union ns_mem), ns->geom.pgnum)); in ns_alloc_device()
579 if (!ns->pages) { in ns_alloc_device()
581 return -ENOMEM; in ns_alloc_device()
583 for (i = 0; i < ns->geom.pgnum; i++) { in ns_alloc_device()
584 ns->pages[i].byte = NULL; in ns_alloc_device()
586 ns->nand_pages_slab = kmem_cache_create("nandsim", in ns_alloc_device()
587 ns->geom.pgszoob, 0, 0, NULL); in ns_alloc_device()
588 if (!ns->nand_pages_slab) { in ns_alloc_device()
590 err = -ENOMEM; in ns_alloc_device()
597 vfree(ns->pages); in ns_alloc_device()
609 if (ns->cfile) { in ns_free_device()
610 kfree(ns->file_buf); in ns_free_device()
611 vfree(ns->pages_written); in ns_free_device()
612 filp_close(ns->cfile, NULL); in ns_free_device()
616 if (ns->pages) { in ns_free_device()
617 for (i = 0; i < ns->geom.pgnum; i++) { in ns_free_device()
618 if (ns->pages[i].byte) in ns_free_device()
619 kmem_cache_free(ns->nand_pages_slab, in ns_free_device()
620 ns->pages[i].byte); in ns_free_device()
622 kmem_cache_destroy(ns->nand_pages_slab); in ns_free_device()
623 vfree(ns->pages); in ns_free_device()
635 * RETURNS: 0 if success, -ERRNO if failure.
647 return -EIO; in ns_init()
651 ns->busw = chip->options & NAND_BUSWIDTH_16 ? 16 : 8; in ns_init()
652 ns->geom.totsz = mtd->size; in ns_init()
653 ns->geom.pgsz = mtd->writesize; in ns_init()
654 ns->geom.oobsz = mtd->oobsize; in ns_init()
655 ns->geom.secsz = mtd->erasesize; in ns_init()
656 ns->geom.pgszoob = ns->geom.pgsz + ns->geom.oobsz; in ns_init()
657 ns->geom.pgnum = div_u64(ns->geom.totsz, ns->geom.pgsz); in ns_init()
658 ns->geom.totszoob = ns->geom.totsz + (uint64_t)ns->geom.pgnum * ns->geom.oobsz; in ns_init()
659 ns->geom.secshift = ffs(ns->geom.secsz) - 1; in ns_init()
660 ns->geom.pgshift = chip->page_shift; in ns_init()
661 ns->geom.pgsec = ns->geom.secsz / ns->geom.pgsz; in ns_init()
662 ns->geom.secszoob = ns->geom.secsz + ns->geom.oobsz * ns->geom.pgsec; in ns_init()
663 ns->options = 0; in ns_init()
665 if (ns->geom.pgsz == 512) { in ns_init()
666 ns->options |= OPT_PAGE512; in ns_init()
667 if (ns->busw == 8) in ns_init()
668 ns->options |= OPT_PAGE512_8BIT; in ns_init()
669 } else if (ns->geom.pgsz == 2048) { in ns_init()
670 ns->options |= OPT_PAGE2048; in ns_init()
671 } else if (ns->geom.pgsz == 4096) { in ns_init()
672 ns->options |= OPT_PAGE4096; in ns_init()
674 NS_ERR("init_nandsim: unknown page size %u\n", ns->geom.pgsz); in ns_init()
675 return -EIO; in ns_init()
678 if (ns->options & OPT_SMALLPAGE) { in ns_init()
679 if (ns->geom.totsz <= (32 << 20)) { in ns_init()
680 ns->geom.pgaddrbytes = 3; in ns_init()
681 ns->geom.secaddrbytes = 2; in ns_init()
683 ns->geom.pgaddrbytes = 4; in ns_init()
684 ns->geom.secaddrbytes = 3; in ns_init()
687 if (ns->geom.totsz <= (128 << 20)) { in ns_init()
688 ns->geom.pgaddrbytes = 4; in ns_init()
689 ns->geom.secaddrbytes = 2; in ns_init()
691 ns->geom.pgaddrbytes = 5; in ns_init()
692 ns->geom.secaddrbytes = 3; in ns_init()
697 if (parts_num > ARRAY_SIZE(ns->partitions)) { in ns_init()
699 return -EINVAL; in ns_init()
701 remains = ns->geom.totsz; in ns_init()
704 uint64_t part_sz = (uint64_t)parts[i] * ns->geom.secsz; in ns_init()
708 return -EINVAL; in ns_init()
710 ns->partitions[i].name = ns_get_partition_name(i); in ns_init()
711 if (!ns->partitions[i].name) { in ns_init()
713 return -ENOMEM; in ns_init()
715 ns->partitions[i].offset = next_offset; in ns_init()
716 ns->partitions[i].size = part_sz; in ns_init()
717 next_offset += ns->partitions[i].size; in ns_init()
718 remains -= ns->partitions[i].size; in ns_init()
720 ns->nbparts = parts_num; in ns_init()
722 if (parts_num + 1 > ARRAY_SIZE(ns->partitions)) { in ns_init()
724 ret = -EINVAL; in ns_init()
727 ns->partitions[i].name = ns_get_partition_name(i); in ns_init()
728 if (!ns->partitions[i].name) { in ns_init()
730 ret = -ENOMEM; in ns_init()
733 ns->partitions[i].offset = next_offset; in ns_init()
734 ns->partitions[i].size = remains; in ns_init()
735 ns->nbparts += 1; in ns_init()
738 if (ns->busw == 16) in ns_init()
739 NS_WARN("16-bit flashes support wasn't tested\n"); in ns_init()
742 (unsigned long long)ns->geom.totsz >> 20); in ns_init()
743 printk("page size: %u bytes\n", ns->geom.pgsz); in ns_init()
744 printk("OOB area size: %u bytes\n", ns->geom.oobsz); in ns_init()
745 printk("sector size: %u KiB\n", ns->geom.secsz >> 10); in ns_init()
746 printk("pages number: %u\n", ns->geom.pgnum); in ns_init()
747 printk("pages per sector: %u\n", ns->geom.pgsec); in ns_init()
748 printk("bus width: %u\n", ns->busw); in ns_init()
749 printk("bits in sector size: %u\n", ns->geom.secshift); in ns_init()
750 printk("bits in page size: %u\n", ns->geom.pgshift); in ns_init()
751 printk("bits in OOB size: %u\n", ffs(ns->geom.oobsz) - 1); in ns_init()
753 (unsigned long long)ns->geom.totszoob >> 10); in ns_init()
754 printk("page address bytes: %u\n", ns->geom.pgaddrbytes); in ns_init()
755 printk("sector address bytes: %u\n", ns->geom.secaddrbytes); in ns_init()
756 printk("options: %#x\n", ns->options); in ns_init()
763 ns->buf.byte = kmalloc(ns->geom.pgszoob, GFP_KERNEL); in ns_init()
764 if (!ns->buf.byte) { in ns_init()
766 ns->geom.pgszoob); in ns_init()
767 ret = -ENOMEM; in ns_init()
770 memset(ns->buf.byte, 0xFF, ns->geom.pgszoob); in ns_init()
777 for (i = 0; i < ARRAY_SIZE(ns->partitions); ++i) in ns_init()
778 kfree(ns->partitions[i].name); in ns_init()
790 for (i = 0; i < ARRAY_SIZE(ns->partitions); ++i) in ns_free()
791 kfree(ns->partitions[i].name); in ns_free()
793 kfree(ns->buf.byte); in ns_free()
814 return -EINVAL; in ns_parse_badblocks()
816 offset = (loff_t)erase_block_no * ns->geom.secsz; in ns_parse_badblocks()
819 return -EINVAL; in ns_parse_badblocks()
843 return -EINVAL; in ns_parse_weakblocks()
855 return -ENOMEM; in ns_parse_weakblocks()
857 wb->erase_block_no = erase_block_no; in ns_parse_weakblocks()
858 wb->max_erases = max_erases; in ns_parse_weakblocks()
859 list_add(&wb->list, &weak_blocks); in ns_parse_weakblocks()
869 if (wb->erase_block_no == erase_block_no) { in ns_erase_error()
870 if (wb->erases_done >= wb->max_erases) in ns_erase_error()
872 wb->erases_done += 1; in ns_erase_error()
894 return -EINVAL; in ns_parse_weakpages()
906 return -ENOMEM; in ns_parse_weakpages()
908 wp->page_no = page_no; in ns_parse_weakpages()
909 wp->max_writes = max_writes; in ns_parse_weakpages()
910 list_add(&wp->list, &weak_pages); in ns_parse_weakpages()
920 if (wp->page_no == page_no) { in ns_write_error()
921 if (wp->writes_done >= wp->max_writes) in ns_write_error()
923 wp->writes_done += 1; in ns_write_error()
945 return -EINVAL; in ns_parse_gravepages()
957 return -ENOMEM; in ns_parse_gravepages()
959 gp->page_no = page_no; in ns_parse_gravepages()
960 gp->max_reads = max_reads; in ns_parse_gravepages()
961 list_add(&gp->list, &grave_pages); in ns_parse_gravepages()
971 if (gp->page_no == page_no) { in ns_read_error()
972 if (gp->reads_done >= gp->max_reads) in ns_read_error()
974 gp->reads_done += 1; in ns_read_error()
984 wear_eb_count = div_u64(mtd->size, mtd->erasesize); in ns_setup_wear_reporting()
988 return -ENOMEM; in ns_setup_wear_reporting()
993 return -ENOMEM; in ns_setup_wear_reporting()
1146 if (ns->regs.count < (ns->geom.pgaddrbytes - ns->geom.secaddrbytes)) in ns_accept_addr_byte()
1147 ns->regs.column |= (byte << 8 * ns->regs.count); in ns_accept_addr_byte()
1149 ns->regs.row |= (byte << 8 * (ns->regs.count - in ns_accept_addr_byte()
1150 ns->geom.pgaddrbytes + in ns_accept_addr_byte()
1151 ns->geom.secaddrbytes)); in ns_accept_addr_byte()
1165 ns->state = STATE_READY; in ns_switch_to_ready_state()
1166 ns->nxstate = STATE_UNKNOWN; in ns_switch_to_ready_state()
1167 ns->op = NULL; in ns_switch_to_ready_state()
1168 ns->npstates = 0; in ns_switch_to_ready_state()
1169 ns->stateidx = 0; in ns_switch_to_ready_state()
1170 ns->regs.num = 0; in ns_switch_to_ready_state()
1171 ns->regs.count = 0; in ns_switch_to_ready_state()
1172 ns->regs.off = 0; in ns_switch_to_ready_state()
1173 ns->regs.row = 0; in ns_switch_to_ready_state()
1174 ns->regs.column = 0; in ns_switch_to_ready_state()
1175 ns->regs.status = status; in ns_switch_to_ready_state()
1184 * correspondent states chain. In this case ns->npstates = 0;
1188 * case the ns->pstates[] array contains previous states.
1192 * ns->pstates[0], ... ns->pstates[ns->npstates], ns->state
1195 * ns->ops, ns->state, ns->nxstate are initialized, ns->npstate is
1199 * ns->pstates.
1205 * ns->pstates[0], ... ns->pstates[ns->npstates], <address input>
1216 * RETURNS: -2 - no matched operations found.
1217 * -1 - several matches.
1218 * 0 - operation is found.
1229 if (!(ns->options & ops[i].reqopts)) in ns_find_operation()
1234 if (!(ops[i].states[ns->npstates] & STATE_ADDR_MASK)) in ns_find_operation()
1237 if (NS_STATE(ns->state) != NS_STATE(ops[i].states[ns->npstates])) in ns_find_operation()
1241 for (j = 0; j < ns->npstates; j++) in ns_find_operation()
1242 if (NS_STATE(ops[i].states[j]) != NS_STATE(ns->pstates[j]) in ns_find_operation()
1243 && (ns->options & ops[idx].reqopts)) { in ns_find_operation()
1256 ns->op = &ops[idx].states[0]; in ns_find_operation()
1263 * state must be the next state (ns->nxstate). in ns_find_operation()
1265 ns->stateidx = ns->npstates - 1; in ns_find_operation()
1267 ns->stateidx = ns->npstates; in ns_find_operation()
1269 ns->npstates = 0; in ns_find_operation()
1270 ns->state = ns->op[ns->stateidx]; in ns_find_operation()
1271 ns->nxstate = ns->op[ns->stateidx + 1]; in ns_find_operation()
1273 idx, ns_get_state_name(ns->state), in ns_find_operation()
1274 ns_get_state_name(ns->nxstate)); in ns_find_operation()
1280 if (ns->npstates != 0) { in ns_find_operation()
1282 ns_get_state_name(ns->state)); in ns_find_operation()
1283 ns->npstates = 0; in ns_find_operation()
1289 return -2; in ns_find_operation()
1295 return -2; in ns_find_operation()
1300 ns->pstates[ns->npstates++] = ns->state; in ns_find_operation()
1302 return -1; in ns_find_operation()
1309 for (i = 0; i < ns->held_cnt; i++) in ns_put_pages()
1310 put_page(ns->held_pages[i]); in ns_put_pages()
1315 loff_t pos) in ns_get_pages() argument
1319 struct address_space *mapping = file->f_mapping; in ns_get_pages()
1321 start_index = pos >> PAGE_SHIFT; in ns_get_pages()
1322 end_index = (pos + count - 1) >> PAGE_SHIFT; in ns_get_pages()
1323 if (end_index - start_index + 1 > NS_MAX_HELD_PAGES) in ns_get_pages()
1324 return -EINVAL; in ns_get_pages()
1325 ns->held_cnt = 0; in ns_get_pages()
1331 write_inode_now(mapping->host, 1); in ns_get_pages()
1336 return -ENOMEM; in ns_get_pages()
1340 ns->held_pages[ns->held_cnt++] = page; in ns_get_pages()
1346 size_t count, loff_t pos) in ns_read_file() argument
1352 err = ns_get_pages(ns, file, count, pos); in ns_read_file()
1356 tx = kernel_read(file, buf, count, &pos); in ns_read_file()
1363 size_t count, loff_t pos) in ns_write_file() argument
1369 err = ns_get_pages(ns, file, count, pos); in ns_write_file()
1373 tx = kernel_write(file, buf, count, &pos); in ns_write_file()
1384 return &(ns->pages[ns->regs.row]); in NS_GET_PAGE()
1392 return NS_GET_PAGE(ns)->byte + ns->regs.column + ns->regs.off; in NS_PAGE_BYTE_OFF()
1397 unsigned int page_no = ns->regs.row; in ns_do_read_error()
1400 prandom_bytes(ns->buf.byte, num); in ns_do_read_error()
1413 while (flips--) { in ns_do_bit_flips()
1414 int pos = prandom_u32() % (num * 8); in ns_do_bit_flips() local
1415 ns->buf.byte[pos / 8] ^= (1 << (pos % 8)); in ns_do_bit_flips()
1418 pos, ns->regs.row, ns->regs.column + ns->regs.off, in ns_do_bit_flips()
1419 nsmtd->ecc_stats.corrected, nsmtd->ecc_stats.failed); in ns_do_bit_flips()
1431 if (ns->cfile) { in ns_read_page()
1432 if (!test_bit(ns->regs.row, ns->pages_written)) { in ns_read_page()
1433 NS_DBG("read_page: page %d not written\n", ns->regs.row); in ns_read_page()
1434 memset(ns->buf.byte, 0xFF, num); in ns_read_page()
1436 loff_t pos; in ns_read_page() local
1440 ns->regs.row, ns->regs.column + ns->regs.off); in ns_read_page()
1443 pos = (loff_t)NS_RAW_OFFSET(ns) + ns->regs.off; in ns_read_page()
1444 tx = ns_read_file(ns, ns->cfile, ns->buf.byte, num, in ns_read_page()
1445 pos); in ns_read_page()
1447 NS_ERR("read_page: read error for page %d ret %ld\n", ns->regs.row, (long)tx); in ns_read_page()
1456 if (mypage->byte == NULL) { in ns_read_page()
1457 NS_DBG("read_page: page %d not allocated\n", ns->regs.row); in ns_read_page()
1458 memset(ns->buf.byte, 0xFF, num); in ns_read_page()
1461 ns->regs.row, ns->regs.column + ns->regs.off); in ns_read_page()
1464 memcpy(ns->buf.byte, NS_PAGE_BYTE_OFF(ns), num); in ns_read_page()
1477 if (ns->cfile) { in ns_erase_sector()
1478 for (i = 0; i < ns->geom.pgsec; i++) in ns_erase_sector()
1479 if (__test_and_clear_bit(ns->regs.row + i, in ns_erase_sector()
1480 ns->pages_written)) { in ns_erase_sector()
1481 NS_DBG("erase_sector: freeing page %d\n", ns->regs.row + i); in ns_erase_sector()
1487 for (i = 0; i < ns->geom.pgsec; i++) { in ns_erase_sector()
1488 if (mypage->byte != NULL) { in ns_erase_sector()
1489 NS_DBG("erase_sector: freeing page %d\n", ns->regs.row+i); in ns_erase_sector()
1490 kmem_cache_free(ns->nand_pages_slab, mypage->byte); in ns_erase_sector()
1491 mypage->byte = NULL; in ns_erase_sector()
1506 if (ns->cfile) { in ns_prog_page()
1511 NS_DBG("prog_page: writing page %d\n", ns->regs.row); in ns_prog_page()
1512 pg_off = ns->file_buf + ns->regs.column + ns->regs.off; in ns_prog_page()
1513 off = (loff_t)NS_RAW_OFFSET(ns) + ns->regs.off; in ns_prog_page()
1514 if (!test_bit(ns->regs.row, ns->pages_written)) { in ns_prog_page()
1516 memset(ns->file_buf, 0xff, ns->geom.pgszoob); in ns_prog_page()
1519 tx = ns_read_file(ns, ns->cfile, pg_off, num, off); in ns_prog_page()
1521 NS_ERR("prog_page: read error for page %d ret %ld\n", ns->regs.row, (long)tx); in ns_prog_page()
1522 return -1; in ns_prog_page()
1526 pg_off[i] &= ns->buf.byte[i]; in ns_prog_page()
1528 loff_t pos = (loff_t)ns->regs.row * ns->geom.pgszoob; in ns_prog_page() local
1529 tx = ns_write_file(ns, ns->cfile, ns->file_buf, in ns_prog_page()
1530 ns->geom.pgszoob, pos); in ns_prog_page()
1531 if (tx != ns->geom.pgszoob) { in ns_prog_page()
1532 NS_ERR("prog_page: write error for page %d ret %ld\n", ns->regs.row, (long)tx); in ns_prog_page()
1533 return -1; in ns_prog_page()
1535 __set_bit(ns->regs.row, ns->pages_written); in ns_prog_page()
1537 tx = ns_write_file(ns, ns->cfile, pg_off, num, off); in ns_prog_page()
1539 NS_ERR("prog_page: write error for page %d ret %ld\n", ns->regs.row, (long)tx); in ns_prog_page()
1540 return -1; in ns_prog_page()
1547 if (mypage->byte == NULL) { in ns_prog_page()
1548 NS_DBG("prog_page: allocating page %d\n", ns->regs.row); in ns_prog_page()
1555 mypage->byte = kmem_cache_alloc(ns->nand_pages_slab, GFP_NOFS); in ns_prog_page()
1556 if (mypage->byte == NULL) { in ns_prog_page()
1557 NS_ERR("prog_page: error allocating memory for page %d\n", ns->regs.row); in ns_prog_page()
1558 return -1; in ns_prog_page()
1560 memset(mypage->byte, 0xFF, ns->geom.pgszoob); in ns_prog_page()
1565 pg_off[i] &= ns->buf.byte[i]; in ns_prog_page()
1573 * RETURNS: 0 if success, -1 if error.
1578 int busdiv = ns->busw == 8 ? 1 : 2; in ns_do_state_action()
1584 if (action != ACTION_SECERASE && ns->regs.row >= ns->geom.pgnum) { in ns_do_state_action()
1585 NS_WARN("do_state_action: wrong page number (%#x)\n", ns->regs.row); in ns_do_state_action()
1586 return -1; in ns_do_state_action()
1597 if (ns->regs.column >= (ns->geom.pgszoob - ns->regs.off)) { in ns_do_state_action()
1601 num = ns->geom.pgszoob - ns->regs.off - ns->regs.column; in ns_do_state_action()
1605 num, NS_RAW_OFFSET(ns) + ns->regs.off); in ns_do_state_action()
1607 if (ns->regs.off == 0) in ns_do_state_action()
1608 NS_LOG("read page %d\n", ns->regs.row); in ns_do_state_action()
1609 else if (ns->regs.off < ns->geom.pgsz) in ns_do_state_action()
1610 NS_LOG("read page %d (second half)\n", ns->regs.row); in ns_do_state_action()
1612 NS_LOG("read OOB of page %d\n", ns->regs.row); in ns_do_state_action()
1615 NS_UDELAY(input_cycle * ns->geom.pgsz / 1000 / busdiv); in ns_do_state_action()
1624 if (ns->lines.wp) { in ns_do_state_action()
1625 NS_ERR("do_state_action: device is write-protected, ignore sector erase\n"); in ns_do_state_action()
1626 return -1; in ns_do_state_action()
1629 if (ns->regs.row >= ns->geom.pgnum - ns->geom.pgsec in ns_do_state_action()
1630 || (ns->regs.row & ~(ns->geom.secsz - 1))) { in ns_do_state_action()
1631 NS_ERR("do_state_action: wrong sector address (%#x)\n", ns->regs.row); in ns_do_state_action()
1632 return -1; in ns_do_state_action()
1635 ns->regs.row = (ns->regs.row << in ns_do_state_action()
1636 8 * (ns->geom.pgaddrbytes - ns->geom.secaddrbytes)) | ns->regs.column; in ns_do_state_action()
1637 ns->regs.column = 0; in ns_do_state_action()
1639 erase_block_no = ns->regs.row >> (ns->geom.secshift - ns->geom.pgshift); in ns_do_state_action()
1642 ns->regs.row, NS_RAW_OFFSET(ns)); in ns_do_state_action()
1654 return -1; in ns_do_state_action()
1661 * Program page - move internal buffer data to the page. in ns_do_state_action()
1664 if (ns->lines.wp) { in ns_do_state_action()
1665 NS_WARN("do_state_action: device is write-protected, programm\n"); in ns_do_state_action()
1666 return -1; in ns_do_state_action()
1669 num = ns->geom.pgszoob - ns->regs.off - ns->regs.column; in ns_do_state_action()
1670 if (num != ns->regs.count) { in ns_do_state_action()
1672 ns->regs.count, num); in ns_do_state_action()
1673 return -1; in ns_do_state_action()
1676 if (ns_prog_page(ns, num) == -1) in ns_do_state_action()
1677 return -1; in ns_do_state_action()
1679 page_no = ns->regs.row; in ns_do_state_action()
1682 num, ns->regs.row, ns->regs.column, NS_RAW_OFFSET(ns) + ns->regs.off); in ns_do_state_action()
1683 NS_LOG("programm page %d\n", ns->regs.row); in ns_do_state_action()
1686 NS_UDELAY(output_cycle * ns->geom.pgsz / 1000 / busdiv); in ns_do_state_action()
1690 return -1; in ns_do_state_action()
1697 ns->regs.off = 0; in ns_do_state_action()
1701 if (!(ns->options & OPT_PAGE512_8BIT)) { in ns_do_state_action()
1702 NS_ERR("do_state_action: BUG! can't skip half of page for non-512" in ns_do_state_action()
1704 return -1; in ns_do_state_action()
1706 NS_DBG("do_state_action: set internal offset to %d\n", ns->geom.pgsz/2); in ns_do_state_action()
1707 ns->regs.off = ns->geom.pgsz/2; in ns_do_state_action()
1711 NS_DBG("do_state_action: set internal offset to %d\n", ns->geom.pgsz); in ns_do_state_action()
1712 ns->regs.off = ns->geom.pgsz; in ns_do_state_action()
1727 if (ns->op) { in ns_switch_state()
1733 ns->stateidx += 1; in ns_switch_state()
1734 ns->state = ns->nxstate; in ns_switch_state()
1735 ns->nxstate = ns->op[ns->stateidx + 1]; in ns_switch_state()
1739 ns_get_state_name(ns->state), in ns_switch_state()
1740 ns_get_state_name(ns->nxstate)); in ns_switch_state()
1743 if ((ns->state & ACTION_MASK) && in ns_switch_state()
1744 ns_do_state_action(ns, ns->state) < 0) { in ns_switch_state()
1759 ns->state = ns_get_state_by_command(ns->regs.command); in ns_switch_state()
1766 if ((ns->state & ACTION_MASK) && in ns_switch_state()
1767 ns_do_state_action(ns, ns->state) < 0) { in ns_switch_state()
1774 if ((ns->nxstate & STATE_ADDR_MASK) && ns->busw == 16) { in ns_switch_state()
1776 ns->regs.column <<= 1; in ns_switch_state()
1779 if (NS_STATE(ns->nxstate) == STATE_READY) { in ns_switch_state()
1787 if ((ns->state & (STATE_DATAIN_MASK | STATE_DATAOUT_MASK)) in ns_switch_state()
1788 && ns->regs.count != ns->regs.num) { in ns_switch_state()
1790 ns->regs.num - ns->regs.count); in ns_switch_state()
1799 } else if (ns->nxstate & (STATE_DATAIN_MASK | STATE_DATAOUT_MASK)) { in ns_switch_state()
1804 ns->state = ns->nxstate; in ns_switch_state()
1805 ns->nxstate = ns->op[++ns->stateidx + 1]; in ns_switch_state()
1806 ns->regs.num = ns->regs.count = 0; in ns_switch_state()
1810 ns_get_state_name(ns->state), in ns_switch_state()
1811 ns_get_state_name(ns->nxstate)); in ns_switch_state()
1817 switch (NS_STATE(ns->state)) { in ns_switch_state()
1820 ns->regs.num = ns->geom.pgszoob - ns->regs.off - ns->regs.column; in ns_switch_state()
1824 ns->regs.num = ns->geom.idbytes; in ns_switch_state()
1828 ns->regs.count = ns->regs.num = 0; in ns_switch_state()
1835 } else if (ns->nxstate & STATE_ADDR_MASK) { in ns_switch_state()
1841 ns->regs.count = 0; in ns_switch_state()
1843 switch (NS_STATE(ns->nxstate)) { in ns_switch_state()
1845 ns->regs.num = ns->geom.pgaddrbytes; in ns_switch_state()
1849 ns->regs.num = ns->geom.secaddrbytes; in ns_switch_state()
1853 ns->regs.num = 1; in ns_switch_state()
1858 ns->regs.num = ns->geom.pgaddrbytes - ns->geom.secaddrbytes; in ns_switch_state()
1869 ns->regs.num = 0; in ns_switch_state()
1870 ns->regs.count = 0; in ns_switch_state()
1880 if (!ns->lines.ce) { in ns_nand_read_byte()
1884 if (ns->lines.ale || ns->lines.cle) { in ns_nand_read_byte()
1888 if (!(ns->state & STATE_DATAOUT_MASK)) { in ns_nand_read_byte()
1890 ns_get_state_name(ns->state), (uint)outb); in ns_nand_read_byte()
1895 if (NS_STATE(ns->state) == STATE_DATAOUT_STATUS) { in ns_nand_read_byte()
1896 NS_DBG("read_byte: return %#x status\n", ns->regs.status); in ns_nand_read_byte()
1897 return ns->regs.status; in ns_nand_read_byte()
1901 if (ns->regs.count == ns->regs.num) { in ns_nand_read_byte()
1906 switch (NS_STATE(ns->state)) { in ns_nand_read_byte()
1908 if (ns->busw == 8) { in ns_nand_read_byte()
1909 outb = ns->buf.byte[ns->regs.count]; in ns_nand_read_byte()
1910 ns->regs.count += 1; in ns_nand_read_byte()
1912 outb = (u_char)cpu_to_le16(ns->buf.word[ns->regs.count >> 1]); in ns_nand_read_byte()
1913 ns->regs.count += 2; in ns_nand_read_byte()
1917 NS_DBG("read_byte: read ID byte %d, total = %d\n", ns->regs.count, ns->regs.num); in ns_nand_read_byte()
1918 outb = ns->ids[ns->regs.count]; in ns_nand_read_byte()
1919 ns->regs.count += 1; in ns_nand_read_byte()
1925 if (ns->regs.count == ns->regs.num) { in ns_nand_read_byte()
1928 if (NS_STATE(ns->nxstate) == STATE_READY) in ns_nand_read_byte()
1940 if (!ns->lines.ce) { in ns_nand_write_byte()
1944 if (ns->lines.ale && ns->lines.cle) { in ns_nand_write_byte()
1949 if (ns->lines.cle == 1) { in ns_nand_write_byte()
1966 if (NS_STATE(ns->state) == STATE_DATAOUT_STATUS in ns_nand_write_byte()
1967 || NS_STATE(ns->state) == STATE_DATAOUT) { in ns_nand_write_byte()
1968 int row = ns->regs.row; in ns_nand_write_byte()
1972 ns->regs.row = row; in ns_nand_write_byte()
1976 if (NS_STATE(ns->nxstate) != STATE_UNKNOWN && !(ns->nxstate & STATE_CMD_MASK)) { in ns_nand_write_byte()
1978 if (!(ns->regs.command == NAND_CMD_READID && in ns_nand_write_byte()
1979 NS_STATE(ns->state) == STATE_DATAOUT_ID && ns->regs.count == 2)) { in ns_nand_write_byte()
1987 ns_get_state_name(ns->nxstate)); in ns_nand_write_byte()
1994 ns->regs.command = byte; in ns_nand_write_byte()
1997 } else if (ns->lines.ale == 1) { in ns_nand_write_byte()
2002 if (NS_STATE(ns->nxstate) == STATE_UNKNOWN) { in ns_nand_write_byte()
2009 if ((ns->state & ACTION_MASK) && in ns_nand_write_byte()
2010 ns_do_state_action(ns, ns->state) < 0) { in ns_nand_write_byte()
2016 ns->regs.count = 0; in ns_nand_write_byte()
2017 switch (NS_STATE(ns->nxstate)) { in ns_nand_write_byte()
2019 ns->regs.num = ns->geom.pgaddrbytes; in ns_nand_write_byte()
2022 ns->regs.num = ns->geom.secaddrbytes; in ns_nand_write_byte()
2025 ns->regs.num = 1; in ns_nand_write_byte()
2033 if (!(ns->nxstate & STATE_ADDR_MASK)) { in ns_nand_write_byte()
2035 (uint)byte, ns_get_state_name(ns->nxstate)); in ns_nand_write_byte()
2041 if (ns->regs.count == ns->regs.num) { in ns_nand_write_byte()
2049 ns->regs.count += 1; in ns_nand_write_byte()
2052 (uint)byte, ns->regs.count, ns->regs.num); in ns_nand_write_byte()
2054 if (ns->regs.count == ns->regs.num) { in ns_nand_write_byte()
2055 NS_DBG("address (%#x, %#x) is accepted\n", ns->regs.row, ns->regs.column); in ns_nand_write_byte()
2065 if (!(ns->state & STATE_DATAIN_MASK)) { in ns_nand_write_byte()
2067 (uint)byte, ns_get_state_name(ns->state), in ns_nand_write_byte()
2074 if (ns->regs.count == ns->regs.num) { in ns_nand_write_byte()
2076 ns->regs.num); in ns_nand_write_byte()
2080 if (ns->busw == 8) { in ns_nand_write_byte()
2081 ns->buf.byte[ns->regs.count] = byte; in ns_nand_write_byte()
2082 ns->regs.count += 1; in ns_nand_write_byte()
2084 ns->buf.word[ns->regs.count >> 1] = cpu_to_le16((uint16_t)byte); in ns_nand_write_byte()
2085 ns->regs.count += 2; in ns_nand_write_byte()
2098 if (!(ns->state & STATE_DATAIN_MASK)) { in ns_nand_write_buf()
2100 ns_get_state_name(ns->state)); in ns_nand_write_buf()
2106 if (ns->regs.count + len > ns->regs.num) { in ns_nand_write_buf()
2112 memcpy(ns->buf.byte + ns->regs.count, buf, len); in ns_nand_write_buf()
2113 ns->regs.count += len; in ns_nand_write_buf()
2115 if (ns->regs.count == ns->regs.num) { in ns_nand_write_buf()
2116 NS_DBG("write_buf: %d bytes were written\n", ns->regs.count); in ns_nand_write_buf()
2125 if (!ns->lines.ce) { in ns_nand_read_buf()
2129 if (ns->lines.ale || ns->lines.cle) { in ns_nand_read_buf()
2133 if (!(ns->state & STATE_DATAOUT_MASK)) { in ns_nand_read_buf()
2135 ns_get_state_name(ns->state)); in ns_nand_read_buf()
2139 if (NS_STATE(ns->state) != STATE_DATAOUT) { in ns_nand_read_buf()
2149 if (ns->regs.count + len > ns->regs.num) { in ns_nand_read_buf()
2155 memcpy(buf, ns->buf.byte + ns->regs.count, len); in ns_nand_read_buf()
2156 ns->regs.count += len; in ns_nand_read_buf()
2158 if (ns->regs.count == ns->regs.num) { in ns_nand_read_buf()
2159 if (NS_STATE(ns->nxstate) == STATE_READY) in ns_nand_read_buf()
2177 ns->lines.ce = 1; in ns_exec_op()
2179 for (op_id = 0; op_id < op->ninstrs; op_id++) { in ns_exec_op()
2180 instr = &op->instrs[op_id]; in ns_exec_op()
2181 ns->lines.cle = 0; in ns_exec_op()
2182 ns->lines.ale = 0; in ns_exec_op()
2184 switch (instr->type) { in ns_exec_op()
2186 ns->lines.cle = 1; in ns_exec_op()
2187 ns_nand_write_byte(chip, instr->ctx.cmd.opcode); in ns_exec_op()
2190 ns->lines.ale = 1; in ns_exec_op()
2191 for (i = 0; i < instr->ctx.addr.naddrs; i++) in ns_exec_op()
2192 ns_nand_write_byte(chip, instr->ctx.addr.addrs[i]); in ns_exec_op()
2195 ns_nand_read_buf(chip, instr->ctx.data.buf.in, instr->ctx.data.len); in ns_exec_op()
2198 ns_nand_write_buf(chip, instr->ctx.data.buf.out, instr->ctx.data.len); in ns_exec_op()
2213 chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT; in ns_attach_chip()
2214 chip->ecc.algo = bch ? NAND_ECC_ALGO_BCH : NAND_ECC_ALGO_HAMMING; in ns_attach_chip()
2221 return -EINVAL; in ns_attach_chip()
2224 /* Use 512-byte ecc blocks */ in ns_attach_chip()
2225 eccsteps = nsmtd->writesize / 512; in ns_attach_chip()
2229 if (nsmtd->oobsize < 64 || !eccsteps) { in ns_attach_chip()
2231 return -EINVAL; in ns_attach_chip()
2234 if (((eccbytes * eccsteps) + 2) > nsmtd->oobsize) { in ns_attach_chip()
2236 return -EINVAL; in ns_attach_chip()
2239 chip->ecc.size = 512; in ns_attach_chip()
2240 chip->ecc.strength = bch; in ns_attach_chip()
2241 chip->ecc.bytes = eccbytes; in ns_attach_chip()
2243 NS_INFO("Using %u-bit/%u bytes BCH ECC\n", bch, chip->ecc.size); in ns_attach_chip()
2258 struct list_head *pos, *n; in ns_init_module() local
2265 return -EINVAL; in ns_init_module()
2271 return -ENOMEM; in ns_init_module()
2273 chip = &ns->chip; in ns_init_module()
2279 chip->options |= NAND_SKIP_BBTSCAN; in ns_init_module()
2283 chip->bbt_options |= NAND_BBT_NO_OOB; in ns_init_module()
2286 chip->bbt_options |= NAND_BBT_USE_FLASH; in ns_init_module()
2292 ret = -EINVAL; in ns_init_module()
2300 ns->geom.idbytes = 8; in ns_init_module()
2302 ns->geom.idbytes = 6; in ns_init_module()
2304 ns->geom.idbytes = 4; in ns_init_module()
2306 ns->geom.idbytes = 2; in ns_init_module()
2307 ns->regs.status = NS_STATUS_OK(ns); in ns_init_module()
2308 ns->nxstate = STATE_UNKNOWN; in ns_init_module()
2309 ns->options |= OPT_PAGE512; /* temporary value */ in ns_init_module()
2310 memcpy(ns->ids, id_bytes, sizeof(ns->ids)); in ns_init_module()
2312 ns->busw = 16; in ns_init_module()
2313 chip->options |= NAND_BUSWIDTH_16; in ns_init_module()
2316 nsmtd->owner = THIS_MODULE; in ns_init_module()
2330 nand_controller_init(&ns->base); in ns_init_module()
2331 ns->base.ops = &ns_controller_ops; in ns_init_module()
2332 chip->controller = &ns->base; in ns_init_module()
2341 uint64_t new_size = (uint64_t)nsmtd->erasesize << overridesize; in ns_init_module()
2345 memorg = nanddev_get_memorg(&chip->base); in ns_init_module()
2347 if (new_size >> overridesize != nsmtd->erasesize) { in ns_init_module()
2349 ret = -EINVAL; in ns_init_module()
2354 nsmtd->size = new_size; in ns_init_module()
2355 memorg->eraseblocks_per_lun = 1 << overridesize; in ns_init_module()
2356 targetsize = nanddev_target_size(&chip->base); in ns_init_module()
2357 chip->chip_shift = ffs(nsmtd->erasesize) + overridesize - 1; in ns_init_module()
2358 chip->pagemask = (targetsize >> chip->page_shift) - 1; in ns_init_module()
2378 ret = mtd_device_register(nsmtd, &ns->partitions[0], ns->nbparts); in ns_init_module()
2397 list_for_each_safe(pos, n, &grave_pages) { in ns_init_module()
2398 list_del(pos); in ns_init_module()
2399 kfree(list_entry(pos, struct grave_page, list)); in ns_init_module()
2402 list_for_each_safe(pos, n, &weak_pages) { in ns_init_module()
2403 list_del(pos); in ns_init_module()
2404 kfree(list_entry(pos, struct weak_page, list)); in ns_init_module()
2407 list_for_each_safe(pos, n, &weak_blocks) { in ns_init_module()
2408 list_del(pos); in ns_init_module()
2409 kfree(list_entry(pos, struct weak_block, list)); in ns_init_module()
2420 * Module clean-up function
2426 struct list_head *pos, *n; in ns_cleanup_module() local
2434 list_for_each_safe(pos, n, &grave_pages) { in ns_cleanup_module()
2435 list_del(pos); in ns_cleanup_module()
2436 kfree(list_entry(pos, struct grave_page, list)); in ns_cleanup_module()
2439 list_for_each_safe(pos, n, &weak_pages) { in ns_cleanup_module()
2440 list_del(pos); in ns_cleanup_module()
2441 kfree(list_entry(pos, struct weak_page, list)); in ns_cleanup_module()
2444 list_for_each_safe(pos, n, &weak_blocks) { in ns_cleanup_module()
2445 list_del(pos); in ns_cleanup_module()
2446 kfree(list_entry(pos, struct weak_block, list)); in ns_cleanup_module()