• Home
  • Raw
  • Download

Lines Matching +full:0 +full:ns

9  * Note: NS means "NAND Simulator".
43 #define CONFIG_NANDSIM_FIRST_ID_BYTE 0x98
44 #define CONFIG_NANDSIM_SECOND_ID_BYTE 0x39
45 #define CONFIG_NANDSIM_THIRD_ID_BYTE 0xFF /* No byte */
46 #define CONFIG_NANDSIM_FOURTH_ID_BYTE 0xFF /* No byte */
68 #define CONFIG_NANDSIM_DO_DELAYS 0
71 #define CONFIG_NANDSIM_LOG 0
74 #define CONFIG_NANDSIM_DBG 0
94 static unsigned int bitflips = 0;
96 static unsigned int overridesize = 0;
101 [0] = CONFIG_NANDSIM_FIRST_ID_BYTE,
105 [4 ... 7] = 0xFF,
109 module_param_named(first_id_byte, id_bytes[0], byte, 0400);
164 MODULE_PARM_DESC(bbt, "0 OOB, 1 BBT with marker in OOB, 2 BBT with marker in data area");
173 do { if (log) pr_debug(" log: " args); } while(0)
175 do { if (dbg) pr_debug(" debug: " args); } while(0)
177 do { pr_warn(" warning: " args); } while(0)
179 do { pr_err(" error: " args); } while(0)
181 do { pr_info(" " args); } while(0)
185 do { if (do_delays) udelay(us); } while(0)
187 do { if (do_delays) mdelay(us); } while(0)
190 #define NS_IS_INITIALIZED(ns) ((ns)->geom.totsz != 0) argument
193 #define NS_STATUS_OK(ns) (NAND_STATUS_READY | (NAND_STATUS_WP * ((ns)->lines.wp == 0))) argument
196 #define NS_STATUS_FAILED(ns) (NAND_STATUS_FAIL | NS_STATUS_OK(ns)) argument
199 #define NS_RAW_OFFSET(ns) \ argument
200 (((ns)->regs.row * (ns)->geom.pgszoob) + (ns)->regs.column)
203 #define NS_RAW_OFFSET_OOB(ns) (NS_RAW_OFFSET(ns) + ns->geom.pgsz) argument
206 #define STATE_CMD_READ0 0x00000001 /* read data from the beginning of page */
207 #define STATE_CMD_READ1 0x00000002 /* read data from the second half of page */
208 #define STATE_CMD_READSTART 0x00000003 /* read data second command (large page devices) */
209 #define STATE_CMD_PAGEPROG 0x00000004 /* start page program */
210 #define STATE_CMD_READOOB 0x00000005 /* read OOB area */
211 #define STATE_CMD_ERASE1 0x00000006 /* sector erase first command */
212 #define STATE_CMD_STATUS 0x00000007 /* read status */
213 #define STATE_CMD_SEQIN 0x00000009 /* sequential data input */
214 #define STATE_CMD_READID 0x0000000A /* read ID */
215 #define STATE_CMD_ERASE2 0x0000000B /* sector erase second command */
216 #define STATE_CMD_RESET 0x0000000C /* reset */
217 #define STATE_CMD_RNDOUT 0x0000000D /* random output command */
218 #define STATE_CMD_RNDOUTSTART 0x0000000E /* random output start command */
219 #define STATE_CMD_MASK 0x0000000F /* command states mask */
222 #define STATE_ADDR_PAGE 0x00000010 /* full (row, column) address is accepted */
223 #define STATE_ADDR_SEC 0x00000020 /* sector address was accepted */
224 #define STATE_ADDR_COLUMN 0x00000030 /* column address was accepted */
225 #define STATE_ADDR_ZERO 0x00000040 /* one byte zero address was accepted */
226 #define STATE_ADDR_MASK 0x00000070 /* address states mask */
229 #define STATE_DATAIN 0x00000100 /* waiting for data input */
230 #define STATE_DATAIN_MASK 0x00000100 /* data input states mask */
232 #define STATE_DATAOUT 0x00001000 /* waiting for page data output */
233 #define STATE_DATAOUT_ID 0x00002000 /* waiting for ID bytes output */
234 #define STATE_DATAOUT_STATUS 0x00003000 /* waiting for status output */
235 #define STATE_DATAOUT_MASK 0x00007000 /* data output states mask */
238 #define STATE_READY 0x00000000
241 #define STATE_UNKNOWN 0x10000000
244 #define ACTION_CPY 0x00100000 /* copy page/OOB to the internal buffer */
245 #define ACTION_PRGPAGE 0x00200000 /* program the internal buffer to flash */
246 #define ACTION_SECERASE 0x00300000 /* erase sector */
247 #define ACTION_ZEROOFF 0x00400000 /* don't add any offset to address */
248 #define ACTION_HALFOFF 0x00500000 /* add to address half of page */
249 #define ACTION_OOBOFF 0x00600000 /* add to address OOB offset */
250 #define ACTION_MASK 0x00700000 /* action mask */
255 #define OPT_ANY 0xFFFFFFFF /* any chip supports this operation */
256 #define OPT_PAGE512 0x00000002 /* 512-byte page chips */
257 #define OPT_PAGE2048 0x00000008 /* 2048-byte page chips */
258 #define OPT_PAGE512_8BIT 0x00000040 /* 512-byte page chips with 8-bit bus width */
259 #define OPT_PAGE4096 0x00000080 /* 4096-byte page chips */
432 static unsigned int wear_eb_count = 0;
433 static unsigned long total_wear = 0;
440 unsigned long wmin = -1, wmax = 0, avg; in ns_show()
441 unsigned long deciles[10], decile_max[10], tot = 0; in ns_show()
445 for (i = 0; i < wear_eb_count; ++i) { in ns_show()
454 for (i = 0; i < 9; ++i) { in ns_show()
455 deciles[i] = 0; in ns_show()
458 deciles[9] = 0; in ns_show()
460 for (i = 0; i < wear_eb_count; ++i) { in ns_show()
463 for (d = 0; d < 10; ++d) in ns_show()
477 for (i = 0; i < 10; ++i) { in ns_show()
478 unsigned long from = (i ? decile_max[i - 1] + 1 : 0); in ns_show()
487 return 0; in ns_show()
489 DEFINE_SHOW_ATTRIBUTE(ns);
493 * @ns: nandsim device description object
498 static int ns_debugfs_create(struct nandsim *ns) in ns_debugfs_create() argument
510 return 0; in ns_debugfs_create()
513 ns->dent = debugfs_create_file("nandsim_wear_report", 0400, root, ns, in ns_debugfs_create()
515 if (IS_ERR_OR_NULL(ns->dent)) { in ns_debugfs_create()
520 return 0; in ns_debugfs_create()
523 static void ns_debugfs_remove(struct nandsim *ns) in ns_debugfs_remove() argument
525 debugfs_remove_recursive(ns->dent); in ns_debugfs_remove()
532 * RETURNS: 0 if success, -ENOMEM if memory alloc fails.
534 static int __init ns_alloc_device(struct nandsim *ns) in ns_alloc_device() argument
553 ns->pages_written = in ns_alloc_device()
555 BITS_TO_LONGS(ns->geom.pgnum))); in ns_alloc_device()
556 if (!ns->pages_written) { in ns_alloc_device()
561 ns->file_buf = kmalloc(ns->geom.pgszoob, GFP_KERNEL); in ns_alloc_device()
562 if (!ns->file_buf) { in ns_alloc_device()
567 ns->cfile = cfile; in ns_alloc_device()
569 return 0; in ns_alloc_device()
572 vfree(ns->pages_written); in ns_alloc_device()
579 ns->pages = vmalloc(array_size(sizeof(union ns_mem), ns->geom.pgnum)); in ns_alloc_device()
580 if (!ns->pages) { in ns_alloc_device()
584 for (i = 0; i < ns->geom.pgnum; i++) { in ns_alloc_device()
585 ns->pages[i].byte = NULL; in ns_alloc_device()
587 ns->nand_pages_slab = kmem_cache_create("nandsim", in ns_alloc_device()
588 ns->geom.pgszoob, 0, 0, NULL); in ns_alloc_device()
589 if (!ns->nand_pages_slab) { in ns_alloc_device()
595 return 0; in ns_alloc_device()
598 vfree(ns->pages); in ns_alloc_device()
606 static void ns_free_device(struct nandsim *ns) in ns_free_device() argument
610 if (ns->cfile) { in ns_free_device()
611 kfree(ns->file_buf); in ns_free_device()
612 vfree(ns->pages_written); in ns_free_device()
613 filp_close(ns->cfile, NULL); in ns_free_device()
617 if (ns->pages) { in ns_free_device()
618 for (i = 0; i < ns->geom.pgnum; i++) { in ns_free_device()
619 if (ns->pages[i].byte) in ns_free_device()
620 kmem_cache_free(ns->nand_pages_slab, in ns_free_device()
621 ns->pages[i].byte); in ns_free_device()
623 kmem_cache_destroy(ns->nand_pages_slab); in ns_free_device()
624 vfree(ns->pages); in ns_free_device()
636 * RETURNS: 0 if success, -ERRNO if failure.
641 struct nandsim *ns = nand_get_controller_data(chip); in ns_init() local
642 int i, ret = 0; in ns_init()
646 if (NS_IS_INITIALIZED(ns)) { in ns_init()
652 ns->busw = chip->options & NAND_BUSWIDTH_16 ? 16 : 8; in ns_init()
653 ns->geom.totsz = mtd->size; in ns_init()
654 ns->geom.pgsz = mtd->writesize; in ns_init()
655 ns->geom.oobsz = mtd->oobsize; in ns_init()
656 ns->geom.secsz = mtd->erasesize; in ns_init()
657 ns->geom.pgszoob = ns->geom.pgsz + ns->geom.oobsz; in ns_init()
658 ns->geom.pgnum = div_u64(ns->geom.totsz, ns->geom.pgsz); in ns_init()
659 ns->geom.totszoob = ns->geom.totsz + (uint64_t)ns->geom.pgnum * ns->geom.oobsz; in ns_init()
660 ns->geom.secshift = ffs(ns->geom.secsz) - 1; in ns_init()
661 ns->geom.pgshift = chip->page_shift; in ns_init()
662 ns->geom.pgsec = ns->geom.secsz / ns->geom.pgsz; in ns_init()
663 ns->geom.secszoob = ns->geom.secsz + ns->geom.oobsz * ns->geom.pgsec; in ns_init()
664 ns->options = 0; in ns_init()
666 if (ns->geom.pgsz == 512) { in ns_init()
667 ns->options |= OPT_PAGE512; in ns_init()
668 if (ns->busw == 8) in ns_init()
669 ns->options |= OPT_PAGE512_8BIT; in ns_init()
670 } else if (ns->geom.pgsz == 2048) { in ns_init()
671 ns->options |= OPT_PAGE2048; in ns_init()
672 } else if (ns->geom.pgsz == 4096) { in ns_init()
673 ns->options |= OPT_PAGE4096; in ns_init()
675 NS_ERR("init_nandsim: unknown page size %u\n", ns->geom.pgsz); in ns_init()
679 if (ns->options & OPT_SMALLPAGE) { in ns_init()
680 if (ns->geom.totsz <= (32 << 20)) { in ns_init()
681 ns->geom.pgaddrbytes = 3; in ns_init()
682 ns->geom.secaddrbytes = 2; in ns_init()
684 ns->geom.pgaddrbytes = 4; in ns_init()
685 ns->geom.secaddrbytes = 3; in ns_init()
688 if (ns->geom.totsz <= (128 << 20)) { in ns_init()
689 ns->geom.pgaddrbytes = 4; in ns_init()
690 ns->geom.secaddrbytes = 2; in ns_init()
692 ns->geom.pgaddrbytes = 5; in ns_init()
693 ns->geom.secaddrbytes = 3; in ns_init()
698 if (parts_num > ARRAY_SIZE(ns->partitions)) { in ns_init()
702 remains = ns->geom.totsz; in ns_init()
703 next_offset = 0; in ns_init()
704 for (i = 0; i < parts_num; ++i) { in ns_init()
705 uint64_t part_sz = (uint64_t)parts[i] * ns->geom.secsz; in ns_init()
711 ns->partitions[i].name = ns_get_partition_name(i); in ns_init()
712 if (!ns->partitions[i].name) { in ns_init()
716 ns->partitions[i].offset = next_offset; in ns_init()
717 ns->partitions[i].size = part_sz; in ns_init()
718 next_offset += ns->partitions[i].size; in ns_init()
719 remains -= ns->partitions[i].size; in ns_init()
721 ns->nbparts = parts_num; in ns_init()
723 if (parts_num + 1 > ARRAY_SIZE(ns->partitions)) { in ns_init()
728 ns->partitions[i].name = ns_get_partition_name(i); in ns_init()
729 if (!ns->partitions[i].name) { in ns_init()
734 ns->partitions[i].offset = next_offset; in ns_init()
735 ns->partitions[i].size = remains; in ns_init()
736 ns->nbparts += 1; in ns_init()
739 if (ns->busw == 16) in ns_init()
743 (unsigned long long)ns->geom.totsz >> 20); in ns_init()
744 printk("page size: %u bytes\n", ns->geom.pgsz); in ns_init()
745 printk("OOB area size: %u bytes\n", ns->geom.oobsz); in ns_init()
746 printk("sector size: %u KiB\n", ns->geom.secsz >> 10); in ns_init()
747 printk("pages number: %u\n", ns->geom.pgnum); in ns_init()
748 printk("pages per sector: %u\n", ns->geom.pgsec); in ns_init()
749 printk("bus width: %u\n", ns->busw); in ns_init()
750 printk("bits in sector size: %u\n", ns->geom.secshift); in ns_init()
751 printk("bits in page size: %u\n", ns->geom.pgshift); in ns_init()
752 printk("bits in OOB size: %u\n", ffs(ns->geom.oobsz) - 1); in ns_init()
754 (unsigned long long)ns->geom.totszoob >> 10); in ns_init()
755 printk("page address bytes: %u\n", ns->geom.pgaddrbytes); in ns_init()
756 printk("sector address bytes: %u\n", ns->geom.secaddrbytes); in ns_init()
757 printk("options: %#x\n", ns->options); in ns_init()
759 ret = ns_alloc_device(ns); in ns_init()
764 ns->buf.byte = kmalloc(ns->geom.pgszoob, GFP_KERNEL); in ns_init()
765 if (!ns->buf.byte) { in ns_init()
767 ns->geom.pgszoob); in ns_init()
771 memset(ns->buf.byte, 0xFF, ns->geom.pgszoob); in ns_init()
773 return 0; in ns_init()
776 ns_free_device(ns); in ns_init()
778 for (i = 0; i < ARRAY_SIZE(ns->partitions); ++i) in ns_init()
779 kfree(ns->partitions[i].name); in ns_init()
787 static void ns_free(struct nandsim *ns) in ns_free() argument
791 for (i = 0; i < ARRAY_SIZE(ns->partitions); ++i) in ns_free()
792 kfree(ns->partitions[i].name); in ns_free()
794 kfree(ns->buf.byte); in ns_free()
795 ns_free_device(ns); in ns_free()
800 static int ns_parse_badblocks(struct nandsim *ns, struct mtd_info *mtd) in ns_parse_badblocks() argument
808 return 0; in ns_parse_badblocks()
811 zero_ok = (*w == '0' ? 1 : 0); in ns_parse_badblocks()
812 erase_block_no = simple_strtoul(w, &w, 0); in ns_parse_badblocks()
817 offset = (loff_t)erase_block_no * ns->geom.secsz; in ns_parse_badblocks()
825 return 0; in ns_parse_badblocks()
837 return 0; in ns_parse_weakblocks()
840 zero_ok = (*w == '0' ? 1 : 0); in ns_parse_weakblocks()
841 erase_block_no = simple_strtoul(w, &w, 0); in ns_parse_weakblocks()
849 max_erases = simple_strtoul(w, &w, 0); in ns_parse_weakblocks()
862 return 0; in ns_parse_weakblocks()
874 return 0; in ns_erase_error()
876 return 0; in ns_erase_error()
888 return 0; in ns_parse_weakpages()
891 zero_ok = (*w == '0' ? 1 : 0); in ns_parse_weakpages()
892 page_no = simple_strtoul(w, &w, 0); in ns_parse_weakpages()
900 max_writes = simple_strtoul(w, &w, 0); in ns_parse_weakpages()
913 return 0; in ns_parse_weakpages()
925 return 0; in ns_write_error()
927 return 0; in ns_write_error()
939 return 0; in ns_parse_gravepages()
942 zero_ok = (*g == '0' ? 1 : 0); in ns_parse_gravepages()
943 page_no = simple_strtoul(g, &g, 0); in ns_parse_gravepages()
951 max_reads = simple_strtoul(g, &g, 0); in ns_parse_gravepages()
964 return 0; in ns_parse_gravepages()
976 return 0; in ns_read_error()
978 return 0; in ns_read_error()
996 return 0; in ns_setup_wear_reporting()
1008 if (total_wear == 0) in ns_update_wear()
1011 if (erase_block_wear[erase_block_no] == 0) in ns_update_wear()
1076 * RETURNS: 1 if wrong command, 0 if right.
1095 return 0; in ns_check_command()
1137 return 0; in ns_get_state_by_command()
1143 static inline void ns_accept_addr_byte(struct nandsim *ns, u_char bt) in ns_accept_addr_byte() argument
1147 if (ns->regs.count < (ns->geom.pgaddrbytes - ns->geom.secaddrbytes)) in ns_accept_addr_byte()
1148 ns->regs.column |= (byte << 8 * ns->regs.count); in ns_accept_addr_byte()
1150 ns->regs.row |= (byte << 8 * (ns->regs.count - in ns_accept_addr_byte()
1151 ns->geom.pgaddrbytes + in ns_accept_addr_byte()
1152 ns->geom.secaddrbytes)); in ns_accept_addr_byte()
1161 static inline void ns_switch_to_ready_state(struct nandsim *ns, u_char status) in ns_switch_to_ready_state() argument
1166 ns->state = STATE_READY; in ns_switch_to_ready_state()
1167 ns->nxstate = STATE_UNKNOWN; in ns_switch_to_ready_state()
1168 ns->op = NULL; in ns_switch_to_ready_state()
1169 ns->npstates = 0; in ns_switch_to_ready_state()
1170 ns->stateidx = 0; in ns_switch_to_ready_state()
1171 ns->regs.num = 0; in ns_switch_to_ready_state()
1172 ns->regs.count = 0; in ns_switch_to_ready_state()
1173 ns->regs.off = 0; in ns_switch_to_ready_state()
1174 ns->regs.row = 0; in ns_switch_to_ready_state()
1175 ns->regs.column = 0; in ns_switch_to_ready_state()
1176 ns->regs.status = status; in ns_switch_to_ready_state()
1185 * correspondent states chain. In this case ns->npstates = 0;
1189 * case the ns->pstates[] array contains previous states.
1192 * states (if the 'flag' parameter is 0):
1193 * ns->pstates[0], ... ns->pstates[ns->npstates], ns->state
1196 * ns->ops, ns->state, ns->nxstate are initialized, ns->npstate is
1200 * ns->pstates.
1204 * In such situation the function is called with 'flag' != 0, and the
1206 * ns->pstates[0], ... ns->pstates[ns->npstates], <address input>
1219 * 0 - operation is found.
1221 static int ns_find_operation(struct nandsim *ns, uint32_t flag) in ns_find_operation() argument
1223 int opsfound = 0; in ns_find_operation()
1224 int i, j, idx = 0; in ns_find_operation()
1226 for (i = 0; i < NS_OPER_NUM; i++) { in ns_find_operation()
1230 if (!(ns->options & ops[i].reqopts)) in ns_find_operation()
1235 if (!(ops[i].states[ns->npstates] & STATE_ADDR_MASK)) in ns_find_operation()
1238 if (NS_STATE(ns->state) != NS_STATE(ops[i].states[ns->npstates])) in ns_find_operation()
1242 for (j = 0; j < ns->npstates; j++) in ns_find_operation()
1243 if (NS_STATE(ops[i].states[j]) != NS_STATE(ns->pstates[j]) in ns_find_operation()
1244 && (ns->options & ops[idx].reqopts)) { in ns_find_operation()
1245 found = 0; in ns_find_operation()
1257 ns->op = &ops[idx].states[0]; in ns_find_operation()
1264 * state must be the next state (ns->nxstate). in ns_find_operation()
1266 ns->stateidx = ns->npstates - 1; in ns_find_operation()
1268 ns->stateidx = ns->npstates; in ns_find_operation()
1270 ns->npstates = 0; in ns_find_operation()
1271 ns->state = ns->op[ns->stateidx]; in ns_find_operation()
1272 ns->nxstate = ns->op[ns->stateidx + 1]; in ns_find_operation()
1274 idx, ns_get_state_name(ns->state), in ns_find_operation()
1275 ns_get_state_name(ns->nxstate)); in ns_find_operation()
1276 return 0; in ns_find_operation()
1279 if (opsfound == 0) { in ns_find_operation()
1281 if (ns->npstates != 0) { in ns_find_operation()
1283 ns_get_state_name(ns->state)); in ns_find_operation()
1284 ns->npstates = 0; in ns_find_operation()
1285 return ns_find_operation(ns, 0); in ns_find_operation()
1289 ns_switch_to_ready_state(ns, NS_STATUS_FAILED(ns)); in ns_find_operation()
1301 ns->pstates[ns->npstates++] = ns->state; in ns_find_operation()
1306 static void ns_put_pages(struct nandsim *ns) in ns_put_pages() argument
1310 for (i = 0; i < ns->held_cnt; i++) in ns_put_pages()
1311 put_page(ns->held_pages[i]); in ns_put_pages()
1315 static int ns_get_pages(struct nandsim *ns, struct file *file, size_t count, in ns_get_pages() argument
1326 ns->held_cnt = 0; in ns_get_pages()
1336 ns_put_pages(ns); in ns_get_pages()
1341 ns->held_pages[ns->held_cnt++] = page; in ns_get_pages()
1343 return 0; in ns_get_pages()
1346 static ssize_t ns_read_file(struct nandsim *ns, struct file *file, void *buf, in ns_read_file() argument
1353 err = ns_get_pages(ns, file, count, pos); in ns_read_file()
1359 ns_put_pages(ns); in ns_read_file()
1363 static ssize_t ns_write_file(struct nandsim *ns, struct file *file, void *buf, in ns_write_file() argument
1370 err = ns_get_pages(ns, file, count, pos); in ns_write_file()
1376 ns_put_pages(ns); in ns_write_file()
1383 static inline union ns_mem *NS_GET_PAGE(struct nandsim *ns) in NS_GET_PAGE() argument
1385 return &(ns->pages[ns->regs.row]); in NS_GET_PAGE()
1391 static inline u_char *NS_PAGE_BYTE_OFF(struct nandsim *ns) in NS_PAGE_BYTE_OFF() argument
1393 return NS_GET_PAGE(ns)->byte + ns->regs.column + ns->regs.off; in NS_PAGE_BYTE_OFF()
1396 static int ns_do_read_error(struct nandsim *ns, int num) in ns_do_read_error() argument
1398 unsigned int page_no = ns->regs.row; in ns_do_read_error()
1401 prandom_bytes(ns->buf.byte, num); in ns_do_read_error()
1405 return 0; in ns_do_read_error()
1408 static void ns_do_bit_flips(struct nandsim *ns, int num) in ns_do_bit_flips() argument
1416 ns->buf.byte[pos / 8] ^= (1 << (pos % 8)); in ns_do_bit_flips()
1419 pos, ns->regs.row, ns->regs.column + ns->regs.off, in ns_do_bit_flips()
1428 static void ns_read_page(struct nandsim *ns, int num) in ns_read_page() argument
1432 if (ns->cfile) { in ns_read_page()
1433 if (!test_bit(ns->regs.row, ns->pages_written)) { in ns_read_page()
1434 NS_DBG("read_page: page %d not written\n", ns->regs.row); in ns_read_page()
1435 memset(ns->buf.byte, 0xFF, num); in ns_read_page()
1441 ns->regs.row, ns->regs.column + ns->regs.off); in ns_read_page()
1442 if (ns_do_read_error(ns, num)) in ns_read_page()
1444 pos = (loff_t)NS_RAW_OFFSET(ns) + ns->regs.off; in ns_read_page()
1445 tx = ns_read_file(ns, ns->cfile, ns->buf.byte, num, in ns_read_page()
1448 NS_ERR("read_page: read error for page %d ret %ld\n", ns->regs.row, (long)tx); in ns_read_page()
1451 ns_do_bit_flips(ns, num); in ns_read_page()
1456 mypage = NS_GET_PAGE(ns); in ns_read_page()
1458 NS_DBG("read_page: page %d not allocated\n", ns->regs.row); in ns_read_page()
1459 memset(ns->buf.byte, 0xFF, num); in ns_read_page()
1462 ns->regs.row, ns->regs.column + ns->regs.off); in ns_read_page()
1463 if (ns_do_read_error(ns, num)) in ns_read_page()
1465 memcpy(ns->buf.byte, NS_PAGE_BYTE_OFF(ns), num); in ns_read_page()
1466 ns_do_bit_flips(ns, num); in ns_read_page()
1473 static void ns_erase_sector(struct nandsim *ns) in ns_erase_sector() argument
1478 if (ns->cfile) { in ns_erase_sector()
1479 for (i = 0; i < ns->geom.pgsec; i++) in ns_erase_sector()
1480 if (__test_and_clear_bit(ns->regs.row + i, in ns_erase_sector()
1481 ns->pages_written)) { in ns_erase_sector()
1482 NS_DBG("erase_sector: freeing page %d\n", ns->regs.row + i); in ns_erase_sector()
1487 mypage = NS_GET_PAGE(ns); in ns_erase_sector()
1488 for (i = 0; i < ns->geom.pgsec; i++) { in ns_erase_sector()
1490 NS_DBG("erase_sector: freeing page %d\n", ns->regs.row+i); in ns_erase_sector()
1491 kmem_cache_free(ns->nand_pages_slab, mypage->byte); in ns_erase_sector()
1501 static int ns_prog_page(struct nandsim *ns, int num) in ns_prog_page() argument
1507 if (ns->cfile) { in ns_prog_page()
1512 NS_DBG("prog_page: writing page %d\n", ns->regs.row); in ns_prog_page()
1513 pg_off = ns->file_buf + ns->regs.column + ns->regs.off; in ns_prog_page()
1514 off = (loff_t)NS_RAW_OFFSET(ns) + ns->regs.off; in ns_prog_page()
1515 if (!test_bit(ns->regs.row, ns->pages_written)) { in ns_prog_page()
1517 memset(ns->file_buf, 0xff, ns->geom.pgszoob); in ns_prog_page()
1519 all = 0; in ns_prog_page()
1520 tx = ns_read_file(ns, ns->cfile, pg_off, num, off); in ns_prog_page()
1522 NS_ERR("prog_page: read error for page %d ret %ld\n", ns->regs.row, (long)tx); in ns_prog_page()
1526 for (i = 0; i < num; i++) in ns_prog_page()
1527 pg_off[i] &= ns->buf.byte[i]; in ns_prog_page()
1529 loff_t pos = (loff_t)ns->regs.row * ns->geom.pgszoob; in ns_prog_page()
1530 tx = ns_write_file(ns, ns->cfile, ns->file_buf, in ns_prog_page()
1531 ns->geom.pgszoob, pos); in ns_prog_page()
1532 if (tx != ns->geom.pgszoob) { in ns_prog_page()
1533 NS_ERR("prog_page: write error for page %d ret %ld\n", ns->regs.row, (long)tx); in ns_prog_page()
1536 __set_bit(ns->regs.row, ns->pages_written); in ns_prog_page()
1538 tx = ns_write_file(ns, ns->cfile, pg_off, num, off); in ns_prog_page()
1540 NS_ERR("prog_page: write error for page %d ret %ld\n", ns->regs.row, (long)tx); in ns_prog_page()
1544 return 0; in ns_prog_page()
1547 mypage = NS_GET_PAGE(ns); in ns_prog_page()
1549 NS_DBG("prog_page: allocating page %d\n", ns->regs.row); in ns_prog_page()
1556 mypage->byte = kmem_cache_alloc(ns->nand_pages_slab, GFP_NOFS); in ns_prog_page()
1558 NS_ERR("prog_page: error allocating memory for page %d\n", ns->regs.row); in ns_prog_page()
1561 memset(mypage->byte, 0xFF, ns->geom.pgszoob); in ns_prog_page()
1564 pg_off = NS_PAGE_BYTE_OFF(ns); in ns_prog_page()
1565 for (i = 0; i < num; i++) in ns_prog_page()
1566 pg_off[i] &= ns->buf.byte[i]; in ns_prog_page()
1568 return 0; in ns_prog_page()
1574 * RETURNS: 0 if success, -1 if error.
1576 static int ns_do_state_action(struct nandsim *ns, uint32_t action) in ns_do_state_action() argument
1579 int busdiv = ns->busw == 8 ? 1 : 2; in ns_do_state_action()
1585 if (action != ACTION_SECERASE && ns->regs.row >= ns->geom.pgnum) { in ns_do_state_action()
1586 NS_WARN("do_state_action: wrong page number (%#x)\n", ns->regs.row); in ns_do_state_action()
1598 if (ns->regs.column >= (ns->geom.pgszoob - ns->regs.off)) { in ns_do_state_action()
1602 num = ns->geom.pgszoob - ns->regs.off - ns->regs.column; in ns_do_state_action()
1603 ns_read_page(ns, num); in ns_do_state_action()
1606 num, NS_RAW_OFFSET(ns) + ns->regs.off); in ns_do_state_action()
1608 if (ns->regs.off == 0) in ns_do_state_action()
1609 NS_LOG("read page %d\n", ns->regs.row); in ns_do_state_action()
1610 else if (ns->regs.off < ns->geom.pgsz) in ns_do_state_action()
1611 NS_LOG("read page %d (second half)\n", ns->regs.row); in ns_do_state_action()
1613 NS_LOG("read OOB of page %d\n", ns->regs.row); in ns_do_state_action()
1616 NS_UDELAY(input_cycle * ns->geom.pgsz / 1000 / busdiv); in ns_do_state_action()
1625 if (ns->lines.wp) { in ns_do_state_action()
1630 if (ns->regs.row >= ns->geom.pgnum - ns->geom.pgsec in ns_do_state_action()
1631 || (ns->regs.row & ~(ns->geom.secsz - 1))) { in ns_do_state_action()
1632 NS_ERR("do_state_action: wrong sector address (%#x)\n", ns->regs.row); in ns_do_state_action()
1636 ns->regs.row = (ns->regs.row << in ns_do_state_action()
1637 8 * (ns->geom.pgaddrbytes - ns->geom.secaddrbytes)) | ns->regs.column; in ns_do_state_action()
1638 ns->regs.column = 0; in ns_do_state_action()
1640 erase_block_no = ns->regs.row >> (ns->geom.secshift - ns->geom.pgshift); in ns_do_state_action()
1643 ns->regs.row, NS_RAW_OFFSET(ns)); in ns_do_state_action()
1646 ns_erase_sector(ns); in ns_do_state_action()
1665 if (ns->lines.wp) { in ns_do_state_action()
1670 num = ns->geom.pgszoob - ns->regs.off - ns->regs.column; in ns_do_state_action()
1671 if (num != ns->regs.count) { in ns_do_state_action()
1673 ns->regs.count, num); in ns_do_state_action()
1677 if (ns_prog_page(ns, num) == -1) in ns_do_state_action()
1680 page_no = ns->regs.row; in ns_do_state_action()
1683 num, ns->regs.row, ns->regs.column, NS_RAW_OFFSET(ns) + ns->regs.off); in ns_do_state_action()
1684 NS_LOG("programm page %d\n", ns->regs.row); in ns_do_state_action()
1687 NS_UDELAY(output_cycle * ns->geom.pgsz / 1000 / busdiv); in ns_do_state_action()
1697 NS_DBG("do_state_action: set internal offset to 0\n"); in ns_do_state_action()
1698 ns->regs.off = 0; in ns_do_state_action()
1702 if (!(ns->options & OPT_PAGE512_8BIT)) { in ns_do_state_action()
1707 NS_DBG("do_state_action: set internal offset to %d\n", ns->geom.pgsz/2); in ns_do_state_action()
1708 ns->regs.off = ns->geom.pgsz/2; in ns_do_state_action()
1712 NS_DBG("do_state_action: set internal offset to %d\n", ns->geom.pgsz); in ns_do_state_action()
1713 ns->regs.off = ns->geom.pgsz; in ns_do_state_action()
1720 return 0; in ns_do_state_action()
1726 static void ns_switch_state(struct nandsim *ns) in ns_switch_state() argument
1728 if (ns->op) { in ns_switch_state()
1734 ns->stateidx += 1; in ns_switch_state()
1735 ns->state = ns->nxstate; in ns_switch_state()
1736 ns->nxstate = ns->op[ns->stateidx + 1]; in ns_switch_state()
1740 ns_get_state_name(ns->state), in ns_switch_state()
1741 ns_get_state_name(ns->nxstate)); in ns_switch_state()
1744 if ((ns->state & ACTION_MASK) && in ns_switch_state()
1745 ns_do_state_action(ns, ns->state) < 0) { in ns_switch_state()
1746 ns_switch_to_ready_state(ns, NS_STATUS_FAILED(ns)); in ns_switch_state()
1760 ns->state = ns_get_state_by_command(ns->regs.command); in ns_switch_state()
1764 if (ns_find_operation(ns, 0)) in ns_switch_state()
1767 if ((ns->state & ACTION_MASK) && in ns_switch_state()
1768 ns_do_state_action(ns, ns->state) < 0) { in ns_switch_state()
1769 ns_switch_to_ready_state(ns, NS_STATUS_FAILED(ns)); in ns_switch_state()
1775 if ((ns->nxstate & STATE_ADDR_MASK) && ns->busw == 16) { in ns_switch_state()
1777 ns->regs.column <<= 1; in ns_switch_state()
1780 if (NS_STATE(ns->nxstate) == STATE_READY) { in ns_switch_state()
1785 u_char status = NS_STATUS_OK(ns); in ns_switch_state()
1788 if ((ns->state & (STATE_DATAIN_MASK | STATE_DATAOUT_MASK)) in ns_switch_state()
1789 && ns->regs.count != ns->regs.num) { in ns_switch_state()
1791 ns->regs.num - ns->regs.count); in ns_switch_state()
1792 status = NS_STATUS_FAILED(ns); in ns_switch_state()
1797 ns_switch_to_ready_state(ns, status); in ns_switch_state()
1800 } else if (ns->nxstate & (STATE_DATAIN_MASK | STATE_DATAOUT_MASK)) { in ns_switch_state()
1805 ns->state = ns->nxstate; in ns_switch_state()
1806 ns->nxstate = ns->op[++ns->stateidx + 1]; in ns_switch_state()
1807 ns->regs.num = ns->regs.count = 0; in ns_switch_state()
1811 ns_get_state_name(ns->state), in ns_switch_state()
1812 ns_get_state_name(ns->nxstate)); in ns_switch_state()
1818 switch (NS_STATE(ns->state)) { in ns_switch_state()
1821 ns->regs.num = ns->geom.pgszoob - ns->regs.off - ns->regs.column; in ns_switch_state()
1825 ns->regs.num = ns->geom.idbytes; in ns_switch_state()
1829 ns->regs.count = ns->regs.num = 0; in ns_switch_state()
1836 } else if (ns->nxstate & STATE_ADDR_MASK) { in ns_switch_state()
1842 ns->regs.count = 0; in ns_switch_state()
1844 switch (NS_STATE(ns->nxstate)) { in ns_switch_state()
1846 ns->regs.num = ns->geom.pgaddrbytes; in ns_switch_state()
1850 ns->regs.num = ns->geom.secaddrbytes; in ns_switch_state()
1854 ns->regs.num = 1; in ns_switch_state()
1859 ns->regs.num = ns->geom.pgaddrbytes - ns->geom.secaddrbytes; in ns_switch_state()
1870 ns->regs.num = 0; in ns_switch_state()
1871 ns->regs.count = 0; in ns_switch_state()
1877 struct nandsim *ns = nand_get_controller_data(chip); in ns_nand_read_byte() local
1878 u_char outb = 0x00; in ns_nand_read_byte()
1881 if (!ns->lines.ce) { in ns_nand_read_byte()
1885 if (ns->lines.ale || ns->lines.cle) { in ns_nand_read_byte()
1889 if (!(ns->state & STATE_DATAOUT_MASK)) { in ns_nand_read_byte()
1891 ns_get_state_name(ns->state), (uint)outb); in ns_nand_read_byte()
1896 if (NS_STATE(ns->state) == STATE_DATAOUT_STATUS) { in ns_nand_read_byte()
1897 NS_DBG("read_byte: return %#x status\n", ns->regs.status); in ns_nand_read_byte()
1898 return ns->regs.status; in ns_nand_read_byte()
1902 if (ns->regs.count == ns->regs.num) { in ns_nand_read_byte()
1907 switch (NS_STATE(ns->state)) { in ns_nand_read_byte()
1909 if (ns->busw == 8) { in ns_nand_read_byte()
1910 outb = ns->buf.byte[ns->regs.count]; in ns_nand_read_byte()
1911 ns->regs.count += 1; in ns_nand_read_byte()
1913 outb = (u_char)cpu_to_le16(ns->buf.word[ns->regs.count >> 1]); in ns_nand_read_byte()
1914 ns->regs.count += 2; in ns_nand_read_byte()
1918 NS_DBG("read_byte: read ID byte %d, total = %d\n", ns->regs.count, ns->regs.num); in ns_nand_read_byte()
1919 outb = ns->ids[ns->regs.count]; in ns_nand_read_byte()
1920 ns->regs.count += 1; in ns_nand_read_byte()
1926 if (ns->regs.count == ns->regs.num) { in ns_nand_read_byte()
1929 if (NS_STATE(ns->nxstate) == STATE_READY) in ns_nand_read_byte()
1930 ns_switch_state(ns); in ns_nand_read_byte()
1938 struct nandsim *ns = nand_get_controller_data(chip); in ns_nand_write_byte() local
1941 if (!ns->lines.ce) { in ns_nand_write_byte()
1945 if (ns->lines.ale && ns->lines.cle) { in ns_nand_write_byte()
1950 if (ns->lines.cle == 1) { in ns_nand_write_byte()
1957 ns_switch_to_ready_state(ns, NS_STATUS_OK(ns)); in ns_nand_write_byte()
1967 if (NS_STATE(ns->state) == STATE_DATAOUT_STATUS in ns_nand_write_byte()
1968 || NS_STATE(ns->state) == STATE_DATAOUT) { in ns_nand_write_byte()
1969 int row = ns->regs.row; in ns_nand_write_byte()
1971 ns_switch_state(ns); in ns_nand_write_byte()
1973 ns->regs.row = row; in ns_nand_write_byte()
1977 if (NS_STATE(ns->nxstate) != STATE_UNKNOWN && !(ns->nxstate & STATE_CMD_MASK)) { in ns_nand_write_byte()
1979 if (!(ns->regs.command == NAND_CMD_READID && in ns_nand_write_byte()
1980 NS_STATE(ns->state) == STATE_DATAOUT_ID && ns->regs.count == 2)) { in ns_nand_write_byte()
1988 ns_get_state_name(ns->nxstate)); in ns_nand_write_byte()
1990 ns_switch_to_ready_state(ns, NS_STATUS_FAILED(ns)); in ns_nand_write_byte()
1995 ns->regs.command = byte; in ns_nand_write_byte()
1996 ns_switch_state(ns); in ns_nand_write_byte()
1998 } else if (ns->lines.ale == 1) { in ns_nand_write_byte()
2003 if (NS_STATE(ns->nxstate) == STATE_UNKNOWN) { in ns_nand_write_byte()
2007 if (ns_find_operation(ns, 1) < 0) in ns_nand_write_byte()
2010 if ((ns->state & ACTION_MASK) && in ns_nand_write_byte()
2011 ns_do_state_action(ns, ns->state) < 0) { in ns_nand_write_byte()
2012 ns_switch_to_ready_state(ns, in ns_nand_write_byte()
2013 NS_STATUS_FAILED(ns)); in ns_nand_write_byte()
2017 ns->regs.count = 0; in ns_nand_write_byte()
2018 switch (NS_STATE(ns->nxstate)) { in ns_nand_write_byte()
2020 ns->regs.num = ns->geom.pgaddrbytes; in ns_nand_write_byte()
2023 ns->regs.num = ns->geom.secaddrbytes; in ns_nand_write_byte()
2026 ns->regs.num = 1; in ns_nand_write_byte()
2034 if (!(ns->nxstate & STATE_ADDR_MASK)) { in ns_nand_write_byte()
2036 (uint)byte, ns_get_state_name(ns->nxstate)); in ns_nand_write_byte()
2037 ns_switch_to_ready_state(ns, NS_STATUS_FAILED(ns)); in ns_nand_write_byte()
2042 if (ns->regs.count == ns->regs.num) { in ns_nand_write_byte()
2044 ns_switch_to_ready_state(ns, NS_STATUS_FAILED(ns)); in ns_nand_write_byte()
2048 ns_accept_addr_byte(ns, byte); in ns_nand_write_byte()
2050 ns->regs.count += 1; in ns_nand_write_byte()
2053 (uint)byte, ns->regs.count, ns->regs.num); in ns_nand_write_byte()
2055 if (ns->regs.count == ns->regs.num) { in ns_nand_write_byte()
2056 NS_DBG("address (%#x, %#x) is accepted\n", ns->regs.row, ns->regs.column); in ns_nand_write_byte()
2057 ns_switch_state(ns); in ns_nand_write_byte()
2066 if (!(ns->state & STATE_DATAIN_MASK)) { in ns_nand_write_byte()
2068 (uint)byte, ns_get_state_name(ns->state), in ns_nand_write_byte()
2070 ns_switch_to_ready_state(ns, NS_STATUS_FAILED(ns)); in ns_nand_write_byte()
2075 if (ns->regs.count == ns->regs.num) { in ns_nand_write_byte()
2077 ns->regs.num); in ns_nand_write_byte()
2081 if (ns->busw == 8) { in ns_nand_write_byte()
2082 ns->buf.byte[ns->regs.count] = byte; in ns_nand_write_byte()
2083 ns->regs.count += 1; in ns_nand_write_byte()
2085 ns->buf.word[ns->regs.count >> 1] = cpu_to_le16((uint16_t)byte); in ns_nand_write_byte()
2086 ns->regs.count += 2; in ns_nand_write_byte()
2096 struct nandsim *ns = nand_get_controller_data(chip); in ns_nand_write_buf() local
2099 if (!(ns->state & STATE_DATAIN_MASK)) { in ns_nand_write_buf()
2101 ns_get_state_name(ns->state)); in ns_nand_write_buf()
2102 ns_switch_to_ready_state(ns, NS_STATUS_FAILED(ns)); in ns_nand_write_buf()
2107 if (ns->regs.count + len > ns->regs.num) { in ns_nand_write_buf()
2109 ns_switch_to_ready_state(ns, NS_STATUS_FAILED(ns)); in ns_nand_write_buf()
2113 memcpy(ns->buf.byte + ns->regs.count, buf, len); in ns_nand_write_buf()
2114 ns->regs.count += len; in ns_nand_write_buf()
2116 if (ns->regs.count == ns->regs.num) { in ns_nand_write_buf()
2117 NS_DBG("write_buf: %d bytes were written\n", ns->regs.count); in ns_nand_write_buf()
2123 struct nandsim *ns = nand_get_controller_data(chip); in ns_nand_read_buf() local
2126 if (!ns->lines.ce) { in ns_nand_read_buf()
2130 if (ns->lines.ale || ns->lines.cle) { in ns_nand_read_buf()
2134 if (!(ns->state & STATE_DATAOUT_MASK)) { in ns_nand_read_buf()
2136 ns_get_state_name(ns->state)); in ns_nand_read_buf()
2140 if (NS_STATE(ns->state) != STATE_DATAOUT) { in ns_nand_read_buf()
2143 for (i = 0; i < len; i++) in ns_nand_read_buf()
2150 if (ns->regs.count + len > ns->regs.num) { in ns_nand_read_buf()
2152 ns_switch_to_ready_state(ns, NS_STATUS_FAILED(ns)); in ns_nand_read_buf()
2156 memcpy(buf, ns->buf.byte + ns->regs.count, len); in ns_nand_read_buf()
2157 ns->regs.count += len; in ns_nand_read_buf()
2159 if (ns->regs.count == ns->regs.num) { in ns_nand_read_buf()
2160 if (NS_STATE(ns->nxstate) == STATE_READY) in ns_nand_read_buf()
2161 ns_switch_state(ns); in ns_nand_read_buf()
2173 struct nandsim *ns = nand_get_controller_data(chip); in ns_exec_op() local
2176 return 0; in ns_exec_op()
2178 ns->lines.ce = 1; in ns_exec_op()
2180 for (op_id = 0; op_id < op->ninstrs; op_id++) { in ns_exec_op()
2182 ns->lines.cle = 0; in ns_exec_op()
2183 ns->lines.ale = 0; in ns_exec_op()
2187 ns->lines.cle = 1; in ns_exec_op()
2191 ns->lines.ale = 1; in ns_exec_op()
2192 for (i = 0; i < instr->ctx.addr.naddrs; i++) in ns_exec_op()
2207 return 0; in ns_exec_op()
2218 return 0; in ns_attach_chip()
2246 return 0; in ns_attach_chip()
2261 struct nandsim *ns; in ns_init_module() local
2269 ns = kzalloc(sizeof(struct nandsim), GFP_KERNEL); in ns_init_module()
2270 if (!ns) { in ns_init_module()
2274 chip = &ns->chip; in ns_init_module()
2276 nand_set_controller_data(chip, (void *)ns); in ns_init_module()
2289 case 0: in ns_init_module()
2292 NS_ERR("bbt has to be 0..2\n"); in ns_init_module()
2300 if (id_bytes[6] != 0xFF || id_bytes[7] != 0xFF) in ns_init_module()
2301 ns->geom.idbytes = 8; in ns_init_module()
2302 else if (id_bytes[4] != 0xFF || id_bytes[5] != 0xFF) in ns_init_module()
2303 ns->geom.idbytes = 6; in ns_init_module()
2304 else if (id_bytes[2] != 0xFF || id_bytes[3] != 0xFF) in ns_init_module()
2305 ns->geom.idbytes = 4; in ns_init_module()
2307 ns->geom.idbytes = 2; in ns_init_module()
2308 ns->regs.status = NS_STATUS_OK(ns); in ns_init_module()
2309 ns->nxstate = STATE_UNKNOWN; in ns_init_module()
2310 ns->options |= OPT_PAGE512; /* temporary value */ in ns_init_module()
2311 memcpy(ns->ids, id_bytes, sizeof(ns->ids)); in ns_init_module()
2313 ns->busw = 16; in ns_init_module()
2331 nand_controller_init(&ns->base); in ns_init_module()
2332 ns->base.ops = &ns_controller_ops; in ns_init_module()
2333 chip->controller = &ns->base; in ns_init_module()
2374 ret = ns_parse_badblocks(ns, nsmtd); in ns_init_module()
2379 ret = mtd_device_register(nsmtd, &ns->partitions[0], ns->nbparts); in ns_init_module()
2383 ret = ns_debugfs_create(ns); in ns_init_module()
2387 return 0; in ns_init_module()
2392 ns_free(ns); in ns_init_module()
2413 kfree(ns); in ns_init_module()
2426 struct nandsim *ns = nand_get_controller_data(chip); in ns_cleanup_module() local
2429 ns_debugfs_remove(ns); in ns_cleanup_module()
2431 ns_free(ns); in ns_cleanup_module()
2450 kfree(ns); in ns_cleanup_module()