source: SVN/rincon/u-boot/board/delta/nand.c @ 55

Last change on this file since 55 was 55, checked in by Tim Harvey, 2 years ago

rincon: added latest u-boot source

restored form server backup

Signed-off-by: Tim Harvey <tharvey@…>

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