diff options
Diffstat (limited to 'drivers/mtd/nand/nandsim.c')
-rw-r--r-- | drivers/mtd/nand/nandsim.c | 66 |
1 files changed, 46 insertions, 20 deletions
diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c index ecd70e2504f6..556e8131ecdc 100644 --- a/drivers/mtd/nand/nandsim.c +++ b/drivers/mtd/nand/nandsim.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <linux/module.h> | 28 | #include <linux/module.h> |
29 | #include <linux/moduleparam.h> | 29 | #include <linux/moduleparam.h> |
30 | #include <linux/vmalloc.h> | 30 | #include <linux/vmalloc.h> |
31 | #include <asm/div64.h> | ||
31 | #include <linux/slab.h> | 32 | #include <linux/slab.h> |
32 | #include <linux/errno.h> | 33 | #include <linux/errno.h> |
33 | #include <linux/string.h> | 34 | #include <linux/string.h> |
@@ -207,13 +208,16 @@ MODULE_PARM_DESC(overridesize, "Specifies the NAND Flash size overriding the I | |||
207 | #define STATE_CMD_READID 0x0000000A /* read ID */ | 208 | #define STATE_CMD_READID 0x0000000A /* read ID */ |
208 | #define STATE_CMD_ERASE2 0x0000000B /* sector erase second command */ | 209 | #define STATE_CMD_ERASE2 0x0000000B /* sector erase second command */ |
209 | #define STATE_CMD_RESET 0x0000000C /* reset */ | 210 | #define STATE_CMD_RESET 0x0000000C /* reset */ |
211 | #define STATE_CMD_RNDOUT 0x0000000D /* random output command */ | ||
212 | #define STATE_CMD_RNDOUTSTART 0x0000000E /* random output start command */ | ||
210 | #define STATE_CMD_MASK 0x0000000F /* command states mask */ | 213 | #define STATE_CMD_MASK 0x0000000F /* command states mask */ |
211 | 214 | ||
212 | /* After an address is input, the simulator goes to one of these states */ | 215 | /* After an address is input, the simulator goes to one of these states */ |
213 | #define STATE_ADDR_PAGE 0x00000010 /* full (row, column) address is accepted */ | 216 | #define STATE_ADDR_PAGE 0x00000010 /* full (row, column) address is accepted */ |
214 | #define STATE_ADDR_SEC 0x00000020 /* sector address was accepted */ | 217 | #define STATE_ADDR_SEC 0x00000020 /* sector address was accepted */ |
215 | #define STATE_ADDR_ZERO 0x00000030 /* one byte zero address was accepted */ | 218 | #define STATE_ADDR_COLUMN 0x00000030 /* column address was accepted */ |
216 | #define STATE_ADDR_MASK 0x00000030 /* address states mask */ | 219 | #define STATE_ADDR_ZERO 0x00000040 /* one byte zero address was accepted */ |
220 | #define STATE_ADDR_MASK 0x00000070 /* address states mask */ | ||
217 | 221 | ||
218 | /* Durind data input/output the simulator is in these states */ | 222 | /* Durind data input/output the simulator is in these states */ |
219 | #define STATE_DATAIN 0x00000100 /* waiting for data input */ | 223 | #define STATE_DATAIN 0x00000100 /* waiting for data input */ |
@@ -240,7 +244,7 @@ MODULE_PARM_DESC(overridesize, "Specifies the NAND Flash size overriding the I | |||
240 | #define ACTION_OOBOFF 0x00600000 /* add to address OOB offset */ | 244 | #define ACTION_OOBOFF 0x00600000 /* add to address OOB offset */ |
241 | #define ACTION_MASK 0x00700000 /* action mask */ | 245 | #define ACTION_MASK 0x00700000 /* action mask */ |
242 | 246 | ||
243 | #define NS_OPER_NUM 12 /* Number of operations supported by the simulator */ | 247 | #define NS_OPER_NUM 13 /* Number of operations supported by the simulator */ |
244 | #define NS_OPER_STATES 6 /* Maximum number of states in operation */ | 248 | #define NS_OPER_STATES 6 /* Maximum number of states in operation */ |
245 | 249 | ||
246 | #define OPT_ANY 0xFFFFFFFF /* any chip supports this operation */ | 250 | #define OPT_ANY 0xFFFFFFFF /* any chip supports this operation */ |
@@ -373,7 +377,10 @@ static struct nandsim_operations { | |||
373 | {OPT_ANY, {STATE_CMD_READID, STATE_ADDR_ZERO, STATE_DATAOUT_ID, STATE_READY}}, | 377 | {OPT_ANY, {STATE_CMD_READID, STATE_ADDR_ZERO, STATE_DATAOUT_ID, STATE_READY}}, |
374 | /* Large page devices read page */ | 378 | /* Large page devices read page */ |
375 | {OPT_LARGEPAGE, {STATE_CMD_READ0, STATE_ADDR_PAGE, STATE_CMD_READSTART | ACTION_CPY, | 379 | {OPT_LARGEPAGE, {STATE_CMD_READ0, STATE_ADDR_PAGE, STATE_CMD_READSTART | ACTION_CPY, |
376 | STATE_DATAOUT, STATE_READY}} | 380 | STATE_DATAOUT, STATE_READY}}, |
381 | /* Large page devices random page read */ | ||
382 | {OPT_LARGEPAGE, {STATE_CMD_RNDOUT, STATE_ADDR_COLUMN, STATE_CMD_RNDOUTSTART | ACTION_CPY, | ||
383 | STATE_DATAOUT, STATE_READY}}, | ||
377 | }; | 384 | }; |
378 | 385 | ||
379 | struct weak_block { | 386 | struct weak_block { |
@@ -579,7 +586,8 @@ static int init_nandsim(struct mtd_info *mtd) | |||
579 | if (ns->busw == 16) | 586 | if (ns->busw == 16) |
580 | NS_WARN("16-bit flashes support wasn't tested\n"); | 587 | NS_WARN("16-bit flashes support wasn't tested\n"); |
581 | 588 | ||
582 | printk("flash size: %llu MiB\n", ns->geom.totsz >> 20); | 589 | printk("flash size: %llu MiB\n", |
590 | (unsigned long long)ns->geom.totsz >> 20); | ||
583 | printk("page size: %u bytes\n", ns->geom.pgsz); | 591 | printk("page size: %u bytes\n", ns->geom.pgsz); |
584 | printk("OOB area size: %u bytes\n", ns->geom.oobsz); | 592 | printk("OOB area size: %u bytes\n", ns->geom.oobsz); |
585 | printk("sector size: %u KiB\n", ns->geom.secsz >> 10); | 593 | printk("sector size: %u KiB\n", ns->geom.secsz >> 10); |
@@ -588,8 +596,9 @@ static int init_nandsim(struct mtd_info *mtd) | |||
588 | printk("bus width: %u\n", ns->busw); | 596 | printk("bus width: %u\n", ns->busw); |
589 | printk("bits in sector size: %u\n", ns->geom.secshift); | 597 | printk("bits in sector size: %u\n", ns->geom.secshift); |
590 | printk("bits in page size: %u\n", ns->geom.pgshift); | 598 | printk("bits in page size: %u\n", ns->geom.pgshift); |
591 | printk("bits in OOB size: %u\n", ns->geom.oobshift); | 599 | printk("bits in OOB size: %u\n", ns->geom.oobshift); |
592 | printk("flash size with OOB: %llu KiB\n", ns->geom.totszoob >> 10); | 600 | printk("flash size with OOB: %llu KiB\n", |
601 | (unsigned long long)ns->geom.totszoob >> 10); | ||
593 | printk("page address bytes: %u\n", ns->geom.pgaddrbytes); | 602 | printk("page address bytes: %u\n", ns->geom.pgaddrbytes); |
594 | printk("sector address bytes: %u\n", ns->geom.secaddrbytes); | 603 | printk("sector address bytes: %u\n", ns->geom.secaddrbytes); |
595 | printk("options: %#x\n", ns->options); | 604 | printk("options: %#x\n", ns->options); |
@@ -937,12 +946,18 @@ static char *get_state_name(uint32_t state) | |||
937 | return "STATE_CMD_ERASE2"; | 946 | return "STATE_CMD_ERASE2"; |
938 | case STATE_CMD_RESET: | 947 | case STATE_CMD_RESET: |
939 | return "STATE_CMD_RESET"; | 948 | return "STATE_CMD_RESET"; |
949 | case STATE_CMD_RNDOUT: | ||
950 | return "STATE_CMD_RNDOUT"; | ||
951 | case STATE_CMD_RNDOUTSTART: | ||
952 | return "STATE_CMD_RNDOUTSTART"; | ||
940 | case STATE_ADDR_PAGE: | 953 | case STATE_ADDR_PAGE: |
941 | return "STATE_ADDR_PAGE"; | 954 | return "STATE_ADDR_PAGE"; |
942 | case STATE_ADDR_SEC: | 955 | case STATE_ADDR_SEC: |
943 | return "STATE_ADDR_SEC"; | 956 | return "STATE_ADDR_SEC"; |
944 | case STATE_ADDR_ZERO: | 957 | case STATE_ADDR_ZERO: |
945 | return "STATE_ADDR_ZERO"; | 958 | return "STATE_ADDR_ZERO"; |
959 | case STATE_ADDR_COLUMN: | ||
960 | return "STATE_ADDR_COLUMN"; | ||
946 | case STATE_DATAIN: | 961 | case STATE_DATAIN: |
947 | return "STATE_DATAIN"; | 962 | return "STATE_DATAIN"; |
948 | case STATE_DATAOUT: | 963 | case STATE_DATAOUT: |
@@ -973,6 +988,7 @@ static int check_command(int cmd) | |||
973 | switch (cmd) { | 988 | switch (cmd) { |
974 | 989 | ||
975 | case NAND_CMD_READ0: | 990 | case NAND_CMD_READ0: |
991 | case NAND_CMD_READ1: | ||
976 | case NAND_CMD_READSTART: | 992 | case NAND_CMD_READSTART: |
977 | case NAND_CMD_PAGEPROG: | 993 | case NAND_CMD_PAGEPROG: |
978 | case NAND_CMD_READOOB: | 994 | case NAND_CMD_READOOB: |
@@ -982,7 +998,8 @@ static int check_command(int cmd) | |||
982 | case NAND_CMD_READID: | 998 | case NAND_CMD_READID: |
983 | case NAND_CMD_ERASE2: | 999 | case NAND_CMD_ERASE2: |
984 | case NAND_CMD_RESET: | 1000 | case NAND_CMD_RESET: |
985 | case NAND_CMD_READ1: | 1001 | case NAND_CMD_RNDOUT: |
1002 | case NAND_CMD_RNDOUTSTART: | ||
986 | return 0; | 1003 | return 0; |
987 | 1004 | ||
988 | case NAND_CMD_STATUS_MULTI: | 1005 | case NAND_CMD_STATUS_MULTI: |
@@ -1021,6 +1038,10 @@ static uint32_t get_state_by_command(unsigned command) | |||
1021 | return STATE_CMD_ERASE2; | 1038 | return STATE_CMD_ERASE2; |
1022 | case NAND_CMD_RESET: | 1039 | case NAND_CMD_RESET: |
1023 | return STATE_CMD_RESET; | 1040 | return STATE_CMD_RESET; |
1041 | case NAND_CMD_RNDOUT: | ||
1042 | return STATE_CMD_RNDOUT; | ||
1043 | case NAND_CMD_RNDOUTSTART: | ||
1044 | return STATE_CMD_RNDOUTSTART; | ||
1024 | } | 1045 | } |
1025 | 1046 | ||
1026 | NS_ERR("get_state_by_command: unknown command, BUG\n"); | 1047 | NS_ERR("get_state_by_command: unknown command, BUG\n"); |
@@ -1582,6 +1603,11 @@ static void switch_state(struct nandsim *ns) | |||
1582 | ns->regs.num = 1; | 1603 | ns->regs.num = 1; |
1583 | break; | 1604 | break; |
1584 | 1605 | ||
1606 | case STATE_ADDR_COLUMN: | ||
1607 | /* Column address is always 2 bytes */ | ||
1608 | ns->regs.num = ns->geom.pgaddrbytes - ns->geom.secaddrbytes; | ||
1609 | break; | ||
1610 | |||
1585 | default: | 1611 | default: |
1586 | NS_ERR("switch_state: BUG! unknown address state\n"); | 1612 | NS_ERR("switch_state: BUG! unknown address state\n"); |
1587 | } | 1613 | } |
@@ -1693,15 +1719,21 @@ static void ns_nand_write_byte(struct mtd_info *mtd, u_char byte) | |||
1693 | return; | 1719 | return; |
1694 | } | 1720 | } |
1695 | 1721 | ||
1696 | /* | 1722 | /* Check that the command byte is correct */ |
1697 | * Chip might still be in STATE_DATAOUT | 1723 | if (check_command(byte)) { |
1698 | * (if OPT_AUTOINCR feature is supported), STATE_DATAOUT_STATUS or | 1724 | NS_ERR("write_byte: unknown command %#x\n", (uint)byte); |
1699 | * STATE_DATAOUT_STATUS_M state. If so, switch state. | 1725 | return; |
1700 | */ | 1726 | } |
1727 | |||
1701 | if (NS_STATE(ns->state) == STATE_DATAOUT_STATUS | 1728 | if (NS_STATE(ns->state) == STATE_DATAOUT_STATUS |
1702 | || NS_STATE(ns->state) == STATE_DATAOUT_STATUS_M | 1729 | || NS_STATE(ns->state) == STATE_DATAOUT_STATUS_M |
1703 | || ((ns->options & OPT_AUTOINCR) && NS_STATE(ns->state) == STATE_DATAOUT)) | 1730 | || NS_STATE(ns->state) == STATE_DATAOUT) { |
1731 | int row = ns->regs.row; | ||
1732 | |||
1704 | switch_state(ns); | 1733 | switch_state(ns); |
1734 | if (byte == NAND_CMD_RNDOUT) | ||
1735 | ns->regs.row = row; | ||
1736 | } | ||
1705 | 1737 | ||
1706 | /* Check if chip is expecting command */ | 1738 | /* Check if chip is expecting command */ |
1707 | if (NS_STATE(ns->nxstate) != STATE_UNKNOWN && !(ns->nxstate & STATE_CMD_MASK)) { | 1739 | if (NS_STATE(ns->nxstate) != STATE_UNKNOWN && !(ns->nxstate & STATE_CMD_MASK)) { |
@@ -1715,12 +1747,6 @@ static void ns_nand_write_byte(struct mtd_info *mtd, u_char byte) | |||
1715 | switch_to_ready_state(ns, NS_STATUS_FAILED(ns)); | 1747 | switch_to_ready_state(ns, NS_STATUS_FAILED(ns)); |
1716 | } | 1748 | } |
1717 | 1749 | ||
1718 | /* Check that the command byte is correct */ | ||
1719 | if (check_command(byte)) { | ||
1720 | NS_ERR("write_byte: unknown command %#x\n", (uint)byte); | ||
1721 | return; | ||
1722 | } | ||
1723 | |||
1724 | NS_DBG("command byte corresponding to %s state accepted\n", | 1750 | NS_DBG("command byte corresponding to %s state accepted\n", |
1725 | get_state_name(get_state_by_command(byte))); | 1751 | get_state_name(get_state_by_command(byte))); |
1726 | ns->regs.command = byte; | 1752 | ns->regs.command = byte; |