diff options
Diffstat (limited to 'arch/cris/arch-v32/lib/nand_init.S')
-rw-r--r-- | arch/cris/arch-v32/lib/nand_init.S | 179 |
1 files changed, 179 insertions, 0 deletions
diff --git a/arch/cris/arch-v32/lib/nand_init.S b/arch/cris/arch-v32/lib/nand_init.S new file mode 100644 index 000000000000..aba5c751c282 --- /dev/null +++ b/arch/cris/arch-v32/lib/nand_init.S | |||
@@ -0,0 +1,179 @@ | |||
1 | ##============================================================================= | ||
2 | ## | ||
3 | ## nand_init.S | ||
4 | ## | ||
5 | ## The bootrom copies data from the NAND flash to the internal RAM but | ||
6 | ## due to a bug/feature we can only trust the 256 first bytes. So this | ||
7 | ## code copies more data from NAND flash to internal RAM. Obvioulsy this | ||
8 | ## code must fit in the first 256 bytes so alter with care. | ||
9 | ## | ||
10 | ## Some notes about the bug/feature for future reference: | ||
11 | ## The bootrom copies the first 127 KB from NAND flash to internal | ||
12 | ## memory. The problem is that it does a bytewise copy. NAND flashes | ||
13 | ## does autoincrement on the address so for a 16-bite device each | ||
14 | ## read/write increases the address by two. So the copy loop in the | ||
15 | ## bootrom will discard every second byte. This is solved by inserting | ||
16 | ## zeroes in every second byte in the first erase block. | ||
17 | ## | ||
18 | ## The bootrom also incorrectly assumes that it can read the flash | ||
19 | ## linear with only one read command but the flash will actually | ||
20 | ## switch between normal area and spare area if you do that so we | ||
21 | ## can't trust more than the first 256 bytes. | ||
22 | ## | ||
23 | ##============================================================================= | ||
24 | |||
25 | #include <asm/arch/hwregs/asm/reg_map_asm.h> | ||
26 | #include <asm/arch/hwregs/asm/gio_defs_asm.h> | ||
27 | #include <asm/arch/hwregs/asm/pinmux_defs_asm.h> | ||
28 | #include <asm/arch/hwregs/asm/bif_core_defs_asm.h> | ||
29 | #include <asm/arch/hwregs/asm/config_defs_asm.h> | ||
30 | #include <linux/config.h> | ||
31 | |||
32 | ;; There are 8-bit NAND flashes and 16-bit NAND flashes. | ||
33 | ;; We need to treat them slightly different. | ||
34 | #if CONFIG_ETRAX_FLASH_BUSWIDTH==2 | ||
35 | #define PAGE_SIZE 256 | ||
36 | #else | ||
37 | #error 2 | ||
38 | #define PAGE_SIZE 512 | ||
39 | #endif | ||
40 | #define ERASE_BLOCK 16384 | ||
41 | |||
42 | ;; GPIO pins connected to NAND flash | ||
43 | #define CE 4 | ||
44 | #define CLE 5 | ||
45 | #define ALE 6 | ||
46 | #define BY 7 | ||
47 | |||
48 | ;; Address space for NAND flash | ||
49 | #define NAND_RD_ADDR 0x90000000 | ||
50 | #define NAND_WR_ADDR 0x94000000 | ||
51 | |||
52 | #define READ_CMD 0x00 | ||
53 | |||
54 | ;; Readability macros | ||
55 | #define CSP_MASK \ | ||
56 | REG_MASK(bif_core, rw_grp3_cfg, gated_csp0) | \ | ||
57 | REG_MASK(bif_core, rw_grp3_cfg, gated_csp1) | ||
58 | #define CSP_VAL \ | ||
59 | REG_STATE(bif_core, rw_grp3_cfg, gated_csp0, rd) | \ | ||
60 | REG_STATE(bif_core, rw_grp3_cfg, gated_csp1, wr) | ||
61 | |||
62 | ;;---------------------------------------------------------------------------- | ||
63 | ;; Macros to set/clear GPIO bits | ||
64 | |||
65 | .macro SET x | ||
66 | or.b (1<<\x),$r9 | ||
67 | move.d $r9, [$r2] | ||
68 | .endm | ||
69 | |||
70 | .macro CLR x | ||
71 | and.b ~(1<<\x),$r9 | ||
72 | move.d $r9, [$r2] | ||
73 | .endm | ||
74 | |||
75 | ;;---------------------------------------------------------------------------- | ||
76 | |||
77 | nand_boot: | ||
78 | ;; Check if nand boot was selected | ||
79 | move.d REG_ADDR(config, regi_config, r_bootsel), $r0 | ||
80 | move.d [$r0], $r0 | ||
81 | and.d REG_MASK(config, r_bootsel, boot_mode), $r0 | ||
82 | cmp.d REG_STATE(config, r_bootsel, boot_mode, nand), $r0 | ||
83 | bne normal_boot ; No NAND boot | ||
84 | nop | ||
85 | |||
86 | copy_nand_to_ram: | ||
87 | ;; copy_nand_to_ram | ||
88 | ;; Arguments | ||
89 | ;; r10 - destination | ||
90 | ;; r11 - source offset | ||
91 | ;; r12 - size | ||
92 | ;; r13 - Address to jump to after completion | ||
93 | ;; Note : r10-r12 are clobbered on return | ||
94 | ;; Registers used: | ||
95 | ;; r0 - NAND_RD_ADDR | ||
96 | ;; r1 - NAND_WR_ADDR | ||
97 | ;; r2 - reg_gio_rw_pa_dout | ||
98 | ;; r3 - reg_gio_r_pa_din | ||
99 | ;; r4 - tmp | ||
100 | ;; r5 - byte counter within a page | ||
101 | ;; r6 - reg_pinmux_rw_pa | ||
102 | ;; r7 - reg_gio_rw_pa_oe | ||
103 | ;; r8 - reg_bif_core_rw_grp3_cfg | ||
104 | ;; r9 - reg_gio_rw_pa_dout shadow | ||
105 | move.d 0x90000000, $r0 | ||
106 | move.d 0x94000000, $r1 | ||
107 | move.d REG_ADDR(gio, regi_gio, rw_pa_dout), $r2 | ||
108 | move.d REG_ADDR(gio, regi_gio, r_pa_din), $r3 | ||
109 | move.d REG_ADDR(pinmux, regi_pinmux, rw_pa), $r6 | ||
110 | move.d REG_ADDR(gio, regi_gio, rw_pa_oe), $r7 | ||
111 | move.d REG_ADDR(bif_core, regi_bif_core, rw_grp3_cfg), $r8 | ||
112 | |||
113 | #if CONFIG_ETRAX_FLASH_BUSWIDTH==2 | ||
114 | lsrq 1, $r11 | ||
115 | #endif | ||
116 | ;; Set up GPIO | ||
117 | move.d [$r2], $r9 | ||
118 | move.d [$r7], $r4 | ||
119 | or.b (1<<ALE) | (1 << CLE) | (1<<CE), $r4 | ||
120 | move.d $r4, [$r7] | ||
121 | |||
122 | ;; Set up bif | ||
123 | move.d [$r8], $r4 | ||
124 | and.d CSP_MASK, $r4 | ||
125 | or.d CSP_VAL, $r4 | ||
126 | move.d $r4, [$r8] | ||
127 | |||
128 | 1: ;; Copy one page | ||
129 | CLR CE | ||
130 | SET CLE | ||
131 | moveq READ_CMD, $r4 | ||
132 | move.b $r4, [$r1] | ||
133 | moveq 20, $r4 | ||
134 | 2: bne 2b | ||
135 | subq 1, $r4 | ||
136 | CLR CLE | ||
137 | SET ALE | ||
138 | clear.w [$r1] ; Column address = 0 | ||
139 | move.d $r11, $r4 | ||
140 | lsrq 8, $r4 | ||
141 | move.b $r4, [$r1] ; Row address | ||
142 | lsrq 8, $r4 | ||
143 | move.b $r4, [$r1] ; Row adddress | ||
144 | moveq 20, $r4 | ||
145 | 2: bne 2b | ||
146 | subq 1, $r4 | ||
147 | CLR ALE | ||
148 | 2: move.d [$r3], $r4 | ||
149 | and.d 1 << BY, $r4 | ||
150 | beq 2b | ||
151 | movu.w PAGE_SIZE, $r5 | ||
152 | 2: ; Copy one byte/word | ||
153 | #if CONFIG_ETRAX_FLASH_BUSWIDTH==2 | ||
154 | move.w [$r0], $r4 | ||
155 | #else | ||
156 | move.b [$r0], $r4 | ||
157 | #endif | ||
158 | subq 1, $r5 | ||
159 | bne 2b | ||
160 | #if CONFIG_ETRAX_FLASH_BUSWIDTH==2 | ||
161 | move.w $r4, [$r10+] | ||
162 | subu.w PAGE_SIZE*2, $r12 | ||
163 | #else | ||
164 | move.b $r4, [$r10+] | ||
165 | subu.w PAGE_SIZE, $r12 | ||
166 | #endif | ||
167 | bpl 1b | ||
168 | addu.w PAGE_SIZE, $r11 | ||
169 | |||
170 | ;; End of copy | ||
171 | jump $r13 | ||
172 | nop | ||
173 | |||
174 | ;; This will warn if the code above is too large. If you consider | ||
175 | ;; to remove this you don't understand the bug/feature. | ||
176 | .org 256 | ||
177 | .org ERASE_BLOCK | ||
178 | |||
179 | normal_boot: | ||