merge of '82245638ef37f8730477752665cc0965a7c2556c'
[vuplus_openembedded] / packages / u-boot / u-boot-1.3.2 / mpc8313e-rdb-nand.patch
1 diff -urN u-boot-1.3.1.orig/board/freescale/mpc8313erdb/Makefile u-boot-1.3.1/board/freescale/mpc8313erdb/Makefile
2 --- u-boot-1.3.1.orig/board/freescale/mpc8313erdb/Makefile      2007-12-06 10:21:19.000000000 +0100
3 +++ u-boot-1.3.1/board/freescale/mpc8313erdb/Makefile   2008-01-31 17:35:43.000000000 +0100
4 @@ -25,7 +25,7 @@
5  
6  LIB    = $(obj)lib$(BOARD).a
7  
8 -COBJS  := $(BOARD).o sdram.o
9 +COBJS  := $(BOARD).o sdram.o nand.o
10  
11  SRCS   := $(SOBJS:.o=.S) $(COBJS:.o=.c)
12  OBJS   := $(addprefix $(obj),$(COBJS))
13 diff -urN u-boot-1.3.1.orig/board/freescale/mpc8313erdb/nand.c u-boot-1.3.1/board/freescale/mpc8313erdb/nand.c
14 --- u-boot-1.3.1.orig/board/freescale/mpc8313erdb/nand.c        1970-01-01 01:00:00.000000000 +0100
15 +++ u-boot-1.3.1/board/freescale/mpc8313erdb/nand.c     2008-01-31 17:35:26.000000000 +0100
16 @@ -0,0 +1,868 @@
17 +/*
18 + * Copyright (C) Freescale Semiconductor, Inc. 2006. 
19 + * 
20 + * Initialized by Nick.Spence@freescale.com
21 + *                Wilson.Lo@freescale.com
22 + *
23 + * See file CREDITS for list of people who contributed to this
24 + * project.
25 + *
26 + * This program is free software; you can redistribute it and/or
27 + * modify it under the terms of the GNU General Public License as
28 + * published by the Free Software Foundation; either version 2 of
29 + * the License, or (at your option) any later version.
30 + *
31 + * This program is distributed in the hope that it will be useful,
32 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
33 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
34 + * GNU General Public License for more details.
35 + *
36 + * You should have received a copy of the GNU General Public License
37 + * along with this program; if not, write to the Free Software
38 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
39 + * MA 02111-1307 USA
40 + */
41 +
42 +#include <common.h>
43 +
44 +#if defined(CONFIG_CMD_NAND)
45 +#if defined(CFG_NAND_LEGACY)
46 + #error "U-Boot legacy NAND commands not supported."
47 +#else
48 +
49 +#include <malloc.h>
50 +#include <asm/errno.h>
51 +#include <nand.h>
52 +
53 +#undef CFG_FCM_DEBUG
54 +#define CFG_FCM_DEBUG_LVL 1
55 +#ifdef CFG_FCM_DEBUG
56 +#define FCM_DEBUG(n, args...)                          \
57 +       do {                                            \
58 +               if (n <= (CFG_FCM_DEBUG_LVL + 0))       \
59 +                       printf(args);                   \
60 +       } while(0)
61 +#else /* CONFIG_FCM_DEBUG */
62 +#define FCM_DEBUG(n, args...) do { } while(0)
63 +#endif
64 +
65 +#define MIN(x, y)              ((x < y) ? x : y)
66 +
67 +#define ERR_BYTE 0xFF  /* Value returned for read bytes when read failed */
68 +
69 +#define FCM_TIMEOUT_USECS 100000 /* Maximum number of uSecs to wait for FCM */
70 +
71 +/* Private structure holding NAND Flash device specific information */
72 +struct fcm_nand {
73 +       int             bank;       /* Chip select bank number             */
74 +       unsigned int    base;       /* Chip select base address            */
75 +       int             pgs;        /* NAND page size                      */
76 +       int             oobbuf;     /* Pointer to OOB block                */
77 +       unsigned int    page;       /* Last page written to / read from    */
78 +       unsigned int    fmr;        /* FCM Flash Mode Register value       */
79 +       unsigned int    mdr;        /* UPM/FCM Data Register value         */
80 +       unsigned int    use_mdr;    /* Non zero if the MDR is to be set    */
81 +       u_char         *addr;       /* Address of assigned FCM buffer      */
82 +       unsigned int    read_bytes; /* Number of bytes read during command */
83 +       unsigned int    index;      /* Pointer to next byte to 'read'      */
84 +       unsigned int    req_bytes;  /* Number of bytes read if command ok  */
85 +       unsigned int    req_index;  /* New read index if command ok        */
86 +       unsigned int    status;     /* status read from LTESR after last op*/
87 +};
88 +
89 +
90 +/* These map to the positions used by the FCM hardware ECC generator */
91 +
92 +/* Small Page FLASH with FMR[ECCM] = 0 */
93 +static struct nand_oobinfo fcm_oob_sp_eccm0 = { /* TODO */
94 +       .useecc = MTD_NANDECC_AUTOPL_USR, /* MTD_NANDECC_PLACEONLY, */
95 +       .eccbytes = 3,
96 +       .eccpos = {6, 7, 8},
97 +       .oobfree = { {0, 5}, {9, 7} }
98 +};
99 +
100 +/* Small Page FLASH with FMR[ECCM] = 1 */
101 +static struct nand_oobinfo fcm_oob_sp_eccm1 = { /* TODO */
102 +       .useecc = MTD_NANDECC_AUTOPL_USR, /* MTD_NANDECC_PLACEONLY, */
103 +       .eccbytes = 3,
104 +       .eccpos = {8, 9, 10},
105 +       .oobfree = { {0, 5}, {6, 2}, {11, 5} }
106 +};
107 +
108 +/* Large Page FLASH with FMR[ECCM] = 0 */
109 +static struct nand_oobinfo fcm_oob_lp_eccm0 = {
110 +       .useecc = MTD_NANDECC_AUTOPL_USR, /* MTD_NANDECC_PLACEONLY, */
111 +       .eccbytes = 12,
112 +       .eccpos = {6, 7, 8, 22, 23, 24, 38, 39, 40, 54, 55, 56},
113 +       .oobfree = { {1, 5}, {9, 13}, {25, 13}, {41, 13}, {57, 7} }
114 +};
115 +
116 +/* Large Page FLASH with FMR[ECCM] = 1 */
117 +static struct nand_oobinfo fcm_oob_lp_eccm1 = {
118 +       .useecc = MTD_NANDECC_AUTOPL_USR, /* MTD_NANDECC_PLACEONLY, */
119 +       .eccbytes = 12,
120 +       .eccpos = {8, 9, 10, 24, 25, 26, 40, 41, 42, 56, 57, 58},
121 +       .oobfree = { {1, 7}, {11, 13}, {27, 13}, {43, 13}, {59, 5} }
122 +};
123 +
124 +/*
125 + * execute FCM command and wait for it to complete
126 + */
127 +static int fcm_run_command(struct mtd_info *mtd)
128 +{
129 +       volatile immap_t *im = (immap_t *) CFG_IMMR;
130 +       volatile lbus83xx_t *lbc= &im->lbus;
131 +       register struct nand_chip *this = mtd->priv;
132 +       struct fcm_nand *fcm = this->priv;
133 +       long long end_tick;
134 +
135 +       /* Setup the FMR[OP] to execute without write protection */
136 +       lbc->fmr = fcm->fmr | 3;
137 +       if (fcm->use_mdr)
138 +               lbc->mdr = fcm->mdr;
139 +
140 +       FCM_DEBUG(5,"fcm_run_command: fmr= %08X fir= %08X fcr= %08X\n",
141 +               lbc->fmr, lbc->fir, lbc->fcr);
142 +       FCM_DEBUG(5,"fcm_run_command: fbar=%08X fpar=%08X fbcr=%08X bank=%d\n",
143 +               lbc->fbar, lbc->fpar, lbc->fbcr, fcm->bank);
144 +
145 +       /* clear event registers */
146 +       lbc->lteatr = 0;
147 +       lbc->ltesr |= (LTESR_FCT | LTESR_PAR | LTESR_CC);
148 +
149 +       /* execute special operation */
150 +       lbc->lsor = fcm->bank;
151 +
152 +       /* wait for FCM complete flag or timeout */
153 +       fcm->status = 0;
154 +       end_tick = usec2ticks(FCM_TIMEOUT_USECS) + get_ticks();
155 +
156 +       while (end_tick > get_ticks()) {
157 +               if (lbc->ltesr & LTESR_CC) {
158 +                       fcm->status = lbc->ltesr &
159 +                                       (LTESR_FCT | LTESR_PAR | LTESR_CC);
160 +                       break;
161 +               }
162 +       }
163 +
164 +       /* store mdr value in case it was needed */
165 +       if (fcm->use_mdr)
166 +               fcm->mdr = lbc->mdr;
167 +
168 +       fcm->use_mdr = 0;
169 +
170 +       FCM_DEBUG(5,"fcm_run_command: stat=%08X mdr= %08X fmr= %08X\n",
171 +               fcm->status, fcm->mdr, lbc->fmr);
172 +
173 +       /* if the operation completed ok then set the read buffer pointers */
174 +       if (fcm->status == LTESR_CC) {
175 +               fcm->read_bytes = fcm->req_bytes;
176 +               fcm->index      = fcm->req_index;
177 +               return 0;
178 +       }
179 +
180 +       return -1;
181 +}
182 +
183 +/*
184 + * Set up the FCM hardware block and page address fields, and the fcm
185 + * structure addr field to point to the correct FCM buffer in memory
186 + */
187 +static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob)
188 +{
189 +       volatile immap_t *im = (immap_t *) CFG_IMMR;
190 +       volatile lbus83xx_t *lbc= &im->lbus;
191 +       register struct nand_chip *this = mtd->priv;
192 +       struct fcm_nand *fcm = this->priv;
193 +       int buf_num;
194 +
195 +       fcm->page = page_addr;
196 +
197 +       lbc->fbar = page_addr >> (this->phys_erase_shift - this->page_shift);
198 +       if (fcm->pgs) {
199 +               lbc->fpar = ((page_addr << FPAR_LP_PI_SHIFT) & FPAR_LP_PI) |
200 +                           ( oob ? FPAR_LP_MS : 0) |
201 +                             column;
202 +               buf_num = (page_addr & 1) << 2;
203 +       } else {
204 +               lbc->fpar = ((page_addr << FPAR_SP_PI_SHIFT) & FPAR_SP_PI) |
205 +                           ( oob ? FPAR_SP_MS : 0) |
206 +                             column;
207 +               buf_num = page_addr & 7;
208 +       }
209 +       fcm->addr = (unsigned char*)(fcm->base + (buf_num * 1024));
210 +
211 +       /* for OOB data point to the second half of the buffer */
212 +       if (oob) {
213 +               fcm->addr += (fcm->pgs ? 2048 : 512);
214 +       }
215 +}
216 +
217 +/* not required for FCM */
218 +static void fcm_hwcontrol(struct mtd_info *mtdinfo, int cmd)
219 +{
220 +       return;
221 +}
222 +
223 +
224 +/*
225 + * FCM does not support 16 bit data busses
226 + */
227 +static u16 fcm_read_word(struct mtd_info *mtd)
228 +{
229 +       printf("fcm_read_word: UNIMPLEMENTED.\n");
230 +       return 0;
231 +}
232 +static void fcm_write_word(struct mtd_info *mtd, u16 word)
233 +{
234 +       printf("fcm_write_word: UNIMPLEMENTED.\n");
235 +}
236 +
237 +/*
238 + * Write buf to the FCM Controller Data Buffer
239 + */
240 +static void fcm_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
241 +{
242 +       register struct nand_chip *this = mtd->priv;
243 +       struct fcm_nand *fcm = this->priv;
244 +
245 +       FCM_DEBUG(3,"fcm_write_buf: writing %d bytes starting with 0x%x"
246 +                   " at %d.\n", len, *((unsigned long*) buf), fcm->index);
247 +
248 +       /* If armed catch the address of the OOB buffer so that it can be */
249 +       /* updated with the real signature after the program comletes */
250 +       if (!fcm->oobbuf)
251 +               fcm->oobbuf = (int) buf;
252 +
253 +       /* copy the data into the FCM hardware buffer and update the index */
254 +       memcpy(&(fcm->addr[fcm->index]), buf, len);
255 +       fcm->index += len;
256 +       return;
257 +}
258 +
259 +
260 +/*
261 + * FCM does not support individual writes. Instead these are either commands
262 + * or data being written, both of which are handled through the cmdfunc
263 + * handler.
264 + */
265 +static void fcm_write_byte(struct mtd_info *mtd, u_char byte)
266 +{
267 +       printf("fcm_write_byte: UNIMPLEMENTED.\n");
268 +}
269 +
270 +/*
271 + * read a byte from either the FCM hardware buffer if it has any data left
272 + * otherwise issue a command to read a single byte.
273 + */
274 +static u_char fcm_read_byte(struct mtd_info *mtd)
275 +{
276 +       volatile immap_t *im = (immap_t *) CFG_IMMR;
277 +       volatile lbus83xx_t *lbc= &im->lbus;
278 +       register struct nand_chip *this = mtd->priv;
279 +       struct fcm_nand *fcm = this->priv;
280 +       unsigned char byte;
281 +
282 +       /* If there are still bytes in the FCM then use the next byte */
283 +       if(fcm->index < fcm->read_bytes) {
284 +               byte = fcm->addr[(fcm->index)++];
285 +               FCM_DEBUG(4,"fcm_read_byte: byte %u (%02X): %d of %d.\n",
286 +                         byte, byte, fcm->index-1, fcm->read_bytes);
287 +       } else {
288 +               /* otherwise issue a command to read 1 byte */
289 +               lbc->fir = (FIR_OP_RSW << FIR_OP0_SHIFT);
290 +               fcm->use_mdr = 1;
291 +               fcm->read_bytes = 0;
292 +               fcm->index = 0;
293 +               fcm->req_bytes = 0;
294 +               fcm->req_index = 0;
295 +               byte = fcm_run_command(mtd) ? ERR_BYTE : fcm->mdr & 0xff;
296 +               FCM_DEBUG(4,"fcm_read_byte: byte %u (%02X) from bus.\n",
297 +                         byte, byte);
298 +       }
299 +
300 +       return byte;
301 +}
302 +
303 +
304 +/*
305 + * Read from the FCM Controller Data Buffer
306 + */
307 +static void fcm_read_buf(struct mtd_info *mtd, u_char* buf, int len)
308 +{
309 +       volatile immap_t *im = (immap_t *) CFG_IMMR;
310 +       volatile lbus83xx_t *lbc= &im->lbus;
311 +       register struct nand_chip *this = mtd->priv;
312 +       struct fcm_nand *fcm = this->priv;
313 +       int i;
314 +       int rest;
315 +
316 +       FCM_DEBUG(3,"fcm_read_buf: reading %d bytes.\n", len);
317 +
318 +       /* If last read failed then return error bytes */
319 +       if (fcm->status != LTESR_CC) {
320 +               /* just keep copying bytes so that the oob works */
321 +               memcpy(buf, &(fcm->addr[(fcm->index)]), len);
322 +               fcm->index += len;
323 +       }
324 +       else
325 +       {
326 +               /* see how much is still in the FCM buffer */
327 +               i = min(len, (fcm->read_bytes - fcm->index));
328 +               rest = i - len;
329 +               len = i;
330 +
331 +               memcpy(buf, &(fcm->addr[(fcm->index)]), len);
332 +               fcm->index += len;
333 +
334 +               /* If more data is needed then issue another block read */
335 +               if (rest) {
336 +                       FCM_DEBUG(3,"fcm_read_buf: getting %d more bytes.\n",
337 +                                   rest);
338 +                       buf += len;
339 +                       lbc->fir = (FIR_OP_RBW << FIR_OP0_SHIFT);
340 +                       set_addr(mtd, 0, 0, 0);
341 +                       lbc->fbcr = rest;
342 +                       fcm->req_bytes = lbc->fbcr;
343 +                       fcm->req_index = 0;
344 +                       fcm->use_mdr = 0;
345 +                       if (!fcm_run_command(mtd))
346 +                               fcm_read_buf(mtd, buf, rest);
347 +                       else
348 +                               memcpy(buf, fcm->addr, rest);
349 +               }
350 +       }
351 +       return;
352 +}
353 +
354 +
355 +/*
356 + * Verify buffer against the FCM Controller Data Buffer
357 + */
358 +static int fcm_verify_buf(struct mtd_info *mtd, const u_char *buf, int len)
359 +{
360 +       volatile immap_t *im = (immap_t *) CFG_IMMR;
361 +       volatile lbus83xx_t *lbc= &im->lbus;
362 +       register struct nand_chip *this = mtd->priv;
363 +       struct fcm_nand *fcm = this->priv;
364 +       int i;
365 +       int rest;
366 +
367 +       FCM_DEBUG(3,"fcm_verify_buf: checking %d bytes starting with 0x%02x.\n",
368 +               len, *((unsigned long*) buf));
369 +       /* If last read failed then return error bytes */
370 +       if (fcm->status != LTESR_CC) {
371 +               return EFAULT;
372 +       }
373 +
374 +       /* see how much is still in the FCM buffer */
375 +       i = min(len, (fcm->read_bytes - fcm->index));
376 +       rest = i - len;
377 +       len = i;
378 +
379 +       if (memcmp(buf, &(fcm->addr[(fcm->index)]), len)) {
380 +               return EFAULT;
381 +       }
382 +
383 +       fcm->index += len;
384 +       if (rest) {
385 +               FCM_DEBUG(3,"fcm_verify_buf: getting %d more bytes.\n", rest);
386 +               buf += len;
387 +               lbc->fir = (FIR_OP_RBW << FIR_OP0_SHIFT);
388 +               set_addr(mtd, 0, 0, 0);
389 +               lbc->fbcr = rest;
390 +               fcm->req_bytes = lbc->fbcr;
391 +               fcm->req_index = 0;
392 +               fcm->use_mdr = 0;
393 +               if (fcm_run_command(mtd))
394 +                       return EFAULT;
395 +               return fcm_verify_buf(mtd, buf, rest);
396 +
397 +       }
398 +       return 0;
399 +}
400 +
401 +/* this function is called after Program and Erase Operations to
402 + * check for success or failure */
403 +static int fcm_wait(struct mtd_info *mtd, struct nand_chip *this, int state)
404 +{
405 +       volatile immap_t *im = (immap_t *) CFG_IMMR;
406 +       volatile lbus83xx_t *lbc= &im->lbus;
407 +       struct fcm_nand *fcm = this->priv;
408 +
409 +       if (fcm->status != LTESR_CC) {
410 +               return(0x1); /* Status Read error */
411 +       }
412 +
413 +       /* Use READ_STATUS command, but wait for the device to be ready */
414 +       fcm->use_mdr = 0;
415 +       fcm->req_index = 0;
416 +       fcm->read_bytes = 0;
417 +       fcm->index = 0;
418 +       fcm->oobbuf = -1;
419 +       lbc->fir = (FIR_OP_CW0 << FIR_OP0_SHIFT) |
420 +                  (FIR_OP_RBW << FIR_OP1_SHIFT);
421 +       lbc->fcr = (NAND_CMD_STATUS << FCR_CMD0_SHIFT);
422 +       set_addr(mtd, 0, 0, 0);
423 +       lbc->fbcr = 1;
424 +       fcm->req_bytes = lbc->fbcr;
425 +       fcm_run_command(mtd);
426 +       if (fcm->status != LTESR_CC) {
427 +               return(0x1); /* Status Read error */
428 +       }
429 +       return this->read_byte(mtd);
430 +}
431 +
432 +
433 +/* cmdfunc send commands to the FCM */
434 +static void fcm_cmdfunc(struct mtd_info *mtd, unsigned command,
435 +                       int column, int page_addr)
436 +{
437 +       volatile immap_t *im = (immap_t *) CFG_IMMR;
438 +       volatile lbus83xx_t *lbc= &im->lbus;
439 +       register struct nand_chip *this = mtd->priv;
440 +       struct fcm_nand *fcm = this->priv;
441 +
442 +       fcm->use_mdr = 0;
443 +       fcm->req_index = 0;
444 +
445 +       /* clear the read buffer */
446 +       fcm->read_bytes = 0;
447 +       if (command != NAND_CMD_PAGEPROG) {
448 +               fcm->index = 0;
449 +               fcm->oobbuf = -1;
450 +       }
451 +
452 +       switch (command) {
453 +       /* READ0 and READ1 read the entire buffer to use hardware ECC */
454 +       case NAND_CMD_READ1:
455 +               FCM_DEBUG(2,"fcm_cmdfunc: NAND_CMD_READ1, page_addr:"
456 +                           " 0x%x, column: 0x%x.\n", page_addr, column);
457 +               fcm->req_index = column + 256;
458 +               goto read0;
459 +       case NAND_CMD_READ0:
460 +               FCM_DEBUG(2,"fcm_cmdfunc: NAND_CMD_READ0, page_addr:"
461 +                           " 0x%x, column: 0x%x.\n", page_addr, column);
462 +               fcm->req_index = column;
463 +read0:
464 +               if (fcm->pgs) {
465 +                       lbc->fir = (FIR_OP_CW0 << FIR_OP0_SHIFT) |
466 +                                  (FIR_OP_CA  << FIR_OP1_SHIFT) |
467 +                                  (FIR_OP_PA  << FIR_OP2_SHIFT) |
468 +                                  (FIR_OP_CW1 << FIR_OP3_SHIFT) |
469 +                                  (FIR_OP_RBW << FIR_OP4_SHIFT);
470 +               } else {
471 +                       lbc->fir = (FIR_OP_CW0 << FIR_OP0_SHIFT) |
472 +                                  (FIR_OP_CA  << FIR_OP1_SHIFT) |
473 +                                  (FIR_OP_PA  << FIR_OP2_SHIFT) |
474 +                                  (FIR_OP_RBW << FIR_OP3_SHIFT);
475 +               }
476 +               lbc->fcr = (NAND_CMD_READ0     << FCR_CMD0_SHIFT) |
477 +                          (NAND_CMD_READSTART << FCR_CMD1_SHIFT);
478 +               lbc->fbcr = 0; /* read entire page to enable ECC */
479 +               set_addr(mtd, 0, page_addr, 0);
480 +               fcm->req_bytes = mtd->oobblock + mtd->oobsize;
481 +               goto write_cmd2;
482 +       /* READOOB read only the OOB becasue no ECC is performed */
483 +       case NAND_CMD_READOOB:
484 +               FCM_DEBUG(2,"fcm_cmdfunc: NAND_CMD_READOOB, page_addr:"
485 +                           " 0x%x, column: 0x%x.\n", page_addr, column);
486 +               if (fcm->pgs) {
487 +                       lbc->fir = (FIR_OP_CW0 << FIR_OP0_SHIFT) |
488 +                                  (FIR_OP_CA  << FIR_OP1_SHIFT) |
489 +                                  (FIR_OP_PA  << FIR_OP2_SHIFT) |
490 +                                  (FIR_OP_CW1 << FIR_OP3_SHIFT) |
491 +                                  (FIR_OP_RBW << FIR_OP4_SHIFT);
492 +                       lbc->fcr = (NAND_CMD_READ0     << FCR_CMD0_SHIFT) |
493 +                                  (NAND_CMD_READSTART << FCR_CMD1_SHIFT);
494 +               } else {
495 +                       lbc->fir = (FIR_OP_CW0 << FIR_OP0_SHIFT) |
496 +                                  (FIR_OP_CA  << FIR_OP1_SHIFT) |
497 +                                  (FIR_OP_PA  << FIR_OP2_SHIFT) |
498 +                                  (FIR_OP_RBW << FIR_OP3_SHIFT);
499 +                       lbc->fcr = (NAND_CMD_READOOB << FCR_CMD0_SHIFT);
500 +               }
501 +               lbc->fbcr = mtd->oobsize - column;
502 +               set_addr(mtd, column, page_addr, 1);
503 +               goto write_cmd1;
504 +       /* READID must read all 5 possible bytes while CEB is active */
505 +       case NAND_CMD_READID:
506 +               FCM_DEBUG(2,"fcm_cmdfunc: NAND_CMD_READID.\n");
507 +               lbc->fir = (FIR_OP_CW0 << FIR_OP0_SHIFT) |
508 +                          (FIR_OP_UA  << FIR_OP1_SHIFT) |
509 +                          (FIR_OP_RBW << FIR_OP2_SHIFT);
510 +               lbc->fcr = (NAND_CMD_READID << FCR_CMD0_SHIFT);
511 +               lbc->fbcr = 5; /* 5 bytes for manuf, device and exts */
512 +               fcm->use_mdr = 1;
513 +               fcm->mdr = 0;
514 +               goto write_cmd0;
515 +       /* ERASE1 stores the block and page address */
516 +       case NAND_CMD_ERASE1:
517 +               FCM_DEBUG(2,"fcm_cmdfunc: NAND_CMD_ERASE1, page_addr:"
518 +                           " 0x%x.\n", page_addr);
519 +               set_addr(mtd, 0, page_addr, 0);
520 +               goto end;
521 +       /* ERASE2 uses the block and page address from ERASE1 */
522 +       case NAND_CMD_ERASE2:
523 +               FCM_DEBUG(2,"fcm_cmdfunc: NAND_CMD_ERASE2.\n");
524 +               lbc->fir = (FIR_OP_CW0 << FIR_OP0_SHIFT) |
525 +                          (FIR_OP_PA  << FIR_OP1_SHIFT) |
526 +                          (FIR_OP_CM1 << FIR_OP2_SHIFT);
527 +               lbc->fcr = (NAND_CMD_ERASE1 << FCR_CMD0_SHIFT) |
528 +                          (NAND_CMD_ERASE2 << FCR_CMD1_SHIFT);
529 +               lbc->fbcr = 0;
530 +               goto write_cmd1;
531 +       /* SEQIN sets up the addr buffer and all registers except the length */
532 +       case NAND_CMD_SEQIN:
533 +               FCM_DEBUG(2,"fcm_cmdfunc: NAND_CMD_SEQIN/PAGE_PROG, page_addr:"
534 +                           " 0x%x, column: 0x%x.\n", page_addr, column);
535 +               if (column == 0) {
536 +                       lbc->fbcr = 0; /* write entire page to enable ECC */
537 +               } else {
538 +                       lbc->fbcr = 1; /* mark as partial page so no HW ECC */
539 +               }
540 +               if (fcm->pgs) {
541 +                       /* always use READ0 for large page devices */
542 +                       lbc->fir = (FIR_OP_CW0 << FIR_OP0_SHIFT) |
543 +                                  (FIR_OP_CA  << FIR_OP1_SHIFT) |
544 +                                  (FIR_OP_PA  << FIR_OP2_SHIFT) |
545 +                                  (FIR_OP_WB  << FIR_OP3_SHIFT) |
546 +                                  (FIR_OP_CW1 << FIR_OP4_SHIFT);
547 +                       lbc->fcr = (NAND_CMD_SEQIN << FCR_CMD0_SHIFT) |
548 +                                  (NAND_CMD_PAGEPROG << FCR_CMD1_SHIFT);
549 +                       set_addr(mtd, column, page_addr, 0);
550 +               } else {
551 +                       lbc->fir = (FIR_OP_CW0 << FIR_OP0_SHIFT) |
552 +                                  (FIR_OP_CM2 << FIR_OP1_SHIFT) |
553 +                                  (FIR_OP_CA  << FIR_OP2_SHIFT) |
554 +                                  (FIR_OP_PA  << FIR_OP3_SHIFT) |
555 +                                  (FIR_OP_WB  << FIR_OP4_SHIFT) |
556 +                                  (FIR_OP_CW1 << FIR_OP5_SHIFT);
557 +                       if (column >= mtd->oobblock) {
558 +                               /* OOB area --> READOOB */
559 +                               column -= mtd->oobblock;
560 +                               lbc->fcr = (NAND_CMD_READOOB << FCR_CMD0_SHIFT)
561 +                                        | (NAND_CMD_PAGEPROG<< FCR_CMD1_SHIFT)
562 +                                        | (NAND_CMD_SEQIN << FCR_CMD2_SHIFT);
563 +                               set_addr(mtd, column, page_addr, 1);
564 +                       } else if (column < 256) {
565 +                               /* First 256 bytes --> READ0 */
566 +                               lbc->fcr = (NAND_CMD_READ0 << FCR_CMD0_SHIFT)
567 +                                        | (NAND_CMD_PAGEPROG<< FCR_CMD1_SHIFT)
568 +                                        | (NAND_CMD_SEQIN << FCR_CMD2_SHIFT);
569 +                               set_addr(mtd, column, page_addr, 0);
570 +                       } else {
571 +                               /* Second 256 bytes --> READ1 */
572 +                               column -= 256;
573 +                               lbc->fcr = (NAND_CMD_READ1 << FCR_CMD0_SHIFT)
574 +                                        | (NAND_CMD_PAGEPROG<< FCR_CMD1_SHIFT)
575 +                                        | (NAND_CMD_SEQIN << FCR_CMD2_SHIFT);
576 +                               set_addr(mtd, column, page_addr, 0);
577 +                       }
578 +               }
579 +               goto end;
580 +       /* PAGEPROG reuses all of the setup from SEQIN and adds the length */
581 +       case NAND_CMD_PAGEPROG:
582 +               FCM_DEBUG(2,"fcm_cmdfunc: NAND_CMD_PAGEPROG"
583 +                           " writing %d bytes.\n",fcm->index);
584 +               /* if the write did not start at 0 or is not a full page */
585 +               /* then set the exact length, otherwise use a full page  */
586 +               /* write so the HW generates the ECC. */
587 +               if (lbc->fbcr ||
588 +                  (fcm->index != (mtd->oobblock + mtd->oobsize)))
589 +                       lbc->fbcr = fcm->index;
590 +               fcm->req_bytes = 0;
591 +               goto write_cmd2;
592 +       /* CMD_STATUS must read the status byte while CEB is active */
593 +       /* Note - it does not wait for the ready line */
594 +       case NAND_CMD_STATUS:
595 +               FCM_DEBUG(2,"fcm_cmdfunc: NAND_CMD_STATUS.\n");
596 +               lbc->fir = (FIR_OP_CM0 << FIR_OP0_SHIFT) |
597 +                          (FIR_OP_RBW << FIR_OP1_SHIFT);
598 +               lbc->fcr = (NAND_CMD_STATUS << FCR_CMD0_SHIFT);
599 +               lbc->fbcr = 1;
600 +               goto write_cmd0;
601 +       /* RESET without waiting for the ready line */
602 +       case NAND_CMD_RESET:
603 +               FCM_DEBUG(2,"fcm_cmdfunc: NAND_CMD_RESET.\n");
604 +               lbc->fir = (FIR_OP_CM0 << FIR_OP0_SHIFT);
605 +               lbc->fcr = (NAND_CMD_RESET << FCR_CMD0_SHIFT);
606 +               lbc->fbcr = 0;
607 +               goto write_cmd0;
608 +       default:
609 +               printk("fcm_cmdfunc: error, unsupported command.\n");
610 +               goto end;
611 +       }
612 +
613 +       /* Short cuts fall through to save code */
614 + write_cmd0:
615 +       set_addr(mtd, 0, 0, 0);
616 + write_cmd1:
617 +       fcm->req_bytes = lbc->fbcr;
618 + write_cmd2:
619 +       fcm_run_command(mtd);
620 +
621 +#ifdef CONFIG_MTD_NAND_VERIFY_WRITE
622 +       /* if we wrote a page then read back the oob to get the ECC */
623 +       if ((command == NAND_CMD_PAGEPROG) &&
624 +           (this->eccmode > NAND_ECC_SOFT) &&
625 +           (lbc->fbcr == 0) &&
626 +           (fcm->oobbuf != 0) &&
627 +           (fcm->oobbuf != -1)) {
628 +               int i;
629 +               uint *oob_config;
630 +               unsigned char *oob_buf;
631 +
632 +               i = fcm->page;
633 +               oob_buf = (unsigned char*) fcm->oobbuf;
634 +               oob_config = this->autooob->eccpos;
635 +
636 +               /* wait for the write to complete and check it passed */
637 +               if (!(this->waitfunc(mtd, this, FL_WRITING) & 0x01)) {
638 +                       /* read back the OOB */
639 +                       fcm_cmdfunc(mtd, NAND_CMD_READOOB, 0, i);
640 +                       /* if it succeeded then copy the ECC bytes */
641 +                       if (fcm->status == LTESR_CC) {
642 +                               for (i = 0; i < this->eccbytes; i++) {
643 +                                       oob_buf[oob_config[i]] =
644 +                                               fcm->addr[oob_config[i]];
645 +                               }
646 +                       }
647 +               }
648 +       }
649 +#endif
650 +
651 + end:
652 +       return;
653 +}
654 +
655 +/*
656 + * fcm_enable_hwecc - start ECC generation
657 + */
658 +static void fcm_enable_hwecc(struct mtd_info *mtd, int mode)
659 +{
660 +       return;
661 +}
662 +
663 +/*
664 + * fcm_calculate_ecc - Calculate the ECC bytes
665 + * This is done by hardware during the write process, so we use this
666 + * to arm the oob buf capture on the next write_buf() call. The ECC bytes
667 + * only need to be captured if CONFIG_MTD_NAND_VERIFY_WRITE is defined which
668 + * reads back the pages and checks they match the data and oob buffers.
669 + */
670 +static int fcm_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code)
671 +{
672 +       register struct nand_chip *this = mtd->priv;
673 +       struct fcm_nand *fcm = this->priv;
674 +
675 +#ifdef CONFIG_MTD_NAND_VERIFY_WRITE
676 +       /* arm capture of oob buf ptr on next write_buf */
677 +       fcm->oobbuf = 0;
678 +#endif
679 +       return 0;
680 +}
681 +
682 +/*
683 + * fcm_correct_data - Detect and correct bit error(s)
684 + * The detection and correction is done automatically by the hardware,
685 + * if the complete page was read. If the status code is okay then there
686 + * was no error, otherwise we return an error code indicating an uncorrectable
687 + * error.
688 + */
689 +static int fcm_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc)
690 +{
691 +       register struct nand_chip *this = mtd->priv;
692 +       struct fcm_nand *fcm = this->priv;
693 +
694 +       /* No errors */
695 +       if (fcm->status == LTESR_CC)
696 +               return 0;
697 +
698 +       return -1; /* uncorrectable error */
699 +}
700 +
701 +
702 +
703 +/*
704 + * Dummy scan_bbt to complete setup of the FMR based on NAND size
705 + */
706 +static int fcm_scan_bbt (struct mtd_info *mtd)
707 +{
708 +       volatile immap_t *im = (immap_t *) CFG_IMMR;
709 +       volatile lbus83xx_t *lbc= &im->lbus;
710 +       register struct nand_chip *this = mtd->priv;
711 +       struct fcm_nand *fcm = this->priv;
712 +       unsigned int i;
713 +       unsigned int al;
714 +
715 +       if (!fcm) {
716 +               printk (KERN_ERR "fcm_scan_bbt():" \
717 +                       " Failed to allocate chip specific data structure\n");
718 +               return -1;
719 +       }
720 +
721 +       /* calculate FMR Address Length field */
722 +       al = 0;
723 +       for (i = this->pagemask >> 16; i ; i >>= 8) {
724 +               al++;
725 +       }
726 +
727 +       /* add to ECCM mode set in fcm_init */
728 +       fcm->fmr |= 12 << FMR_CWTO_SHIFT |  /* Timeout > 12 mSecs */
729 +                   al << FMR_AL_SHIFT;
730 +
731 +       FCM_DEBUG(1,"fcm_init: nand->options  =   %08X\n", this->options);
732 +       FCM_DEBUG(1,"fcm_init: nand->numchips = %10d\n", this->numchips);
733 +       FCM_DEBUG(1,"fcm_init: nand->chipsize = %10d\n", this->chipsize);
734 +       FCM_DEBUG(1,"fcm_init: nand->pagemask = %10X\n", this->pagemask);
735 +       FCM_DEBUG(1,"fcm_init: nand->eccmode  = %10d\n", this->eccmode );
736 +       FCM_DEBUG(1,"fcm_init: nand->eccsize  = %10d\n", this->eccsize );
737 +       FCM_DEBUG(1,"fcm_init: nand->eccbytes = %10d\n", this->eccbytes);
738 +       FCM_DEBUG(1,"fcm_init: nand->eccsteps = %10d\n", this->eccsteps);
739 +       FCM_DEBUG(1,"fcm_init: nand->chip_delay = %8d\n", this->chip_delay);
740 +       FCM_DEBUG(1,"fcm_init: nand->badblockpos = %7d\n", this->badblockpos);
741 +       FCM_DEBUG(1,"fcm_init: nand->chip_shift = %8d\n", this->chip_shift);
742 +       FCM_DEBUG(1,"fcm_init: nand->page_shift = %8d\n", this->page_shift);
743 +       FCM_DEBUG(1,"fcm_init: nand->phys_erase_shift = %2d\n",
744 +                                                     this->phys_erase_shift);
745 +       FCM_DEBUG(1,"fcm_init: mtd->flags     =   %08X\n", mtd->flags);
746 +       FCM_DEBUG(1,"fcm_init: mtd->size      = %10d\n", mtd->size);
747 +       FCM_DEBUG(1,"fcm_init: mtd->erasesize = %10d\n", mtd->erasesize);
748 +       FCM_DEBUG(1,"fcm_init: mtd->oobblock  = %10d\n", mtd->oobblock);
749 +       FCM_DEBUG(1,"fcm_init: mtd->oobsize   = %10d\n", mtd->oobsize);
750 +       FCM_DEBUG(1,"fcm_init: mtd->oobavail  = %10d\n", mtd->oobavail);
751 +       FCM_DEBUG(1,"fcm_init: mtd->ecctype   = %10d\n", mtd->ecctype);
752 +       FCM_DEBUG(1,"fcm_init: mtd->eccsize   = %10d\n", mtd->eccsize);
753 +
754 +       /* adjust Option Register and ECC to match Flash page size */
755 +       if (mtd->oobblock == 512)
756 +               lbc->bank[fcm->bank].or &= ~(OR_FCM_PGS);
757 +       else if (mtd->oobblock == 2048) {
758 +               lbc->bank[fcm->bank].or |= OR_FCM_PGS;
759 +               /* adjust ecc setup if needed */
760 +               if ( (lbc->bank[fcm->bank].br & BR_DECC) == BR_DECC_CHK_GEN) {
761 +                       mtd->eccsize = 2048;
762 +                       mtd->oobavail -= 9;
763 +                       this->eccmode = NAND_ECC_HW12_2048;
764 +                       this->eccsize = 2048;
765 +                       this->eccbytes += 9;
766 +                       this->eccsteps = 1;
767 +                       this->autooob = (fcm->fmr & FMR_ECCM) ?
768 +                                       &fcm_oob_lp_eccm1 : &fcm_oob_lp_eccm0;
769 +                       memcpy(&mtd->oobinfo, this->autooob,
770 +                                       sizeof(mtd->oobinfo));
771 +               }
772 +       }
773 +       else {
774 +               printf("fcm_init: page size %d is not supported\n",
775 +                       mtd->oobblock);
776 +               return -1;
777 +       }
778 +       fcm->pgs = (lbc->bank[fcm->bank].or>>OR_FCM_PGS_SHIFT) & 1;
779 +
780 +       if (al > 2) {
781 +               printf("fcm_init: %d address bytes is not supported\n", al+2);
782 +               return -1;
783 +       }
784 +
785 +       /* restore default scan_bbt function and call it */
786 +       this->scan_bbt = nand_default_bbt;
787 +       return nand_default_bbt(mtd);
788 +}
789 +
790 +/*
791 + * Board-specific NAND initialization. The following members of the
792 + * argument are board-specific (per include/linux/mtd/nand_new.h):
793 + * - IO_ADDR_R?: address to read the 8 I/O lines of the flash device
794 + * - IO_ADDR_W?: address to write the 8 I/O lines of the flash device
795 + * - hwcontrol: hardwarespecific function for accesing control-lines
796 + * - dev_ready: hardwarespecific function for accesing device ready/busy line
797 + * - enable_hwecc: function to enable (reset) hardware ecc generator. Must
798 + *   only be provided if a hardware ECC is available
799 + * - eccmode: mode of ecc, see defines
800 + * - chip_delay: chip dependent delay for transfering data from array to
801 + *   read regs (tR)
802 + * - options: various chip options. They can partly be set to inform
803 + *   nand_scan about special functionality. See the defines for further
804 + *   explanation
805 + * Members with a "?" were not set in the merged testing-NAND branch,
806 + * so they are not set here either.
807 + */
808 +int board_nand_init(struct nand_chip *nand)
809 +{
810 +       volatile immap_t *im = (immap_t *) CFG_IMMR;
811 +       volatile lbus83xx_t *lbc= &im->lbus;
812 +       struct fcm_nand *fcm;
813 +       unsigned int bank;
814 +
815 +       /* Enable FCM detection of timeouts, ECC errors and completion */
816 +       lbc->ltedr &= ~(LTESR_FCT | LTESR_PAR | LTESR_CC);
817 +
818 +       fcm = kmalloc (sizeof(struct fcm_nand), GFP_KERNEL);
819 +       if (!fcm) {
820 +               printk (KERN_ERR "board_nand_init():" \
821 +                       " Cannot allocate read buffer data structure\n");
822 +               return;
823 +       }
824 +
825 +       /* Find which chip select bank is being used for this device */
826 +       for (bank=0; bank<8; bank++) {
827 +               if ( (lbc->bank[bank].br & BR_V) &&
828 +                  ( (lbc->bank[bank].br & BR_MSEL) == BR_MS_FCM ) &&
829 +                  ( (lbc->bank[bank].br & BR_BA) ==
830 +                    (lbc->bank[bank].or & OR_FCM_AM &
831 +                       (unsigned int)(nand->IO_ADDR_R) ) ) ) {
832 +                       fcm->bank = bank;
833 +// TODO                        fcm->fmr = FMR_ECCM; /* rest filled in later */
834 +                       fcm->fmr = 0; /* rest filled in later */
835 +                       fcm->read_bytes = 0;
836 +                       fcm->index = 0;
837 +                       fcm->pgs = (lbc->bank[bank].or>>OR_FCM_PGS_SHIFT) & 1;
838 +                       fcm->base = lbc->bank[bank].br & BR_BA;
839 +                       fcm->addr = (unsigned char*) (fcm->base);
840 +                       nand->priv = fcm;
841 +                       fcm->oobbuf = -1;
842 +                       break;
843 +               }
844 +       }
845 +
846 +       if (!nand->priv) {
847 +               printk (KERN_ERR "board_nand_init():" \
848 +                       " Could not find matching Chip Select\n");
849 +               return -1;
850 +       }
851 +
852 +       /* set up nand options */
853 +       nand->options = 0;
854 +       /* set up function call table */
855 +       nand->hwcontrol = fcm_hwcontrol;
856 +       nand->waitfunc = fcm_wait;
857 +       nand->read_byte = fcm_read_byte;
858 +       nand->write_byte = fcm_write_byte;
859 +       nand->read_word = fcm_read_word;
860 +       nand->write_word = fcm_write_word;
861 +       nand->read_buf = fcm_read_buf;
862 +       nand->verify_buf = fcm_verify_buf;
863 +       nand->write_buf = fcm_write_buf;
864 +       nand->cmdfunc = fcm_cmdfunc;
865 +       nand->scan_bbt = fcm_scan_bbt;
866 +
867 +       /* If CS Base Register selects full hardware ECC then use it */
868 +       if ( ( (lbc->bank[bank].br & BR_DECC) >> BR_DECC_SHIFT) == 2) {
869 +               /* put in small page settings and adjust later if needed */
870 +               nand->eccmode = NAND_ECC_HW3_512;
871 +               nand->autooob = (fcm->fmr & FMR_ECCM) ?
872 +                               &fcm_oob_sp_eccm1 : &fcm_oob_sp_eccm0;
873 +               nand->calculate_ecc = fcm_calculate_ecc;
874 +               nand->correct_data = fcm_correct_data;
875 +               nand->enable_hwecc = fcm_enable_hwecc;
876 +       } else {
877 +               /* otherwise fall back to default software ECC */
878 +               nand->eccmode = NAND_ECC_SOFT;
879 +       }
880 +       return 0;
881 +}
882 +
883 +#endif
884 +#endif
885 diff -urN u-boot-1.3.1.orig/include/configs/MPC8313ERDB.h u-boot-1.3.1/include/configs/MPC8313ERDB.h
886 --- u-boot-1.3.1.orig/include/configs/MPC8313ERDB.h     2007-12-06 10:21:19.000000000 +0100
887 +++ u-boot-1.3.1/include/configs/MPC8313ERDB.h  2008-01-31 17:36:18.000000000 +0100
888 @@ -360,6 +360,7 @@
889  #define CONFIG_CMD_MII
890  #define CONFIG_CMD_DATE
891  #define CONFIG_CMD_PCI
892 +#define CONFIG_CMD_NAND
893  
894  #if defined(CFG_RAMBOOT)
895      #undef CONFIG_CMD_ENV