diff options
Diffstat (limited to 'drivers/mtd/nand/nandsim.c')
-rw-r--r-- | drivers/mtd/nand/nandsim.c | 162 |
1 files changed, 81 insertions, 81 deletions
diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c index 754b6ed7ce14..de4500395300 100644 --- a/drivers/mtd/nand/nandsim.c +++ b/drivers/mtd/nand/nandsim.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Author: Artem B. Bityuckiy <dedekind@oktetlabs.ru>, <dedekind@infradead.org> | 4 | * Author: Artem B. Bityuckiy <dedekind@oktetlabs.ru>, <dedekind@infradead.org> |
5 | * | 5 | * |
6 | * Copyright (C) 2004 Nokia Corporation | 6 | * Copyright (C) 2004 Nokia Corporation |
7 | * | 7 | * |
8 | * Note: NS means "NAND Simulator". | 8 | * Note: NS means "NAND Simulator". |
9 | * Note: Input means input TO flash chip, output means output FROM chip. | 9 | * Note: Input means input TO flash chip, output means output FROM chip. |
@@ -126,7 +126,7 @@ MODULE_PARM_DESC(dbg, "Output debug information if not zero"); | |||
126 | 126 | ||
127 | /* The largest possible page size */ | 127 | /* The largest possible page size */ |
128 | #define NS_LARGEST_PAGE_SIZE 2048 | 128 | #define NS_LARGEST_PAGE_SIZE 2048 |
129 | 129 | ||
130 | /* The prefix for simulator output */ | 130 | /* The prefix for simulator output */ |
131 | #define NS_OUTPUT_PREFIX "[nandsim]" | 131 | #define NS_OUTPUT_PREFIX "[nandsim]" |
132 | 132 | ||
@@ -145,7 +145,7 @@ MODULE_PARM_DESC(dbg, "Output debug information if not zero"); | |||
145 | do { if (do_delays) udelay(us); } while(0) | 145 | do { if (do_delays) udelay(us); } while(0) |
146 | #define NS_MDELAY(us) \ | 146 | #define NS_MDELAY(us) \ |
147 | do { if (do_delays) mdelay(us); } while(0) | 147 | do { if (do_delays) mdelay(us); } while(0) |
148 | 148 | ||
149 | /* Is the nandsim structure initialized ? */ | 149 | /* Is the nandsim structure initialized ? */ |
150 | #define NS_IS_INITIALIZED(ns) ((ns)->geom.totsz != 0) | 150 | #define NS_IS_INITIALIZED(ns) ((ns)->geom.totsz != 0) |
151 | 151 | ||
@@ -153,12 +153,12 @@ MODULE_PARM_DESC(dbg, "Output debug information if not zero"); | |||
153 | #define NS_STATUS_OK(ns) (NAND_STATUS_READY | (NAND_STATUS_WP * ((ns)->lines.wp == 0))) | 153 | #define NS_STATUS_OK(ns) (NAND_STATUS_READY | (NAND_STATUS_WP * ((ns)->lines.wp == 0))) |
154 | 154 | ||
155 | /* Operation failed completion status */ | 155 | /* Operation failed completion status */ |
156 | #define NS_STATUS_FAILED(ns) (NAND_STATUS_FAIL | NS_STATUS_OK(ns)) | 156 | #define NS_STATUS_FAILED(ns) (NAND_STATUS_FAIL | NS_STATUS_OK(ns)) |
157 | 157 | ||
158 | /* Calculate the page offset in flash RAM image by (row, column) address */ | 158 | /* Calculate the page offset in flash RAM image by (row, column) address */ |
159 | #define NS_RAW_OFFSET(ns) \ | 159 | #define NS_RAW_OFFSET(ns) \ |
160 | (((ns)->regs.row << (ns)->geom.pgshift) + ((ns)->regs.row * (ns)->geom.oobsz) + (ns)->regs.column) | 160 | (((ns)->regs.row << (ns)->geom.pgshift) + ((ns)->regs.row * (ns)->geom.oobsz) + (ns)->regs.column) |
161 | 161 | ||
162 | /* Calculate the OOB offset in flash RAM image by (row, column) address */ | 162 | /* Calculate the OOB offset in flash RAM image by (row, column) address */ |
163 | #define NS_RAW_OFFSET_OOB(ns) (NS_RAW_OFFSET(ns) + ns->geom.pgsz) | 163 | #define NS_RAW_OFFSET_OOB(ns) (NS_RAW_OFFSET(ns) + ns->geom.pgsz) |
164 | 164 | ||
@@ -223,15 +223,15 @@ MODULE_PARM_DESC(dbg, "Output debug information if not zero"); | |||
223 | 223 | ||
224 | /* Remove action bits ftom state */ | 224 | /* Remove action bits ftom state */ |
225 | #define NS_STATE(x) ((x) & ~ACTION_MASK) | 225 | #define NS_STATE(x) ((x) & ~ACTION_MASK) |
226 | 226 | ||
227 | /* | 227 | /* |
228 | * Maximum previous states which need to be saved. Currently saving is | 228 | * Maximum previous states which need to be saved. Currently saving is |
229 | * only needed for page programm operation with preceeded read command | 229 | * only needed for page programm operation with preceeded read command |
230 | * (which is only valid for 512-byte pages). | 230 | * (which is only valid for 512-byte pages). |
231 | */ | 231 | */ |
232 | #define NS_MAX_PREVSTATES 1 | 232 | #define NS_MAX_PREVSTATES 1 |
233 | 233 | ||
234 | /* | 234 | /* |
235 | * The structure which describes all the internal simulator data. | 235 | * The structure which describes all the internal simulator data. |
236 | */ | 236 | */ |
237 | struct nandsim { | 237 | struct nandsim { |
@@ -242,7 +242,7 @@ struct nandsim { | |||
242 | uint32_t options; /* chip's characteristic bits */ | 242 | uint32_t options; /* chip's characteristic bits */ |
243 | uint32_t state; /* current chip state */ | 243 | uint32_t state; /* current chip state */ |
244 | uint32_t nxstate; /* next expected state */ | 244 | uint32_t nxstate; /* next expected state */ |
245 | 245 | ||
246 | uint32_t *op; /* current operation, NULL operations isn't known yet */ | 246 | uint32_t *op; /* current operation, NULL operations isn't known yet */ |
247 | uint32_t pstates[NS_MAX_PREVSTATES]; /* previous states */ | 247 | uint32_t pstates[NS_MAX_PREVSTATES]; /* previous states */ |
248 | uint16_t npstates; /* number of previous states saved */ | 248 | uint16_t npstates; /* number of previous states saved */ |
@@ -413,7 +413,7 @@ init_nandsim(struct mtd_info *mtd) | |||
413 | ns->geom.secaddrbytes = 3; | 413 | ns->geom.secaddrbytes = 3; |
414 | } | 414 | } |
415 | } | 415 | } |
416 | 416 | ||
417 | /* Detect how many ID bytes the NAND chip outputs */ | 417 | /* Detect how many ID bytes the NAND chip outputs */ |
418 | for (i = 0; nand_flash_ids[i].name != NULL; i++) { | 418 | for (i = 0; nand_flash_ids[i].name != NULL; i++) { |
419 | if (second_id_byte != nand_flash_ids[i].id) | 419 | if (second_id_byte != nand_flash_ids[i].id) |
@@ -444,7 +444,7 @@ init_nandsim(struct mtd_info *mtd) | |||
444 | #ifdef CONFIG_NS_ABS_POS | 444 | #ifdef CONFIG_NS_ABS_POS |
445 | ns->mem.byte = ioremap(CONFIG_NS_ABS_POS, ns->geom.totszoob); | 445 | ns->mem.byte = ioremap(CONFIG_NS_ABS_POS, ns->geom.totszoob); |
446 | if (!ns->mem.byte) { | 446 | if (!ns->mem.byte) { |
447 | NS_ERR("init_nandsim: failed to map the NAND flash image at address %p\n", | 447 | NS_ERR("init_nandsim: failed to map the NAND flash image at address %p\n", |
448 | (void *)CONFIG_NS_ABS_POS); | 448 | (void *)CONFIG_NS_ABS_POS); |
449 | return -ENOMEM; | 449 | return -ENOMEM; |
450 | } | 450 | } |
@@ -567,7 +567,7 @@ static int | |||
567 | check_command(int cmd) | 567 | check_command(int cmd) |
568 | { | 568 | { |
569 | switch (cmd) { | 569 | switch (cmd) { |
570 | 570 | ||
571 | case NAND_CMD_READ0: | 571 | case NAND_CMD_READ0: |
572 | case NAND_CMD_READSTART: | 572 | case NAND_CMD_READSTART: |
573 | case NAND_CMD_PAGEPROG: | 573 | case NAND_CMD_PAGEPROG: |
@@ -580,7 +580,7 @@ check_command(int cmd) | |||
580 | case NAND_CMD_RESET: | 580 | case NAND_CMD_RESET: |
581 | case NAND_CMD_READ1: | 581 | case NAND_CMD_READ1: |
582 | return 0; | 582 | return 0; |
583 | 583 | ||
584 | case NAND_CMD_STATUS_MULTI: | 584 | case NAND_CMD_STATUS_MULTI: |
585 | default: | 585 | default: |
586 | return 1; | 586 | return 1; |
@@ -631,7 +631,7 @@ static inline void | |||
631 | accept_addr_byte(struct nandsim *ns, u_char bt) | 631 | accept_addr_byte(struct nandsim *ns, u_char bt) |
632 | { | 632 | { |
633 | uint byte = (uint)bt; | 633 | uint byte = (uint)bt; |
634 | 634 | ||
635 | if (ns->regs.count < (ns->geom.pgaddrbytes - ns->geom.secaddrbytes)) | 635 | if (ns->regs.count < (ns->geom.pgaddrbytes - ns->geom.secaddrbytes)) |
636 | ns->regs.column |= (byte << 8 * ns->regs.count); | 636 | ns->regs.column |= (byte << 8 * ns->regs.count); |
637 | else { | 637 | else { |
@@ -642,11 +642,11 @@ accept_addr_byte(struct nandsim *ns, u_char bt) | |||
642 | 642 | ||
643 | return; | 643 | return; |
644 | } | 644 | } |
645 | 645 | ||
646 | /* | 646 | /* |
647 | * Switch to STATE_READY state. | 647 | * Switch to STATE_READY state. |
648 | */ | 648 | */ |
649 | static inline void | 649 | static inline void |
650 | switch_to_ready_state(struct nandsim *ns, u_char status) | 650 | switch_to_ready_state(struct nandsim *ns, u_char status) |
651 | { | 651 | { |
652 | NS_DBG("switch_to_ready_state: switch to %s state\n", get_state_name(STATE_READY)); | 652 | NS_DBG("switch_to_ready_state: switch to %s state\n", get_state_name(STATE_READY)); |
@@ -675,7 +675,7 @@ switch_to_ready_state(struct nandsim *ns, u_char status) | |||
675 | * (for example program from the second half and read from the | 675 | * (for example program from the second half and read from the |
676 | * second half operations both begin with the READ1 command). In this | 676 | * second half operations both begin with the READ1 command). In this |
677 | * case the ns->pstates[] array contains previous states. | 677 | * case the ns->pstates[] array contains previous states. |
678 | * | 678 | * |
679 | * Thus, the function tries to find operation containing the following | 679 | * Thus, the function tries to find operation containing the following |
680 | * states (if the 'flag' parameter is 0): | 680 | * states (if the 'flag' parameter is 0): |
681 | * ns->pstates[0], ... ns->pstates[ns->npstates], ns->state | 681 | * ns->pstates[0], ... ns->pstates[ns->npstates], ns->state |
@@ -683,7 +683,7 @@ switch_to_ready_state(struct nandsim *ns, u_char status) | |||
683 | * If (one and only one) matching operation is found, it is accepted ( | 683 | * If (one and only one) matching operation is found, it is accepted ( |
684 | * ns->ops, ns->state, ns->nxstate are initialized, ns->npstate is | 684 | * ns->ops, ns->state, ns->nxstate are initialized, ns->npstate is |
685 | * zeroed). | 685 | * zeroed). |
686 | * | 686 | * |
687 | * If there are several maches, the current state is pushed to the | 687 | * If there are several maches, the current state is pushed to the |
688 | * ns->pstates. | 688 | * ns->pstates. |
689 | * | 689 | * |
@@ -692,7 +692,7 @@ switch_to_ready_state(struct nandsim *ns, u_char status) | |||
692 | * In such situation the function is called with 'flag' != 0, and the | 692 | * In such situation the function is called with 'flag' != 0, and the |
693 | * operation is searched using the following pattern: | 693 | * operation is searched using the following pattern: |
694 | * ns->pstates[0], ... ns->pstates[ns->npstates], <address input> | 694 | * ns->pstates[0], ... ns->pstates[ns->npstates], <address input> |
695 | * | 695 | * |
696 | * It is supposed that this pattern must either match one operation on | 696 | * It is supposed that this pattern must either match one operation on |
697 | * none. There can't be ambiguity in that case. | 697 | * none. There can't be ambiguity in that case. |
698 | * | 698 | * |
@@ -711,15 +711,15 @@ find_operation(struct nandsim *ns, uint32_t flag) | |||
711 | { | 711 | { |
712 | int opsfound = 0; | 712 | int opsfound = 0; |
713 | int i, j, idx = 0; | 713 | int i, j, idx = 0; |
714 | 714 | ||
715 | for (i = 0; i < NS_OPER_NUM; i++) { | 715 | for (i = 0; i < NS_OPER_NUM; i++) { |
716 | 716 | ||
717 | int found = 1; | 717 | int found = 1; |
718 | 718 | ||
719 | if (!(ns->options & ops[i].reqopts)) | 719 | if (!(ns->options & ops[i].reqopts)) |
720 | /* Ignore operations we can't perform */ | 720 | /* Ignore operations we can't perform */ |
721 | continue; | 721 | continue; |
722 | 722 | ||
723 | if (flag) { | 723 | if (flag) { |
724 | if (!(ops[i].states[ns->npstates] & STATE_ADDR_MASK)) | 724 | if (!(ops[i].states[ns->npstates] & STATE_ADDR_MASK)) |
725 | continue; | 725 | continue; |
@@ -728,7 +728,7 @@ find_operation(struct nandsim *ns, uint32_t flag) | |||
728 | continue; | 728 | continue; |
729 | } | 729 | } |
730 | 730 | ||
731 | for (j = 0; j < ns->npstates; j++) | 731 | for (j = 0; j < ns->npstates; j++) |
732 | if (NS_STATE(ops[i].states[j]) != NS_STATE(ns->pstates[j]) | 732 | if (NS_STATE(ops[i].states[j]) != NS_STATE(ns->pstates[j]) |
733 | && (ns->options & ops[idx].reqopts)) { | 733 | && (ns->options & ops[idx].reqopts)) { |
734 | found = 0; | 734 | found = 0; |
@@ -745,7 +745,7 @@ find_operation(struct nandsim *ns, uint32_t flag) | |||
745 | /* Exact match */ | 745 | /* Exact match */ |
746 | ns->op = &ops[idx].states[0]; | 746 | ns->op = &ops[idx].states[0]; |
747 | if (flag) { | 747 | if (flag) { |
748 | /* | 748 | /* |
749 | * In this case the find_operation function was | 749 | * In this case the find_operation function was |
750 | * called when address has just began input. But it isn't | 750 | * called when address has just began input. But it isn't |
751 | * yet fully input and the current state must | 751 | * yet fully input and the current state must |
@@ -763,7 +763,7 @@ find_operation(struct nandsim *ns, uint32_t flag) | |||
763 | idx, get_state_name(ns->state), get_state_name(ns->nxstate)); | 763 | idx, get_state_name(ns->state), get_state_name(ns->nxstate)); |
764 | return 0; | 764 | return 0; |
765 | } | 765 | } |
766 | 766 | ||
767 | if (opsfound == 0) { | 767 | if (opsfound == 0) { |
768 | /* Nothing was found. Try to ignore previous commands (if any) and search again */ | 768 | /* Nothing was found. Try to ignore previous commands (if any) and search again */ |
769 | if (ns->npstates != 0) { | 769 | if (ns->npstates != 0) { |
@@ -777,13 +777,13 @@ find_operation(struct nandsim *ns, uint32_t flag) | |||
777 | switch_to_ready_state(ns, NS_STATUS_FAILED(ns)); | 777 | switch_to_ready_state(ns, NS_STATUS_FAILED(ns)); |
778 | return -2; | 778 | return -2; |
779 | } | 779 | } |
780 | 780 | ||
781 | if (flag) { | 781 | if (flag) { |
782 | /* This shouldn't happen */ | 782 | /* This shouldn't happen */ |
783 | NS_DBG("find_operation: BUG, operation must be known if address is input\n"); | 783 | NS_DBG("find_operation: BUG, operation must be known if address is input\n"); |
784 | return -2; | 784 | return -2; |
785 | } | 785 | } |
786 | 786 | ||
787 | NS_DBG("find_operation: there is still ambiguity\n"); | 787 | NS_DBG("find_operation: there is still ambiguity\n"); |
788 | 788 | ||
789 | ns->pstates[ns->npstates++] = ns->state; | 789 | ns->pstates[ns->npstates++] = ns->state; |
@@ -803,7 +803,7 @@ do_state_action(struct nandsim *ns, uint32_t action) | |||
803 | int busdiv = ns->busw == 8 ? 1 : 2; | 803 | int busdiv = ns->busw == 8 ? 1 : 2; |
804 | 804 | ||
805 | action &= ACTION_MASK; | 805 | action &= ACTION_MASK; |
806 | 806 | ||
807 | /* Check that page address input is correct */ | 807 | /* Check that page address input is correct */ |
808 | if (action != ACTION_SECERASE && ns->regs.row >= ns->geom.pgnum) { | 808 | if (action != ACTION_SECERASE && ns->regs.row >= ns->geom.pgnum) { |
809 | NS_WARN("do_state_action: wrong page number (%#x)\n", ns->regs.row); | 809 | NS_WARN("do_state_action: wrong page number (%#x)\n", ns->regs.row); |
@@ -827,14 +827,14 @@ do_state_action(struct nandsim *ns, uint32_t action) | |||
827 | 827 | ||
828 | NS_DBG("do_state_action: (ACTION_CPY:) copy %d bytes to int buf, raw offset %d\n", | 828 | NS_DBG("do_state_action: (ACTION_CPY:) copy %d bytes to int buf, raw offset %d\n", |
829 | num, NS_RAW_OFFSET(ns) + ns->regs.off); | 829 | num, NS_RAW_OFFSET(ns) + ns->regs.off); |
830 | 830 | ||
831 | if (ns->regs.off == 0) | 831 | if (ns->regs.off == 0) |
832 | NS_LOG("read page %d\n", ns->regs.row); | 832 | NS_LOG("read page %d\n", ns->regs.row); |
833 | else if (ns->regs.off < ns->geom.pgsz) | 833 | else if (ns->regs.off < ns->geom.pgsz) |
834 | NS_LOG("read page %d (second half)\n", ns->regs.row); | 834 | NS_LOG("read page %d (second half)\n", ns->regs.row); |
835 | else | 835 | else |
836 | NS_LOG("read OOB of page %d\n", ns->regs.row); | 836 | NS_LOG("read OOB of page %d\n", ns->regs.row); |
837 | 837 | ||
838 | NS_UDELAY(access_delay); | 838 | NS_UDELAY(access_delay); |
839 | NS_UDELAY(input_cycle * ns->geom.pgsz / 1000 / busdiv); | 839 | NS_UDELAY(input_cycle * ns->geom.pgsz / 1000 / busdiv); |
840 | 840 | ||
@@ -844,30 +844,30 @@ do_state_action(struct nandsim *ns, uint32_t action) | |||
844 | /* | 844 | /* |
845 | * Erase sector. | 845 | * Erase sector. |
846 | */ | 846 | */ |
847 | 847 | ||
848 | if (ns->lines.wp) { | 848 | if (ns->lines.wp) { |
849 | NS_ERR("do_state_action: device is write-protected, ignore sector erase\n"); | 849 | NS_ERR("do_state_action: device is write-protected, ignore sector erase\n"); |
850 | return -1; | 850 | return -1; |
851 | } | 851 | } |
852 | 852 | ||
853 | if (ns->regs.row >= ns->geom.pgnum - ns->geom.pgsec | 853 | if (ns->regs.row >= ns->geom.pgnum - ns->geom.pgsec |
854 | || (ns->regs.row & ~(ns->geom.secsz - 1))) { | 854 | || (ns->regs.row & ~(ns->geom.secsz - 1))) { |
855 | NS_ERR("do_state_action: wrong sector address (%#x)\n", ns->regs.row); | 855 | NS_ERR("do_state_action: wrong sector address (%#x)\n", ns->regs.row); |
856 | return -1; | 856 | return -1; |
857 | } | 857 | } |
858 | 858 | ||
859 | ns->regs.row = (ns->regs.row << | 859 | ns->regs.row = (ns->regs.row << |
860 | 8 * (ns->geom.pgaddrbytes - ns->geom.secaddrbytes)) | ns->regs.column; | 860 | 8 * (ns->geom.pgaddrbytes - ns->geom.secaddrbytes)) | ns->regs.column; |
861 | ns->regs.column = 0; | 861 | ns->regs.column = 0; |
862 | 862 | ||
863 | NS_DBG("do_state_action: erase sector at address %#x, off = %d\n", | 863 | NS_DBG("do_state_action: erase sector at address %#x, off = %d\n", |
864 | ns->regs.row, NS_RAW_OFFSET(ns)); | 864 | ns->regs.row, NS_RAW_OFFSET(ns)); |
865 | NS_LOG("erase sector %d\n", ns->regs.row >> (ns->geom.secshift - ns->geom.pgshift)); | 865 | NS_LOG("erase sector %d\n", ns->regs.row >> (ns->geom.secshift - ns->geom.pgshift)); |
866 | 866 | ||
867 | memset(ns->mem.byte + NS_RAW_OFFSET(ns), 0xFF, ns->geom.secszoob); | 867 | memset(ns->mem.byte + NS_RAW_OFFSET(ns), 0xFF, ns->geom.secszoob); |
868 | 868 | ||
869 | NS_MDELAY(erase_delay); | 869 | NS_MDELAY(erase_delay); |
870 | 870 | ||
871 | break; | 871 | break; |
872 | 872 | ||
873 | case ACTION_PRGPAGE: | 873 | case ACTION_PRGPAGE: |
@@ -893,12 +893,12 @@ do_state_action(struct nandsim *ns, uint32_t action) | |||
893 | NS_DBG("do_state_action: copy %d bytes from int buf to (%#x, %#x), raw off = %d\n", | 893 | NS_DBG("do_state_action: copy %d bytes from int buf to (%#x, %#x), raw off = %d\n", |
894 | num, ns->regs.row, ns->regs.column, NS_RAW_OFFSET(ns) + ns->regs.off); | 894 | num, ns->regs.row, ns->regs.column, NS_RAW_OFFSET(ns) + ns->regs.off); |
895 | NS_LOG("programm page %d\n", ns->regs.row); | 895 | NS_LOG("programm page %d\n", ns->regs.row); |
896 | 896 | ||
897 | NS_UDELAY(programm_delay); | 897 | NS_UDELAY(programm_delay); |
898 | NS_UDELAY(output_cycle * ns->geom.pgsz / 1000 / busdiv); | 898 | NS_UDELAY(output_cycle * ns->geom.pgsz / 1000 / busdiv); |
899 | 899 | ||
900 | break; | 900 | break; |
901 | 901 | ||
902 | case ACTION_ZEROOFF: | 902 | case ACTION_ZEROOFF: |
903 | NS_DBG("do_state_action: set internal offset to 0\n"); | 903 | NS_DBG("do_state_action: set internal offset to 0\n"); |
904 | ns->regs.off = 0; | 904 | ns->regs.off = 0; |
@@ -918,7 +918,7 @@ do_state_action(struct nandsim *ns, uint32_t action) | |||
918 | NS_DBG("do_state_action: set internal offset to %d\n", ns->geom.pgsz); | 918 | NS_DBG("do_state_action: set internal offset to %d\n", ns->geom.pgsz); |
919 | ns->regs.off = ns->geom.pgsz; | 919 | ns->regs.off = ns->geom.pgsz; |
920 | break; | 920 | break; |
921 | 921 | ||
922 | default: | 922 | default: |
923 | NS_DBG("do_state_action: BUG! unknown action\n"); | 923 | NS_DBG("do_state_action: BUG! unknown action\n"); |
924 | } | 924 | } |
@@ -937,7 +937,7 @@ switch_state(struct nandsim *ns) | |||
937 | * The current operation have already been identified. | 937 | * The current operation have already been identified. |
938 | * Just follow the states chain. | 938 | * Just follow the states chain. |
939 | */ | 939 | */ |
940 | 940 | ||
941 | ns->stateidx += 1; | 941 | ns->stateidx += 1; |
942 | ns->state = ns->nxstate; | 942 | ns->state = ns->nxstate; |
943 | ns->nxstate = ns->op[ns->stateidx + 1]; | 943 | ns->nxstate = ns->op[ns->stateidx + 1]; |
@@ -951,14 +951,14 @@ switch_state(struct nandsim *ns) | |||
951 | switch_to_ready_state(ns, NS_STATUS_FAILED(ns)); | 951 | switch_to_ready_state(ns, NS_STATUS_FAILED(ns)); |
952 | return; | 952 | return; |
953 | } | 953 | } |
954 | 954 | ||
955 | } else { | 955 | } else { |
956 | /* | 956 | /* |
957 | * We don't yet know which operation we perform. | 957 | * We don't yet know which operation we perform. |
958 | * Try to identify it. | 958 | * Try to identify it. |
959 | */ | 959 | */ |
960 | 960 | ||
961 | /* | 961 | /* |
962 | * The only event causing the switch_state function to | 962 | * The only event causing the switch_state function to |
963 | * be called with yet unknown operation is new command. | 963 | * be called with yet unknown operation is new command. |
964 | */ | 964 | */ |
@@ -987,7 +987,7 @@ switch_state(struct nandsim *ns) | |||
987 | */ | 987 | */ |
988 | 988 | ||
989 | u_char status = NS_STATUS_OK(ns); | 989 | u_char status = NS_STATUS_OK(ns); |
990 | 990 | ||
991 | /* In case of data states, see if all bytes were input/output */ | 991 | /* In case of data states, see if all bytes were input/output */ |
992 | if ((ns->state & (STATE_DATAIN_MASK | STATE_DATAOUT_MASK)) | 992 | if ((ns->state & (STATE_DATAIN_MASK | STATE_DATAOUT_MASK)) |
993 | && ns->regs.count != ns->regs.num) { | 993 | && ns->regs.count != ns->regs.num) { |
@@ -995,17 +995,17 @@ switch_state(struct nandsim *ns) | |||
995 | ns->regs.num - ns->regs.count); | 995 | ns->regs.num - ns->regs.count); |
996 | status = NS_STATUS_FAILED(ns); | 996 | status = NS_STATUS_FAILED(ns); |
997 | } | 997 | } |
998 | 998 | ||
999 | NS_DBG("switch_state: operation complete, switch to STATE_READY state\n"); | 999 | NS_DBG("switch_state: operation complete, switch to STATE_READY state\n"); |
1000 | 1000 | ||
1001 | switch_to_ready_state(ns, status); | 1001 | switch_to_ready_state(ns, status); |
1002 | 1002 | ||
1003 | return; | 1003 | return; |
1004 | } else if (ns->nxstate & (STATE_DATAIN_MASK | STATE_DATAOUT_MASK)) { | 1004 | } else if (ns->nxstate & (STATE_DATAIN_MASK | STATE_DATAOUT_MASK)) { |
1005 | /* | 1005 | /* |
1006 | * If the next state is data input/output, switch to it now | 1006 | * If the next state is data input/output, switch to it now |
1007 | */ | 1007 | */ |
1008 | 1008 | ||
1009 | ns->state = ns->nxstate; | 1009 | ns->state = ns->nxstate; |
1010 | ns->nxstate = ns->op[++ns->stateidx + 1]; | 1010 | ns->nxstate = ns->op[++ns->stateidx + 1]; |
1011 | ns->regs.num = ns->regs.count = 0; | 1011 | ns->regs.num = ns->regs.count = 0; |
@@ -1023,16 +1023,16 @@ switch_state(struct nandsim *ns) | |||
1023 | case STATE_DATAOUT: | 1023 | case STATE_DATAOUT: |
1024 | ns->regs.num = ns->geom.pgszoob - ns->regs.off - ns->regs.column; | 1024 | ns->regs.num = ns->geom.pgszoob - ns->regs.off - ns->regs.column; |
1025 | break; | 1025 | break; |
1026 | 1026 | ||
1027 | case STATE_DATAOUT_ID: | 1027 | case STATE_DATAOUT_ID: |
1028 | ns->regs.num = ns->geom.idbytes; | 1028 | ns->regs.num = ns->geom.idbytes; |
1029 | break; | 1029 | break; |
1030 | 1030 | ||
1031 | case STATE_DATAOUT_STATUS: | 1031 | case STATE_DATAOUT_STATUS: |
1032 | case STATE_DATAOUT_STATUS_M: | 1032 | case STATE_DATAOUT_STATUS_M: |
1033 | ns->regs.count = ns->regs.num = 0; | 1033 | ns->regs.count = ns->regs.num = 0; |
1034 | break; | 1034 | break; |
1035 | 1035 | ||
1036 | default: | 1036 | default: |
1037 | NS_ERR("switch_state: BUG! unknown data state\n"); | 1037 | NS_ERR("switch_state: BUG! unknown data state\n"); |
1038 | } | 1038 | } |
@@ -1044,16 +1044,16 @@ switch_state(struct nandsim *ns) | |||
1044 | */ | 1044 | */ |
1045 | 1045 | ||
1046 | ns->regs.count = 0; | 1046 | ns->regs.count = 0; |
1047 | 1047 | ||
1048 | switch (NS_STATE(ns->nxstate)) { | 1048 | switch (NS_STATE(ns->nxstate)) { |
1049 | case STATE_ADDR_PAGE: | 1049 | case STATE_ADDR_PAGE: |
1050 | ns->regs.num = ns->geom.pgaddrbytes; | 1050 | ns->regs.num = ns->geom.pgaddrbytes; |
1051 | 1051 | ||
1052 | break; | 1052 | break; |
1053 | case STATE_ADDR_SEC: | 1053 | case STATE_ADDR_SEC: |
1054 | ns->regs.num = ns->geom.secaddrbytes; | 1054 | ns->regs.num = ns->geom.secaddrbytes; |
1055 | break; | 1055 | break; |
1056 | 1056 | ||
1057 | case STATE_ADDR_ZERO: | 1057 | case STATE_ADDR_ZERO: |
1058 | ns->regs.num = 1; | 1058 | ns->regs.num = 1; |
1059 | break; | 1059 | break; |
@@ -1062,7 +1062,7 @@ switch_state(struct nandsim *ns) | |||
1062 | NS_ERR("switch_state: BUG! unknown address state\n"); | 1062 | NS_ERR("switch_state: BUG! unknown address state\n"); |
1063 | } | 1063 | } |
1064 | } else { | 1064 | } else { |
1065 | /* | 1065 | /* |
1066 | * Just reset internal counters. | 1066 | * Just reset internal counters. |
1067 | */ | 1067 | */ |
1068 | 1068 | ||
@@ -1184,7 +1184,7 @@ ns_nand_read_byte(struct mtd_info *mtd) | |||
1184 | default: | 1184 | default: |
1185 | BUG(); | 1185 | BUG(); |
1186 | } | 1186 | } |
1187 | 1187 | ||
1188 | if (ns->regs.count == ns->regs.num) { | 1188 | if (ns->regs.count == ns->regs.num) { |
1189 | NS_DBG("read_byte: all bytes were read\n"); | 1189 | NS_DBG("read_byte: all bytes were read\n"); |
1190 | 1190 | ||
@@ -1201,9 +1201,9 @@ ns_nand_read_byte(struct mtd_info *mtd) | |||
1201 | } | 1201 | } |
1202 | else if (NS_STATE(ns->nxstate) == STATE_READY) | 1202 | else if (NS_STATE(ns->nxstate) == STATE_READY) |
1203 | switch_state(ns); | 1203 | switch_state(ns); |
1204 | 1204 | ||
1205 | } | 1205 | } |
1206 | 1206 | ||
1207 | return outb; | 1207 | return outb; |
1208 | } | 1208 | } |
1209 | 1209 | ||
@@ -1211,7 +1211,7 @@ static void | |||
1211 | ns_nand_write_byte(struct mtd_info *mtd, u_char byte) | 1211 | ns_nand_write_byte(struct mtd_info *mtd, u_char byte) |
1212 | { | 1212 | { |
1213 | struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv; | 1213 | struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv; |
1214 | 1214 | ||
1215 | /* Sanity and correctness checks */ | 1215 | /* Sanity and correctness checks */ |
1216 | if (!ns->lines.ce) { | 1216 | if (!ns->lines.ce) { |
1217 | NS_ERR("write_byte: chip is disabled, ignore write\n"); | 1217 | NS_ERR("write_byte: chip is disabled, ignore write\n"); |
@@ -1221,7 +1221,7 @@ ns_nand_write_byte(struct mtd_info *mtd, u_char byte) | |||
1221 | NS_ERR("write_byte: ALE and CLE pins are high simultaneously, ignore write\n"); | 1221 | NS_ERR("write_byte: ALE and CLE pins are high simultaneously, ignore write\n"); |
1222 | return; | 1222 | return; |
1223 | } | 1223 | } |
1224 | 1224 | ||
1225 | if (ns->lines.cle == 1) { | 1225 | if (ns->lines.cle == 1) { |
1226 | /* | 1226 | /* |
1227 | * The byte written is a command. | 1227 | * The byte written is a command. |
@@ -1233,7 +1233,7 @@ ns_nand_write_byte(struct mtd_info *mtd, u_char byte) | |||
1233 | return; | 1233 | return; |
1234 | } | 1234 | } |
1235 | 1235 | ||
1236 | /* | 1236 | /* |
1237 | * Chip might still be in STATE_DATAOUT | 1237 | * Chip might still be in STATE_DATAOUT |
1238 | * (if OPT_AUTOINCR feature is supported), STATE_DATAOUT_STATUS or | 1238 | * (if OPT_AUTOINCR feature is supported), STATE_DATAOUT_STATUS or |
1239 | * STATE_DATAOUT_STATUS_M state. If so, switch state. | 1239 | * STATE_DATAOUT_STATUS_M state. If so, switch state. |
@@ -1254,13 +1254,13 @@ ns_nand_write_byte(struct mtd_info *mtd, u_char byte) | |||
1254 | "ignore previous states\n", (uint)byte, get_state_name(ns->nxstate)); | 1254 | "ignore previous states\n", (uint)byte, get_state_name(ns->nxstate)); |
1255 | switch_to_ready_state(ns, NS_STATUS_FAILED(ns)); | 1255 | switch_to_ready_state(ns, NS_STATUS_FAILED(ns)); |
1256 | } | 1256 | } |
1257 | 1257 | ||
1258 | /* Check that the command byte is correct */ | 1258 | /* Check that the command byte is correct */ |
1259 | if (check_command(byte)) { | 1259 | if (check_command(byte)) { |
1260 | NS_ERR("write_byte: unknown command %#x\n", (uint)byte); | 1260 | NS_ERR("write_byte: unknown command %#x\n", (uint)byte); |
1261 | return; | 1261 | return; |
1262 | } | 1262 | } |
1263 | 1263 | ||
1264 | NS_DBG("command byte corresponding to %s state accepted\n", | 1264 | NS_DBG("command byte corresponding to %s state accepted\n", |
1265 | get_state_name(get_state_by_command(byte))); | 1265 | get_state_name(get_state_by_command(byte))); |
1266 | ns->regs.command = byte; | 1266 | ns->regs.command = byte; |
@@ -1277,12 +1277,12 @@ ns_nand_write_byte(struct mtd_info *mtd, u_char byte) | |||
1277 | 1277 | ||
1278 | if (find_operation(ns, 1) < 0) | 1278 | if (find_operation(ns, 1) < 0) |
1279 | return; | 1279 | return; |
1280 | 1280 | ||
1281 | if ((ns->state & ACTION_MASK) && do_state_action(ns, ns->state) < 0) { | 1281 | if ((ns->state & ACTION_MASK) && do_state_action(ns, ns->state) < 0) { |
1282 | switch_to_ready_state(ns, NS_STATUS_FAILED(ns)); | 1282 | switch_to_ready_state(ns, NS_STATUS_FAILED(ns)); |
1283 | return; | 1283 | return; |
1284 | } | 1284 | } |
1285 | 1285 | ||
1286 | ns->regs.count = 0; | 1286 | ns->regs.count = 0; |
1287 | switch (NS_STATE(ns->nxstate)) { | 1287 | switch (NS_STATE(ns->nxstate)) { |
1288 | case STATE_ADDR_PAGE: | 1288 | case STATE_ADDR_PAGE: |
@@ -1306,7 +1306,7 @@ ns_nand_write_byte(struct mtd_info *mtd, u_char byte) | |||
1306 | switch_to_ready_state(ns, NS_STATUS_FAILED(ns)); | 1306 | switch_to_ready_state(ns, NS_STATUS_FAILED(ns)); |
1307 | return; | 1307 | return; |
1308 | } | 1308 | } |
1309 | 1309 | ||
1310 | /* Check if this is expected byte */ | 1310 | /* Check if this is expected byte */ |
1311 | if (ns->regs.count == ns->regs.num) { | 1311 | if (ns->regs.count == ns->regs.num) { |
1312 | NS_ERR("write_byte: no more address bytes expected\n"); | 1312 | NS_ERR("write_byte: no more address bytes expected\n"); |
@@ -1325,12 +1325,12 @@ ns_nand_write_byte(struct mtd_info *mtd, u_char byte) | |||
1325 | NS_DBG("address (%#x, %#x) is accepted\n", ns->regs.row, ns->regs.column); | 1325 | NS_DBG("address (%#x, %#x) is accepted\n", ns->regs.row, ns->regs.column); |
1326 | switch_state(ns); | 1326 | switch_state(ns); |
1327 | } | 1327 | } |
1328 | 1328 | ||
1329 | } else { | 1329 | } else { |
1330 | /* | 1330 | /* |
1331 | * The byte written is an input data. | 1331 | * The byte written is an input data. |
1332 | */ | 1332 | */ |
1333 | 1333 | ||
1334 | /* Check that chip is expecting data input */ | 1334 | /* Check that chip is expecting data input */ |
1335 | if (!(ns->state & STATE_DATAIN_MASK)) { | 1335 | if (!(ns->state & STATE_DATAIN_MASK)) { |
1336 | NS_ERR("write_byte: data input (%#x) isn't expected, state is %s, " | 1336 | NS_ERR("write_byte: data input (%#x) isn't expected, state is %s, " |
@@ -1372,7 +1372,7 @@ ns_nand_read_word(struct mtd_info *mtd) | |||
1372 | struct nand_chip *chip = (struct nand_chip *)mtd->priv; | 1372 | struct nand_chip *chip = (struct nand_chip *)mtd->priv; |
1373 | 1373 | ||
1374 | NS_DBG("read_word\n"); | 1374 | NS_DBG("read_word\n"); |
1375 | 1375 | ||
1376 | return chip->read_byte(mtd) | (chip->read_byte(mtd) << 8); | 1376 | return chip->read_byte(mtd) | (chip->read_byte(mtd) << 8); |
1377 | } | 1377 | } |
1378 | 1378 | ||
@@ -1380,14 +1380,14 @@ static void | |||
1380 | ns_nand_write_word(struct mtd_info *mtd, uint16_t word) | 1380 | ns_nand_write_word(struct mtd_info *mtd, uint16_t word) |
1381 | { | 1381 | { |
1382 | struct nand_chip *chip = (struct nand_chip *)mtd->priv; | 1382 | struct nand_chip *chip = (struct nand_chip *)mtd->priv; |
1383 | 1383 | ||
1384 | NS_DBG("write_word\n"); | 1384 | NS_DBG("write_word\n"); |
1385 | 1385 | ||
1386 | chip->write_byte(mtd, word & 0xFF); | 1386 | chip->write_byte(mtd, word & 0xFF); |
1387 | chip->write_byte(mtd, word >> 8); | 1387 | chip->write_byte(mtd, word >> 8); |
1388 | } | 1388 | } |
1389 | 1389 | ||
1390 | static void | 1390 | static void |
1391 | ns_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len) | 1391 | ns_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len) |
1392 | { | 1392 | { |
1393 | struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv; | 1393 | struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv; |
@@ -1409,13 +1409,13 @@ ns_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len) | |||
1409 | 1409 | ||
1410 | memcpy(ns->buf.byte + ns->regs.count, buf, len); | 1410 | memcpy(ns->buf.byte + ns->regs.count, buf, len); |
1411 | ns->regs.count += len; | 1411 | ns->regs.count += len; |
1412 | 1412 | ||
1413 | if (ns->regs.count == ns->regs.num) { | 1413 | if (ns->regs.count == ns->regs.num) { |
1414 | NS_DBG("write_buf: %d bytes were written\n", ns->regs.count); | 1414 | NS_DBG("write_buf: %d bytes were written\n", ns->regs.count); |
1415 | } | 1415 | } |
1416 | } | 1416 | } |
1417 | 1417 | ||
1418 | static void | 1418 | static void |
1419 | ns_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len) | 1419 | ns_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len) |
1420 | { | 1420 | { |
1421 | struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv; | 1421 | struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv; |
@@ -1453,7 +1453,7 @@ ns_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len) | |||
1453 | 1453 | ||
1454 | memcpy(buf, ns->buf.byte + ns->regs.count, len); | 1454 | memcpy(buf, ns->buf.byte + ns->regs.count, len); |
1455 | ns->regs.count += len; | 1455 | ns->regs.count += len; |
1456 | 1456 | ||
1457 | if (ns->regs.count == ns->regs.num) { | 1457 | if (ns->regs.count == ns->regs.num) { |
1458 | if ((ns->options & OPT_AUTOINCR) && NS_STATE(ns->state) == STATE_DATAOUT) { | 1458 | if ((ns->options & OPT_AUTOINCR) && NS_STATE(ns->state) == STATE_DATAOUT) { |
1459 | ns->regs.count = 0; | 1459 | ns->regs.count = 0; |
@@ -1465,11 +1465,11 @@ ns_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len) | |||
1465 | else if (NS_STATE(ns->nxstate) == STATE_READY) | 1465 | else if (NS_STATE(ns->nxstate) == STATE_READY) |
1466 | switch_state(ns); | 1466 | switch_state(ns); |
1467 | } | 1467 | } |
1468 | 1468 | ||
1469 | return; | 1469 | return; |
1470 | } | 1470 | } |
1471 | 1471 | ||
1472 | static int | 1472 | static int |
1473 | ns_nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len) | 1473 | ns_nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len) |
1474 | { | 1474 | { |
1475 | ns_nand_read_buf(mtd, (u_char *)&ns_verify_buf[0], len); | 1475 | ns_nand_read_buf(mtd, (u_char *)&ns_verify_buf[0], len); |
@@ -1496,7 +1496,7 @@ int __init ns_init_module(void) | |||
1496 | NS_ERR("wrong bus width (%d), use only 8 or 16\n", bus_width); | 1496 | NS_ERR("wrong bus width (%d), use only 8 or 16\n", bus_width); |
1497 | return -EINVAL; | 1497 | return -EINVAL; |
1498 | } | 1498 | } |
1499 | 1499 | ||
1500 | /* Allocate and initialize mtd_info, nand_chip and nandsim structures */ | 1500 | /* Allocate and initialize mtd_info, nand_chip and nandsim structures */ |
1501 | nsmtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip) | 1501 | nsmtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip) |
1502 | + sizeof(struct nandsim), GFP_KERNEL); | 1502 | + sizeof(struct nandsim), GFP_KERNEL); |
@@ -1509,7 +1509,7 @@ int __init ns_init_module(void) | |||
1509 | chip = (struct nand_chip *)(nsmtd + 1); | 1509 | chip = (struct nand_chip *)(nsmtd + 1); |
1510 | nsmtd->priv = (void *)chip; | 1510 | nsmtd->priv = (void *)chip; |
1511 | nand = (struct nandsim *)(chip + 1); | 1511 | nand = (struct nandsim *)(chip + 1); |
1512 | chip->priv = (void *)nand; | 1512 | chip->priv = (void *)nand; |
1513 | 1513 | ||
1514 | /* | 1514 | /* |
1515 | * Register simulator's callbacks. | 1515 | * Register simulator's callbacks. |
@@ -1526,9 +1526,9 @@ int __init ns_init_module(void) | |||
1526 | chip->eccmode = NAND_ECC_SOFT; | 1526 | chip->eccmode = NAND_ECC_SOFT; |
1527 | chip->options |= NAND_SKIP_BBTSCAN; | 1527 | chip->options |= NAND_SKIP_BBTSCAN; |
1528 | 1528 | ||
1529 | /* | 1529 | /* |
1530 | * Perform minimum nandsim structure initialization to handle | 1530 | * Perform minimum nandsim structure initialization to handle |
1531 | * the initial ID read command correctly | 1531 | * the initial ID read command correctly |
1532 | */ | 1532 | */ |
1533 | if (third_id_byte != 0xFF || fourth_id_byte != 0xFF) | 1533 | if (third_id_byte != 0xFF || fourth_id_byte != 0xFF) |
1534 | nand->geom.idbytes = 4; | 1534 | nand->geom.idbytes = 4; |
@@ -1557,7 +1557,7 @@ int __init ns_init_module(void) | |||
1557 | NS_ERR("scan_bbt: can't initialize the nandsim structure\n"); | 1557 | NS_ERR("scan_bbt: can't initialize the nandsim structure\n"); |
1558 | goto error; | 1558 | goto error; |
1559 | } | 1559 | } |
1560 | 1560 | ||
1561 | if ((retval = nand_default_bbt(nsmtd)) != 0) { | 1561 | if ((retval = nand_default_bbt(nsmtd)) != 0) { |
1562 | free_nandsim(nand); | 1562 | free_nandsim(nand); |
1563 | goto error; | 1563 | goto error; |