mips/nand.hhp |
58 | 58 | static unsigned block_bits |
59 | 59 | static unsigned size_bits |
60 | 60 | static unsigned word_size |
| 61 | static unsigned ecc_start |
61 | 62 | |
62 | 63 | static void unbusy (): |
63 | 64 | while !(gpio_get_port (2) & (1 << 30)): |
... | ... | |
117 | 118 | unsigned num_planes_bits = d >> 2 & 3 |
118 | 119 | unsigned plane_bits = 26 + (d >> 4 & 7) |
119 | 120 | size_bits = plane_bits + num_planes_bits - 3 |
| 121 | if page_bits == 11: |
| 122 | ecc_start = 6 |
| 123 | else if page_bits == 12: |
| 124 | ecc_start = 12 |
| 125 | else: |
| 126 | debug ("unknown nand type; assuming ecc offset to be 6. This is probably wrong!\n") |
| 127 | ecc_start = 6 |
120 | 128 | |
121 | 129 | static bool read (unsigned a, char *buffer): |
122 | 130 | unsigned column = a & ((1 << page_bits) - 1) |
... | ... | |
134 | 142 | // 33: 9-byte ecc of 4th 512 bytes |
135 | 143 | // 42: unused |
136 | 144 | // 64: end of space |
137 | | unsigned col = (1 << page_bits) + 6 + 9 * (column >> 9) |
| 145 | |
| 146 | // For 2 GB nand: |
| 147 | // 0-11: unused/bad block markers |
| 148 | // 12-89: 8 times 9-byte ecc |
| 149 | // 90-127: unused |
| 150 | // 128: end of space |
| 151 | unsigned col = (1 << page_bits) + ecc_start + 9 * (column >> 9) |
138 | 152 | cmd (CMD_READ0) |
139 | 153 | addr (col) |
140 | 154 | addr (col >> 8) |
... | ... | |
143 | 157 | addr (row >> 16) |
144 | 158 | cmd (CMD_READSTART) |
145 | 159 | //debug ("parity data:") |
| 160 | bool parity_all_ff = true |
146 | 161 | for unsigned t = 0; t < 9; ++t: |
147 | 162 | error[t] = rdata () |
| 163 | if parity_all_ff && (error[t] & 0xff) != 0xff: |
| 164 | parity_all_ff = false |
148 | 165 | //debug (" %x", error[t] & 0xff) |
149 | 166 | //debug ("\n") |
150 | 167 | cmd (CMD_RNDOUT) |
... | ... | |
153 | 170 | cmd (CMD_RNDOUTSTART) |
154 | 171 | EMC_NFINTS = 0 |
155 | 172 | EMC_NFECR = EMC_NFECR_ECCE | EMC_NFECR_RS | EMC_NFECR_RS_DECODING | EMC_NFECR_ERST |
| 173 | bool all_ff = true |
156 | 174 | for unsigned t = 0; t < 0x200; ++t: |
157 | 175 | buffer[t] = rdata () |
158 | | for unsigned t = 0; t < 9; ++t: |
159 | | ((volatile char *)&EMC_NFPAR (0))[t] = error[t] |
160 | | EMC_NFECR = EMC_NFECR_ECCE | EMC_NFECR_RS | EMC_NFECR_RS_DECODING | EMC_NFECR_PRDY |
161 | | while !(EMC_NFINTS & EMC_NFINTS_DECF): |
162 | | DELAY () |
163 | | unsigned ints = EMC_NFINTS |
164 | | if ints & EMC_NFINTS_UNCOR: |
165 | | debug ("uncorrectable error in nand at %x\n", a) |
166 | | return false |
167 | | unsigned errs = (ints & EMC_NFINTS_ERRCNT_MASK) >> EMC_NFINTS_ERRCNT_BIT |
168 | | for unsigned i = 0; i < errs; ++i: |
169 | | unsigned err = EMC_NFERR (i) |
170 | | unsigned index = (err >> 16) - 1 |
171 | | unsigned mask = err & 0x1ff |
172 | | unsigned bit = index * 9 |
173 | | unsigned offset= bit & 7 |
174 | | unsigned byte = bit / 8 |
175 | | debug ("correcting %x on %x+%d\n", mask, byte, offset) |
176 | | unsigned data = buffer[byte] | buffer[byte + 1] << 8 |
177 | | data ^= mask << offset |
178 | | buffer[byte] = data |
179 | | buffer[byte + 1] = data >> 8 |
| 176 | if all_ff && (buffer[t] & 0xff) != 0xff: |
| 177 | all_ff = false |
| 178 | if !all_ff || !parity_all_ff: |
| 179 | for unsigned t = 0; t < 9; ++t: |
| 180 | ((volatile char *)&EMC_NFPAR (0))[t] = error[t] |
| 181 | EMC_NFECR = EMC_NFECR_ECCE | EMC_NFECR_RS | EMC_NFECR_RS_DECODING | EMC_NFECR_PRDY |
| 182 | while !(EMC_NFINTS & EMC_NFINTS_DECF): |
| 183 | DELAY () |
| 184 | unsigned ints = EMC_NFINTS |
| 185 | if ints & EMC_NFINTS_UNCOR: |
| 186 | debug ("uncorrectable error in nand at %x\n", a) |
| 187 | return false |
| 188 | unsigned errs = (ints & EMC_NFINTS_ERRCNT_MASK) >> EMC_NFINTS_ERRCNT_BIT |
| 189 | for unsigned i = 0; i < errs; ++i: |
| 190 | unsigned err = EMC_NFERR (i) |
| 191 | unsigned index = (err >> 16) - 1 |
| 192 | unsigned mask = err & 0x1ff |
| 193 | unsigned bit = index * 9 |
| 194 | unsigned offset= bit & 7 |
| 195 | unsigned byte = bit / 8 |
| 196 | debug ("correcting %x on %x+%d\n", mask, byte, offset) |
| 197 | unsigned data = buffer[byte] | buffer[byte + 1] << 8 |
| 198 | data ^= mask << offset |
| 199 | buffer[byte] = data |
| 200 | buffer[byte + 1] = data >> 8 |
180 | 201 | #if 0 |
181 | 202 | for unsigned i = 0; i < 0x10; ++i: |
182 | 203 | if (buffer[i] & 0xff) < 0x10: |
... | ... | |
228 | 249 | // 33: 9-byte ecc of 4th 512 bytes |
229 | 250 | // 42: unused |
230 | 251 | // 64: end of space |
231 | | for unsigned i = 0; i < 6; ++i: |
232 | | wdata (0) |
| 252 | |
| 253 | // For 2 GB nand: |
| 254 | // 0-11: unused/bad block markers |
| 255 | // 12-89: 8 times 9-byte ecc |
| 256 | // 90-127: unused |
| 257 | // 128: end of space |
| 258 | for unsigned i = 0; i < ecc_start; ++i: |
| 259 | wdata (i == 4 ? 0 : 0xff) |
233 | 260 | for unsigned i = 0; i < 1 << (page_bits - 9); ++i: |
234 | 261 | for unsigned j = 0; j < 9; ++j: |
235 | 262 | wdata (ecc[i][j]) |
... | ... | |
268 | 295 | unsigned offset= bit & 7 |
269 | 296 | unsigned byte = bit / 8 |
270 | 297 | debug ("error detected by parity: %x on %x+%d\n", mask, byte, offset) |
271 | | for unsigned i = 0; i < 6; ++i: |
272 | | if rdata () != 0: |
273 | | debug ("extra data not 0 at byte %d\n", i) |
| 298 | for unsigned i = 0; i < ecc_start; ++i: |
| 299 | if rdata () != (i == 4 ? 0 : 0xff): |
| 300 | debug ("incorrect extra data at byte %d\n", i) |
274 | 301 | for unsigned i = 0; i < 1 << (page_bits - 9); ++i: |
275 | 302 | for unsigned j = 0; j < 9; ++j: |
276 | 303 | unsigned r = rdata () & 0xff |