]>
Commit | Line | Data |
---|---|---|
7c93b244 MK |
1 | /* |
2 | * (C) Copyright 2006 DENX Software Engineering | |
3 | * | |
4 | * See file CREDITS for list of people who contributed to this | |
5 | * project. | |
6 | * | |
7 | * This program is free software; you can redistribute it and/or | |
8 | * modify it under the terms of the GNU General Public License as | |
9 | * published by the Free Software Foundation; either version 2 of | |
10 | * the License, or (at your option) any later version. | |
11 | * | |
12 | * This program is distributed in the hope that it will be useful, | |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | * GNU General Public License for more details. | |
16 | * | |
17 | * You should have received a copy of the GNU General Public License | |
18 | * along with this program; if not, write to the Free Software | |
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, | |
20 | * MA 02111-1307 USA | |
21 | */ | |
22 | ||
23 | #include <common.h> | |
24 | ||
ab3abcba | 25 | #if defined(CONFIG_CMD_NAND) |
7c93b244 MK |
26 | #ifdef CONFIG_NEW_NAND_CODE |
27 | ||
28 | #include <nand.h> | |
29 | #include <asm/arch/pxa-regs.h> | |
30 | ||
31 | #ifdef CFG_DFC_DEBUG1 | |
32 | # define DFC_DEBUG1(fmt, args...) printf(fmt, ##args) | |
33 | #else | |
34 | # define DFC_DEBUG1(fmt, args...) | |
35 | #endif | |
36 | ||
37 | #ifdef CFG_DFC_DEBUG2 | |
38 | # define DFC_DEBUG2(fmt, args...) printf(fmt, ##args) | |
39 | #else | |
40 | # define DFC_DEBUG2(fmt, args...) | |
41 | #endif | |
42 | ||
43 | #ifdef CFG_DFC_DEBUG3 | |
44 | # define DFC_DEBUG3(fmt, args...) printf(fmt, ##args) | |
45 | #else | |
46 | # define DFC_DEBUG3(fmt, args...) | |
47 | #endif | |
48 | ||
49 | #define MIN(x, y) ((x < y) ? x : y) | |
50 | ||
51 | /* These really don't belong here, as they are specific to the NAND Model */ | |
52 | static uint8_t scan_ff_pattern[] = { 0xff, 0xff }; | |
53 | ||
54 | static struct nand_bbt_descr delta_bbt_descr = { | |
55 | .options = 0, | |
56 | .offs = 0, | |
57 | .len = 2, | |
58 | .pattern = scan_ff_pattern | |
59 | }; | |
60 | ||
61 | static struct nand_oobinfo delta_oob = { | |
62 | .useecc = MTD_NANDECC_AUTOPL_USR, /* MTD_NANDECC_PLACEONLY, */ | |
63 | .eccbytes = 6, | |
64 | .eccpos = {2, 3, 4, 5, 6, 7}, | |
65 | .oobfree = { {8, 2}, {12, 4} } | |
66 | }; | |
67 | ||
68 | ||
69 | /* | |
70 | * not required for Monahans DFC | |
71 | */ | |
72 | static void dfc_hwcontrol(struct mtd_info *mtdinfo, int cmd) | |
73 | { | |
74 | return; | |
75 | } | |
76 | ||
77 | #if 0 | |
78 | /* read device ready pin */ | |
79 | static int dfc_device_ready(struct mtd_info *mtdinfo) | |
80 | { | |
81 | if(NDSR & NDSR_RDY) | |
82 | return 1; | |
83 | else | |
84 | return 0; | |
85 | return 0; | |
86 | } | |
87 | #endif | |
88 | ||
89 | /* | |
90 | * Write buf to the DFC Controller Data Buffer | |
91 | */ | |
92 | static void dfc_write_buf(struct mtd_info *mtd, const u_char *buf, int len) | |
93 | { | |
94 | unsigned long bytes_multi = len & 0xfffffffc; | |
95 | unsigned long rest = len & 0x3; | |
96 | unsigned long *long_buf; | |
97 | int i; | |
98 | ||
99 | DFC_DEBUG2("dfc_write_buf: writing %d bytes starting with 0x%x.\n", len, *((unsigned long*) buf)); | |
100 | if(bytes_multi) { | |
101 | for(i=0; i<bytes_multi; i+=4) { | |
102 | long_buf = (unsigned long*) &buf[i]; | |
103 | NDDB = *long_buf; | |
104 | } | |
105 | } | |
106 | if(rest) { | |
107 | printf("dfc_write_buf: ERROR, writing non 4-byte aligned data.\n"); | |
108 | } | |
109 | return; | |
110 | } | |
111 | ||
112 | ||
113 | /* | |
114 | * These functions are quite problematic for the DFC. Luckily they are | |
115 | * not used in the current nand code, except for nand_command, which | |
116 | * we've defined our own anyway. The problem is, that we always need | |
117 | * to write 4 bytes to the DFC Data Buffer, but in these functions we | |
118 | * don't know if to buffer the bytes/half words until we've gathered 4 | |
119 | * bytes or if to send them straight away. | |
120 | * | |
121 | * Solution: Don't use these with Mona's DFC and complain loudly. | |
122 | */ | |
123 | static void dfc_write_word(struct mtd_info *mtd, u16 word) | |
124 | { | |
125 | printf("dfc_write_word: WARNING, this function does not work with the Monahans DFC!\n"); | |
126 | } | |
127 | static void dfc_write_byte(struct mtd_info *mtd, u_char byte) | |
128 | { | |
129 | printf("dfc_write_byte: WARNING, this function does not work with the Monahans DFC!\n"); | |
130 | } | |
131 | ||
132 | /* The original: | |
133 | * static void dfc_read_buf(struct mtd_info *mtd, const u_char *buf, int len) | |
134 | * | |
135 | * Shouldn't this be "u_char * const buf" ? | |
136 | */ | |
137 | static void dfc_read_buf(struct mtd_info *mtd, u_char* const buf, int len) | |
138 | { | |
139 | int i=0, j; | |
140 | ||
141 | /* we have to be carefull not to overflow the buffer if len is | |
142 | * not a multiple of 4 */ | |
143 | unsigned long bytes_multi = len & 0xfffffffc; | |
144 | unsigned long rest = len & 0x3; | |
145 | unsigned long *long_buf; | |
146 | ||
147 | DFC_DEBUG3("dfc_read_buf: reading %d bytes.\n", len); | |
148 | /* if there are any, first copy multiple of 4 bytes */ | |
149 | if(bytes_multi) { | |
150 | for(i=0; i<bytes_multi; i+=4) { | |
151 | long_buf = (unsigned long*) &buf[i]; | |
152 | *long_buf = NDDB; | |
153 | } | |
154 | } | |
155 | ||
156 | /* ...then the rest */ | |
157 | if(rest) { | |
158 | unsigned long rest_data = NDDB; | |
159 | for(j=0;j<rest; j++) | |
160 | buf[i+j] = (u_char) ((rest_data>>j) & 0xff); | |
161 | } | |
162 | ||
163 | return; | |
164 | } | |
165 | ||
166 | /* | |
167 | * read a word. Not implemented as not used in NAND code. | |
168 | */ | |
169 | static u16 dfc_read_word(struct mtd_info *mtd) | |
170 | { | |
171 | printf("dfc_write_byte: UNIMPLEMENTED.\n"); | |
172 | return 0; | |
173 | } | |
174 | ||
175 | /* global var, too bad: mk@tbd: move to ->priv pointer */ | |
176 | static unsigned long read_buf = 0; | |
177 | static int bytes_read = -1; | |
178 | ||
179 | /* | |
180 | * read a byte from NDDB Because we can only read 4 bytes from NDDB at | |
181 | * a time, we buffer the remaining bytes. The buffer is reset when a | |
182 | * new command is sent to the chip. | |
183 | * | |
184 | * WARNING: | |
185 | * This function is currently only used to read status and id | |
186 | * bytes. For these commands always 8 bytes need to be read from | |
187 | * NDDB. So we read and discard these bytes right now. In case this | |
188 | * function is used for anything else in the future, we must check | |
189 | * what was the last command issued and read the appropriate amount of | |
190 | * bytes respectively. | |
191 | */ | |
192 | static u_char dfc_read_byte(struct mtd_info *mtd) | |
193 | { | |
194 | unsigned char byte; | |
195 | unsigned long dummy; | |
196 | ||
197 | if(bytes_read < 0) { | |
198 | read_buf = NDDB; | |
199 | dummy = NDDB; | |
200 | bytes_read = 0; | |
201 | } | |
202 | byte = (unsigned char) (read_buf>>(8 * bytes_read++)); | |
203 | if(bytes_read >= 4) | |
204 | bytes_read = -1; | |
205 | ||
206 | DFC_DEBUG2("dfc_read_byte: byte %u: 0x%x of (0x%x).\n", bytes_read - 1, byte, read_buf); | |
207 | return byte; | |
208 | } | |
209 | ||
210 | /* calculate delta between OSCR values start and now */ | |
211 | static unsigned long get_delta(unsigned long start) | |
212 | { | |
213 | unsigned long cur = OSCR; | |
214 | ||
215 | if(cur < start) /* OSCR overflowed */ | |
216 | return (cur + (start^0xffffffff)); | |
217 | else | |
218 | return (cur - start); | |
219 | } | |
220 | ||
221 | /* delay function, this doesn't belong here */ | |
222 | static void wait_us(unsigned long us) | |
223 | { | |
224 | unsigned long start = OSCR; | |
225 | us *= OSCR_CLK_FREQ; | |
226 | ||
227 | while (get_delta(start) < us) { | |
228 | /* do nothing */ | |
229 | } | |
230 | } | |
231 | ||
232 | static void dfc_clear_nddb(void) | |
233 | { | |
234 | NDCR &= ~NDCR_ND_RUN; | |
235 | wait_us(CFG_NAND_OTHER_TO); | |
236 | } | |
237 | ||
238 | /* wait_event with timeout */ | |
239 | static unsigned long dfc_wait_event(unsigned long event) | |
240 | { | |
241 | unsigned long ndsr, timeout, start = OSCR; | |
242 | ||
243 | if(!event) | |
244 | return 0xff000000; | |
245 | else if(event & (NDSR_CS0_CMDD | NDSR_CS0_BBD)) | |
246 | timeout = CFG_NAND_PROG_ERASE_TO * OSCR_CLK_FREQ; | |
247 | else | |
248 | timeout = CFG_NAND_OTHER_TO * OSCR_CLK_FREQ; | |
249 | ||
250 | while(1) { | |
251 | ndsr = NDSR; | |
252 | if(ndsr & event) { | |
253 | NDSR |= event; | |
254 | break; | |
255 | } | |
256 | if(get_delta(start) > timeout) { | |
0a5676be | 257 | DFC_DEBUG1("dfc_wait_event: TIMEOUT waiting for event: 0x%lx.\n", event); |
7c93b244 MK |
258 | return 0xff000000; |
259 | } | |
260 | ||
261 | } | |
262 | return ndsr; | |
263 | } | |
264 | ||
265 | /* we don't always wan't to do this */ | |
266 | static void dfc_new_cmd(void) | |
267 | { | |
268 | int retry = 0; | |
269 | unsigned long status; | |
270 | ||
271 | while(retry++ <= CFG_NAND_SENDCMD_RETRY) { | |
272 | /* Clear NDSR */ | |
273 | NDSR = 0xFFF; | |
274 | ||
275 | /* set NDCR[NDRUN] */ | |
276 | if(!(NDCR & NDCR_ND_RUN)) | |
277 | NDCR |= NDCR_ND_RUN; | |
278 | ||
279 | status = dfc_wait_event(NDSR_WRCMDREQ); | |
280 | ||
281 | if(status & NDSR_WRCMDREQ) | |
282 | return; | |
283 | ||
284 | DFC_DEBUG2("dfc_new_cmd: FAILED to get WRITECMDREQ, retry: %d.\n", retry); | |
285 | dfc_clear_nddb(); | |
286 | } | |
287 | DFC_DEBUG1("dfc_new_cmd: giving up after %d retries.\n", retry); | |
288 | } | |
289 | ||
290 | /* this function is called after Programm and Erase Operations to | |
291 | * check for success or failure */ | |
292 | static int dfc_wait(struct mtd_info *mtd, struct nand_chip *this, int state) | |
293 | { | |
294 | unsigned long ndsr=0, event=0; | |
295 | ||
296 | if(state == FL_WRITING) { | |
297 | event = NDSR_CS0_CMDD | NDSR_CS0_BBD; | |
298 | } else if(state == FL_ERASING) { | |
299 | event = NDSR_CS0_CMDD | NDSR_CS0_BBD; | |
300 | } | |
301 | ||
302 | ndsr = dfc_wait_event(event); | |
303 | ||
304 | if((ndsr & NDSR_CS0_BBD) || (ndsr & 0xff000000)) | |
305 | return(0x1); /* Status Read error */ | |
306 | return 0; | |
307 | } | |
308 | ||
309 | /* cmdfunc send commands to the DFC */ | |
310 | static void dfc_cmdfunc(struct mtd_info *mtd, unsigned command, | |
311 | int column, int page_addr) | |
312 | { | |
313 | /* register struct nand_chip *this = mtd->priv; */ | |
314 | unsigned long ndcb0=0, ndcb1=0, ndcb2=0, event=0; | |
315 | ||
316 | /* clear the ugly byte read buffer */ | |
317 | bytes_read = -1; | |
318 | read_buf = 0; | |
319 | ||
320 | switch (command) { | |
321 | case NAND_CMD_READ0: | |
322 | DFC_DEBUG3("dfc_cmdfunc: NAND_CMD_READ0, page_addr: 0x%x, column: 0x%x.\n", page_addr, (column>>1)); | |
323 | dfc_new_cmd(); | |
324 | ndcb0 = (NAND_CMD_READ0 | (4<<16)); | |
325 | column >>= 1; /* adjust for 16 bit bus */ | |
326 | ndcb1 = (((column>>1) & 0xff) | | |
327 | ((page_addr<<8) & 0xff00) | | |
328 | ((page_addr<<8) & 0xff0000) | | |
329 | ((page_addr<<8) & 0xff000000)); /* make this 0x01000000 ? */ | |
330 | event = NDSR_RDDREQ; | |
331 | goto write_cmd; | |
332 | case NAND_CMD_READ1: | |
333 | DFC_DEBUG2("dfc_cmdfunc: NAND_CMD_READ1 unimplemented!\n"); | |
334 | goto end; | |
335 | case NAND_CMD_READOOB: | |
336 | DFC_DEBUG1("dfc_cmdfunc: NAND_CMD_READOOB unimplemented!\n"); | |
337 | goto end; | |
338 | case NAND_CMD_READID: | |
339 | dfc_new_cmd(); | |
340 | DFC_DEBUG2("dfc_cmdfunc: NAND_CMD_READID.\n"); | |
341 | ndcb0 = (NAND_CMD_READID | (3 << 21) | (1 << 16)); /* addr cycles*/ | |
342 | event = NDSR_RDDREQ; | |
343 | goto write_cmd; | |
344 | case NAND_CMD_PAGEPROG: | |
345 | /* sent as a multicommand in NAND_CMD_SEQIN */ | |
346 | DFC_DEBUG2("dfc_cmdfunc: NAND_CMD_PAGEPROG empty due to multicmd.\n"); | |
347 | goto end; | |
348 | case NAND_CMD_ERASE1: | |
349 | DFC_DEBUG2("dfc_cmdfunc: NAND_CMD_ERASE1, page_addr: 0x%x, column: 0x%x.\n", page_addr, (column>>1)); | |
350 | dfc_new_cmd(); | |
351 | ndcb0 = (0xd060 | (1<<25) | (2<<21) | (1<<19) | (3<<16)); | |
352 | ndcb1 = (page_addr & 0x00ffffff); | |
353 | goto write_cmd; | |
354 | case NAND_CMD_ERASE2: | |
355 | DFC_DEBUG2("dfc_cmdfunc: NAND_CMD_ERASE2 empty due to multicmd.\n"); | |
356 | goto end; | |
357 | case NAND_CMD_SEQIN: | |
358 | /* send PAGE_PROG command(0x1080) */ | |
359 | dfc_new_cmd(); | |
360 | DFC_DEBUG2("dfc_cmdfunc: NAND_CMD_SEQIN/PAGE_PROG, page_addr: 0x%x, column: 0x%x.\n", page_addr, (column>>1)); | |
361 | ndcb0 = (0x1080 | (1<<25) | (1<<21) | (1<<19) | (4<<16)); | |
362 | column >>= 1; /* adjust for 16 bit bus */ | |
363 | ndcb1 = (((column>>1) & 0xff) | | |
364 | ((page_addr<<8) & 0xff00) | | |
365 | ((page_addr<<8) & 0xff0000) | | |
366 | ((page_addr<<8) & 0xff000000)); /* make this 0x01000000 ? */ | |
367 | event = NDSR_WRDREQ; | |
368 | goto write_cmd; | |
369 | case NAND_CMD_STATUS: | |
370 | DFC_DEBUG2("dfc_cmdfunc: NAND_CMD_STATUS.\n"); | |
371 | dfc_new_cmd(); | |
372 | ndcb0 = NAND_CMD_STATUS | (4<<21); | |
373 | event = NDSR_RDDREQ; | |
374 | goto write_cmd; | |
375 | case NAND_CMD_RESET: | |
376 | DFC_DEBUG2("dfc_cmdfunc: NAND_CMD_RESET.\n"); | |
377 | ndcb0 = NAND_CMD_RESET | (5<<21); | |
378 | event = NDSR_CS0_CMDD; | |
379 | goto write_cmd; | |
380 | default: | |
381 | printk("dfc_cmdfunc: error, unsupported command.\n"); | |
382 | goto end; | |
383 | } | |
384 | ||
385 | write_cmd: | |
386 | NDCB0 = ndcb0; | |
387 | NDCB0 = ndcb1; | |
388 | NDCB0 = ndcb2; | |
389 | ||
390 | /* wait_event: */ | |
391 | dfc_wait_event(event); | |
392 | end: | |
393 | return; | |
394 | } | |
395 | ||
396 | static void dfc_gpio_init(void) | |
397 | { | |
398 | DFC_DEBUG2("Setting up DFC GPIO's.\n"); | |
399 | ||
400 | /* no idea what is done here, see zylonite.c */ | |
401 | GPIO4 = 0x1; | |
402 | ||
403 | DF_ALE_WE1 = 0x00000001; | |
404 | DF_ALE_WE2 = 0x00000001; | |
405 | DF_nCS0 = 0x00000001; | |
406 | DF_nCS1 = 0x00000001; | |
407 | DF_nWE = 0x00000001; | |
408 | DF_nRE = 0x00000001; | |
409 | DF_IO0 = 0x00000001; | |
410 | DF_IO8 = 0x00000001; | |
411 | DF_IO1 = 0x00000001; | |
412 | DF_IO9 = 0x00000001; | |
413 | DF_IO2 = 0x00000001; | |
414 | DF_IO10 = 0x00000001; | |
415 | DF_IO3 = 0x00000001; | |
416 | DF_IO11 = 0x00000001; | |
417 | DF_IO4 = 0x00000001; | |
418 | DF_IO12 = 0x00000001; | |
419 | DF_IO5 = 0x00000001; | |
420 | DF_IO13 = 0x00000001; | |
421 | DF_IO6 = 0x00000001; | |
422 | DF_IO14 = 0x00000001; | |
423 | DF_IO7 = 0x00000001; | |
424 | DF_IO15 = 0x00000001; | |
425 | ||
426 | DF_nWE = 0x1901; | |
427 | DF_nRE = 0x1901; | |
428 | DF_CLE_NOE = 0x1900; | |
429 | DF_ALE_WE1 = 0x1901; | |
430 | DF_INT_RnB = 0x1900; | |
431 | } | |
432 | ||
433 | /* | |
434 | * Board-specific NAND initialization. The following members of the | |
435 | * argument are board-specific (per include/linux/mtd/nand_new.h): | |
436 | * - IO_ADDR_R?: address to read the 8 I/O lines of the flash device | |
437 | * - IO_ADDR_W?: address to write the 8 I/O lines of the flash device | |
438 | * - hwcontrol: hardwarespecific function for accesing control-lines | |
439 | * - dev_ready: hardwarespecific function for accesing device ready/busy line | |
440 | * - enable_hwecc?: function to enable (reset) hardware ecc generator. Must | |
441 | * only be provided if a hardware ECC is available | |
442 | * - eccmode: mode of ecc, see defines | |
443 | * - chip_delay: chip dependent delay for transfering data from array to | |
444 | * read regs (tR) | |
445 | * - options: various chip options. They can partly be set to inform | |
446 | * nand_scan about special functionality. See the defines for further | |
447 | * explanation | |
448 | * Members with a "?" were not set in the merged testing-NAND branch, | |
449 | * so they are not set here either. | |
450 | */ | |
fa230445 | 451 | int board_nand_init(struct nand_chip *nand) |
7c93b244 MK |
452 | { |
453 | unsigned long tCH, tCS, tWH, tWP, tRH, tRP, tRP_high, tR, tWHR, tAR; | |
454 | ||
455 | /* set up GPIO Control Registers */ | |
456 | dfc_gpio_init(); | |
457 | ||
458 | /* turn on the NAND Controller Clock (104 MHz @ D0) */ | |
459 | CKENA |= (CKENA_4_NAND | CKENA_9_SMC); | |
460 | ||
461 | #undef CFG_TIMING_TIGHT | |
462 | #ifndef CFG_TIMING_TIGHT | |
463 | tCH = MIN(((unsigned long) (NAND_TIMING_tCH * DFC_CLK_PER_US) + 1), | |
464 | DFC_MAX_tCH); | |
465 | tCS = MIN(((unsigned long) (NAND_TIMING_tCS * DFC_CLK_PER_US) + 1), | |
466 | DFC_MAX_tCS); | |
467 | tWH = MIN(((unsigned long) (NAND_TIMING_tWH * DFC_CLK_PER_US) + 1), | |
468 | DFC_MAX_tWH); | |
469 | tWP = MIN(((unsigned long) (NAND_TIMING_tWP * DFC_CLK_PER_US) + 1), | |
470 | DFC_MAX_tWP); | |
471 | tRH = MIN(((unsigned long) (NAND_TIMING_tRH * DFC_CLK_PER_US) + 1), | |
472 | DFC_MAX_tRH); | |
473 | tRP = MIN(((unsigned long) (NAND_TIMING_tRP * DFC_CLK_PER_US) + 1), | |
474 | DFC_MAX_tRP); | |
475 | tR = MIN(((unsigned long) (NAND_TIMING_tR * DFC_CLK_PER_US) + 1), | |
476 | DFC_MAX_tR); | |
477 | tWHR = MIN(((unsigned long) (NAND_TIMING_tWHR * DFC_CLK_PER_US) + 1), | |
478 | DFC_MAX_tWHR); | |
479 | tAR = MIN(((unsigned long) (NAND_TIMING_tAR * DFC_CLK_PER_US) + 1), | |
480 | DFC_MAX_tAR); | |
481 | #else /* this is the tight timing */ | |
482 | ||
483 | tCH = MIN(((unsigned long) (NAND_TIMING_tCH * DFC_CLK_PER_US)), | |
484 | DFC_MAX_tCH); | |
485 | tCS = MIN(((unsigned long) (NAND_TIMING_tCS * DFC_CLK_PER_US)), | |
486 | DFC_MAX_tCS); | |
487 | tWH = MIN(((unsigned long) (NAND_TIMING_tWH * DFC_CLK_PER_US)), | |
488 | DFC_MAX_tWH); | |
489 | tWP = MIN(((unsigned long) (NAND_TIMING_tWP * DFC_CLK_PER_US)), | |
490 | DFC_MAX_tWP); | |
491 | tRH = MIN(((unsigned long) (NAND_TIMING_tRH * DFC_CLK_PER_US)), | |
492 | DFC_MAX_tRH); | |
493 | tRP = MIN(((unsigned long) (NAND_TIMING_tRP * DFC_CLK_PER_US)), | |
494 | DFC_MAX_tRP); | |
495 | tR = MIN(((unsigned long) (NAND_TIMING_tR * DFC_CLK_PER_US) - tCH - 2), | |
496 | DFC_MAX_tR); | |
497 | tWHR = MIN(((unsigned long) (NAND_TIMING_tWHR * DFC_CLK_PER_US) - tCH - 2), | |
498 | DFC_MAX_tWHR); | |
499 | tAR = MIN(((unsigned long) (NAND_TIMING_tAR * DFC_CLK_PER_US) - 2), | |
500 | DFC_MAX_tAR); | |
501 | #endif /* CFG_TIMING_TIGHT */ | |
502 | ||
503 | ||
504 | DFC_DEBUG2("tCH=%u, tCS=%u, tWH=%u, tWP=%u, tRH=%u, tRP=%u, tR=%u, tWHR=%u, tAR=%u.\n", tCH, tCS, tWH, tWP, tRH, tRP, tR, tWHR, tAR); | |
505 | ||
506 | /* tRP value is split in the register */ | |
507 | if(tRP & (1 << 4)) { | |
508 | tRP_high = 1; | |
509 | tRP &= ~(1 << 4); | |
510 | } else { | |
511 | tRP_high = 0; | |
512 | } | |
513 | ||
514 | NDTR0CS0 = (tCH << 19) | | |
515 | (tCS << 16) | | |
516 | (tWH << 11) | | |
517 | (tWP << 8) | | |
518 | (tRP_high << 6) | | |
519 | (tRH << 3) | | |
520 | (tRP << 0); | |
521 | ||
522 | NDTR1CS0 = (tR << 16) | | |
523 | (tWHR << 4) | | |
524 | (tAR << 0); | |
525 | ||
526 | /* If it doesn't work (unlikely) think about: | |
527 | * - ecc enable | |
528 | * - chip select don't care | |
529 | * - read id byte count | |
530 | * | |
531 | * Intentionally enabled by not setting bits: | |
532 | * - dma (DMA_EN) | |
533 | * - page size = 512 | |
534 | * - cs don't care, see if we can enable later! | |
535 | * - row address start position (after second cycle) | |
536 | * - pages per block = 32 | |
537 | * - ND_RDY : clears command buffer | |
538 | */ | |
539 | /* NDCR_NCSX | /\* Chip select busy don't care *\/ */ | |
540 | ||
541 | NDCR = (NDCR_SPARE_EN | /* use the spare area */ | |
542 | NDCR_DWIDTH_C | /* 16bit DFC data bus width */ | |
543 | NDCR_DWIDTH_M | /* 16 bit Flash device data bus width */ | |
544 | (2 << 16) | /* read id count = 7 ???? mk@tbd */ | |
545 | NDCR_ND_ARB_EN | /* enable bus arbiter */ | |
546 | NDCR_RDYM | /* flash device ready ir masked */ | |
547 | NDCR_CS0_PAGEDM | /* ND_nCSx page done ir masked */ | |
548 | NDCR_CS1_PAGEDM | | |
549 | NDCR_CS0_CMDDM | /* ND_CSx command done ir masked */ | |
550 | NDCR_CS1_CMDDM | | |
551 | NDCR_CS0_BBDM | /* ND_CSx bad block detect ir masked */ | |
552 | NDCR_CS1_BBDM | | |
553 | NDCR_DBERRM | /* double bit error ir masked */ | |
554 | NDCR_SBERRM | /* single bit error ir masked */ | |
555 | NDCR_WRDREQM | /* write data request ir masked */ | |
556 | NDCR_RDDREQM | /* read data request ir masked */ | |
557 | NDCR_WRCMDREQM); /* write command request ir masked */ | |
558 | ||
559 | ||
560 | /* wait 10 us due to cmd buffer clear reset */ | |
561 | /* wait(10); */ | |
562 | ||
563 | ||
564 | nand->hwcontrol = dfc_hwcontrol; | |
565 | /* nand->dev_ready = dfc_device_ready; */ | |
566 | nand->eccmode = NAND_ECC_SOFT; | |
567 | nand->options = NAND_BUSWIDTH_16; | |
568 | nand->waitfunc = dfc_wait; | |
569 | nand->read_byte = dfc_read_byte; | |
570 | nand->write_byte = dfc_write_byte; | |
571 | nand->read_word = dfc_read_word; | |
572 | nand->write_word = dfc_write_word; | |
573 | nand->read_buf = dfc_read_buf; | |
574 | nand->write_buf = dfc_write_buf; | |
575 | ||
576 | nand->cmdfunc = dfc_cmdfunc; | |
577 | nand->autooob = &delta_oob; | |
578 | nand->badblock_pattern = &delta_bbt_descr; | |
fa230445 | 579 | return 0; |
7c93b244 MK |
580 | } |
581 | ||
582 | #else | |
583 | #error "U-Boot legacy NAND support not available for Monahans DFC." | |
584 | #endif | |
585 | #endif |