Root/package/uboot-xburst/files/drivers/mtd/nand/jz4740_nand.c

1/*
2 * Platform independend driver for JZ4740.
3 *
4 * Copyright (c) 2007 Ingenic Semiconductor Inc.
5 * Author: <jlwei@ingenic.cn>
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#include <common.h>
13
14#if defined(CONFIG_CMD_NAND)
15#include <nand.h>
16#include <asm/io.h>
17#include <asm/jz4740.h>
18
19#define __nand_ecc_enable() (REG_EMC_NFECR = EMC_NFECR_ECCE | EMC_NFECR_ERST )
20#define __nand_ecc_disable() (REG_EMC_NFECR &= ~EMC_NFECR_ECCE)
21
22#define JZ_NAND_DATA_ADDR ((void __iomem *)0xB8000000)
23#define JZ_NAND_CMD_ADDR (JZ_NAND_DATA_ADDR + 0x8000)
24#define JZ_NAND_ADDR_ADDR (JZ_NAND_DATA_ADDR + 0x10000)
25
26#define BIT(x) (1 << (x))
27#define JZ_NAND_ECC_CTRL_ENCODING BIT(3)
28#define JZ_NAND_ECC_CTRL_RS BIT(2)
29#define JZ_NAND_ECC_CTRL_RESET BIT(1)
30#define JZ_NAND_ECC_CTRL_ENABLE BIT(0)
31
32static struct nand_ecclayout qi_lb60_ecclayout_2gb = {
33    .eccbytes = 72,
34    .eccpos = {
35        12, 13, 14, 15, 16, 17, 18, 19,
36        20, 21, 22, 23, 24, 25, 26, 27,
37        28, 29, 30, 31, 32, 33, 34, 35,
38        36, 37, 38, 39, 40, 41, 42, 43,
39        44, 45, 46, 47, 48, 49, 50, 51,
40        52, 53, 54, 55, 56, 57, 58, 59,
41        60, 61, 62, 63, 64, 65, 66, 67,
42        68, 69, 70, 71, 72, 73, 74, 75,
43        76, 77, 78, 79, 80, 81, 82, 83},
44    .oobfree = {
45         {.offset = 2,
46         .length = 10},
47        {.offset = 84,
48         .length = 44}}
49};
50
51static int is_reading;
52
53static void jz_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
54{
55    struct nand_chip *this = mtd->priv;
56
57    if (ctrl & NAND_CTRL_CHANGE) {
58        if (ctrl & NAND_ALE)
59            this->IO_ADDR_W = JZ_NAND_ADDR_ADDR;
60        else if (ctrl & NAND_CLE)
61            this->IO_ADDR_W = JZ_NAND_CMD_ADDR;
62        else
63            this->IO_ADDR_W = JZ_NAND_DATA_ADDR;
64
65        if (ctrl & NAND_NCE)
66            REG_EMC_NFCSR |= EMC_NFCSR_NFCE1;
67        else
68            REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE1;
69    }
70
71    if (cmd != NAND_CMD_NONE)
72        writeb(cmd, this->IO_ADDR_W);
73}
74
75static int jz_nand_device_ready(struct mtd_info *mtd)
76{
77    udelay(20);
78    return (REG_GPIO_PXPIN(2) & 0x40000000) ? 1 : 0;
79}
80
81void board_nand_select_device(struct nand_chip *nand, int chip)
82{
83    /*
84     * Don't use "chip" to address the NAND device,
85     * generate the cs from the address where it is encoded.
86     */
87}
88
89static int jz_nand_rs_calculate_ecc(struct mtd_info* mtd, const u_char* dat,
90                u_char* ecc_code)
91{
92    uint32_t reg, status;
93    int i;
94    volatile u8 *paraddr = (volatile u8 *)EMC_NFPAR0;
95
96    if(is_reading)
97        return 0;
98
99    do {
100        status = REG_EMC_NFINTS;
101    } while(!(status & EMC_NFINTS_ENCF));
102
103    __nand_ecc_disable();
104
105    for(i = 0; i < 9; i++)
106        ecc_code[i] = *(paraddr + i);
107
108    return 0;
109}
110
111static void jz_nand_hwctl(struct mtd_info* mtd, int mode)
112{
113    uint32_t reg;
114    REG_EMC_NFINTS = 0;
115    reg = REG_EMC_NFECR;
116    reg |= JZ_NAND_ECC_CTRL_RESET;
117    reg |= JZ_NAND_ECC_CTRL_ENABLE;
118    reg |= JZ_NAND_ECC_CTRL_RS;
119
120    switch(mode) {
121    case NAND_ECC_READ:
122        reg &= ~JZ_NAND_ECC_CTRL_ENCODING;
123        is_reading = 1;
124        break;
125    case NAND_ECC_WRITE:
126        reg |= JZ_NAND_ECC_CTRL_ENCODING;
127        is_reading = 0;
128        break;
129    default:
130        break;
131    }
132
133    REG_EMC_NFECR = reg;
134}
135
136/* Correct 1~9-bit errors in 512-bytes data */
137static void jz_rs_correct(unsigned char *dat, int idx, int mask)
138{
139    int i;
140
141    idx--;
142
143    i = idx + (idx >> 3);
144    if (i >= 512)
145        return;
146
147    mask <<= (idx & 0x7);
148
149    dat[i] ^= mask & 0xff;
150    if (i < 511)
151        dat[i+1] ^= (mask >> 8) & 0xff;
152}
153
154static int jz_nand_rs_correct_data(struct mtd_info *mtd, u_char *dat,
155                   u_char *read_ecc, u_char *calc_ecc)
156{
157    int k;
158    uint32_t reg, status;
159    volatile u8 *paraddr = (volatile u8 *)EMC_NFPAR0;
160
161    /* Set PAR values */
162    static uint8_t all_ff_ecc[] = {0xcd, 0x9d, 0x90, 0x58, 0xf4, 0x8b, 0xff, 0xb7, 0x6f};
163    if (read_ecc[0] == 0xff &&
164        read_ecc[1] == 0xff &&
165        read_ecc[2] == 0xff &&
166        read_ecc[3] == 0xff &&
167        read_ecc[4] == 0xff &&
168        read_ecc[5] == 0xff &&
169        read_ecc[6] == 0xff &&
170        read_ecc[7] == 0xff &&
171        read_ecc[8] == 0xff) {
172        for (k = 0; k < 9; k++)
173            *(paraddr + k) = all_ff_ecc[k];
174    } else {
175
176        for (k = 0; k < 9; k++)
177            *(paraddr + k) = read_ecc[k];
178    }
179    /* Set PRDY */
180    REG_EMC_NFECR |= EMC_NFECR_PRDY;
181
182    /* Wait for completion */
183    do {
184        status = REG_EMC_NFINTS;
185    } while (!(status & EMC_NFINTS_DECF));
186
187    __nand_ecc_disable();
188
189    /* Check decoding */
190    if (status & EMC_NFINTS_ERR) {
191        if (status & EMC_NFINTS_UNCOR) {
192            printk("uncorrectable ecc\n");
193            while(1);
194            return -1;
195        }
196
197        uint32_t errcnt = (status & EMC_NFINTS_ERRCNT_MASK) >> EMC_NFINTS_ERRCNT_BIT;
198        switch (errcnt) {
199        case 4:
200            jz_rs_correct(dat,
201                      (REG_EMC_NFERR3 & EMC_NFERR_INDEX_MASK) >> EMC_NFERR_INDEX_BIT,
202                      (REG_EMC_NFERR3 & EMC_NFERR_MASK_MASK) >> EMC_NFERR_MASK_BIT);
203        case 3:
204            jz_rs_correct(dat,
205                      (REG_EMC_NFERR2 & EMC_NFERR_INDEX_MASK) >> EMC_NFERR_INDEX_BIT,
206                      (REG_EMC_NFERR2 & EMC_NFERR_MASK_MASK) >> EMC_NFERR_MASK_BIT);
207        case 2:
208            jz_rs_correct(dat,
209                      (REG_EMC_NFERR1 & EMC_NFERR_INDEX_MASK) >> EMC_NFERR_INDEX_BIT,
210                      (REG_EMC_NFERR1 & EMC_NFERR_MASK_MASK) >> EMC_NFERR_MASK_BIT);
211        case 1:
212            jz_rs_correct(dat,
213                      (REG_EMC_NFERR0 & EMC_NFERR_INDEX_MASK) >> EMC_NFERR_INDEX_BIT,
214                      (REG_EMC_NFERR0 & EMC_NFERR_MASK_MASK) >> EMC_NFERR_MASK_BIT);
215            return errcnt;
216        default:
217            break;
218        }
219    }
220
221    return 0;
222}
223
224/*
225 * Main initialization routine
226 */
227int board_nand_init(struct nand_chip *nand)
228{
229    /* EMC setup, Set NFE bit */
230    REG_EMC_NFCSR |= EMC_NFCSR_NFE1;
231    REG_EMC_SMCR1 = 0x094c4400;
232    /* REG_EMC_SMCR3 = 0x04444400; */
233
234    nand->IO_ADDR_R = JZ_NAND_DATA_ADDR;
235    nand->IO_ADDR_W = JZ_NAND_DATA_ADDR;
236    nand->cmd_ctrl = jz_nand_cmd_ctrl;
237    nand->dev_ready = jz_nand_device_ready;
238
239    nand->ecc.hwctl = jz_nand_hwctl;
240    nand->ecc.correct = jz_nand_rs_correct_data;
241    nand->ecc.calculate = jz_nand_rs_calculate_ecc;
242    nand->ecc.mode = NAND_ECC_HW_OOB_FIRST;
243    nand->ecc.size = CONFIG_SYS_NAND_ECCSIZE;
244    nand->ecc.bytes = CONFIG_SYS_NAND_ECCBYTES;
245    nand->ecc.layout = &qi_lb60_ecclayout_2gb;
246    nand->chip_delay = 50;
247
248    return 0;
249}
250#endif /* (CONFIG_CMD_NAND) */
251

Archive Download this file



interactive