tizen 2.4 release
[kernel/u-boot-tm1.git] / drivers / mtd / nand / sprd_nand.c
1 #include <config.h>
2 #include <asm/arch/bits.h>
3 #include <asm/arch/chip_drv_config_extern.h>
4 #include <asm/arch/regs_nfc.h>
5 #include <asm/arch/regs_cpc.h>
6 #include <nand.h>
7 #include <asm/io.h>
8 #include <linux/mtd/nand.h>
9
10 #ifdef CONFIG_NAND_SPL
11 #define printf(arg...) do{}while(0)
12 #endif
13
14
15 #define NF_PARA_20M             0x7ac05      //trwl = 0  trwh = 0
16 #define NF_PARA_40M             0x7ac15      //trwl = 1  trwh = 0
17 #define NF_PARA_53M             0x7ad26      //trwl = 2  trwh = 1
18 #define NF_PARA_80M             0x7ad37      //trwl = 3  trwh = 1
19 #define NF_PARA_DEFAULT         0x7ad77      //trwl = 7  trwh = 1
20 #define NF_TIMEOUT_VAL          0x1000000
21
22 #define PAGE_SIZE_S         512
23 #define SPARE_SIZE_S        16
24 #define PAGE_SIZE_L         2048
25 #define SPARE_SIZE_L        64
26
27 #define REG_CPC_NFWPN                           (*((volatile unsigned int *)(CPC_NFWPN_REG)))
28 #define REG_CPC_NFRB                            (*((volatile unsigned int *)(CPC_NFRB_REG)))
29 #define REG_CPC_NFCLE                           (*((volatile unsigned int *)(CPC_NFCLE_REG)))
30 #define REG_CPC_NFALE                           (*((volatile unsigned int *)(CPC_NFALE_REG)))
31 #define REG_CPC_NFCEN                           (*((volatile unsigned int *)(CPC_NFCEN_REG)))
32 #define REG_CPC_NFWEN                           (*((volatile unsigned int *)(CPC_NFWEN_REG)))
33 #define REG_CPC_NFREN                           (*((volatile unsigned int *)(CPC_NFREN_REG)))
34 #define REG_CPC_NFD0                            (*((volatile unsigned int *)(CPC_NFD0_REG)))
35 #define REG_CPC_NFD1                            (*((volatile unsigned int *)(CPC_NFD1_REG)))
36 #define REG_CPC_NFD2                            (*((volatile unsigned int *)(CPC_NFD2_REG)))
37 #define REG_CPC_NFD3                            (*((volatile unsigned int *)(CPC_NFD3_REG)))
38 #define REG_CPC_NFD4                            (*((volatile unsigned int *)(CPC_NFD4_REG)))
39 #define REG_CPC_NFD5                            (*((volatile unsigned int *)(CPC_NFD5_REG)))
40 #define REG_CPC_NFD6                            (*((volatile unsigned int *)(CPC_NFD6_REG)))
41 #define REG_CPC_NFD7                            (*((volatile unsigned int *)(CPC_NFD7_REG)))
42 #define REG_CPC_NFD8                            (*((volatile unsigned int *)(CPC_NFD8_REG)))
43
44 #define REG_CPC_NFD9                            (*((volatile unsigned int *)(CPC_NFD9_REG)))
45 #define REG_CPC_NFD10                           (*((volatile unsigned int *)(CPC_NFD10_REG)))
46 #define REG_CPC_NFD11                           (*((volatile unsigned int *)(CPC_NFD11_REG)))
47 #define REG_CPC_NFD12                           (*((volatile unsigned int *)(CPC_NFD12_REG)))
48 #define REG_CPC_NFD13                           (*((volatile unsigned int *)(CPC_NFD13_REG)))
49 #define REG_CPC_NFD14                           (*((volatile unsigned int *)(CPC_NFD14_REG)))
50 #define REG_CPC_NFD15                           (*((volatile unsigned int *)(CPC_NFD15_REG)))
51
52
53 #define REG_AHB_CTL0                            (*((volatile unsigned int *)(AHB_CTL0)))
54 #define REG_AHB_SOFT_RST                                (*((volatile unsigned int *)(AHB_SOFT_RST)))
55
56 #define REG_GR_NFC_MEM_DLY                      (*((volatile unsigned int *)(GR_NFC_MEM_DLY)))
57
58 #ifdef CONFIG_SC8800G
59 #define set_sc8800g_gpio_as_nand_8bit()                 \
60         do {                                                    \
61                         REG_CPC_NFWPN |= BIT_8 | BIT_9;                         \
62                         REG_CPC_NFWPN &= ~(BIT_4 | BIT_5);              \
63                         REG_CPC_NFRB |= BIT_8 | BIT_9;                  \
64                         REG_CPC_NFRB &= ~(BIT_4 | BIT_5);               \
65                         REG_CPC_NFCLE |= BIT_8 | BIT_9;                 \
66                         REG_CPC_NFCLE &= ~(BIT_4 | BIT_5);              \
67                         REG_CPC_NFALE |= BIT_8 | BIT_9;                 \
68                         REG_CPC_NFALE &= ~(BIT_4 | BIT_5);              \
69                         REG_CPC_NFCEN |= BIT_8 | BIT_9;                 \
70                         REG_CPC_NFCEN &= ~(BIT_4 | BIT_5);              \
71                         REG_CPC_NFWEN |= BIT_8 | BIT_9;                 \
72                         REG_CPC_NFWEN &= ~(BIT_4 | BIT_5);              \
73                         REG_CPC_NFREN |= BIT_8 | BIT_9;                 \
74                         REG_CPC_NFREN &= ~(BIT_4 | BIT_5);              \
75                         REG_CPC_NFD0 |= BIT_8 | BIT_9;                 \
76                         REG_CPC_NFD0 &= ~(BIT_4 | BIT_5);              \
77                         REG_CPC_NFD1 |= BIT_8 | BIT_9;                 \
78                         REG_CPC_NFD1 &= ~(BIT_4 | BIT_5);              \
79                         REG_CPC_NFD2 |= BIT_8 | BIT_9;                 \
80                         REG_CPC_NFD2 &= ~(BIT_4 | BIT_5);              \
81                         REG_CPC_NFD3 |= BIT_8 | BIT_9;                 \
82                         REG_CPC_NFD3 &= ~(BIT_4 | BIT_5);              \
83                         REG_CPC_NFD4 |= BIT_8 | BIT_9;                 \
84                         REG_CPC_NFD4 &= ~(BIT_4 | BIT_5);              \
85                         REG_CPC_NFD5 |= BIT_8 | BIT_9;                 \
86                         REG_CPC_NFD5 &= ~(BIT_4 | BIT_5);              \
87                         REG_CPC_NFD6 |= BIT_8 | BIT_9;                 \
88                         REG_CPC_NFD6 &= ~(BIT_4 | BIT_5);              \
89                         REG_CPC_NFD7 |= BIT_8 | BIT_9;                 \
90                         REG_CPC_NFD7 &= ~(BIT_4 | BIT_5);              \
91         } while (0)
92
93 #define set_sc8800g_gpio_as_nand_16bit()                \
94         do {                                                    \
95                                 REG_CPC_NFD8 |= BIT_8 | BIT_9;                                  \
96                         REG_CPC_NFD8 &= ~(BIT_4 | BIT_5);                               \
97                                 REG_CPC_NFD9 |= BIT_8 | BIT_9;                          \
98                         REG_CPC_NFD9 &= ~(BIT_4 | BIT_5);               \
99                                 REG_CPC_NFD10 |= BIT_8 | BIT_9;                         \
100                         REG_CPC_NFD10 &= ~(BIT_4 | BIT_5);              \
101                                 REG_CPC_NFD11 |= BIT_8 | BIT_9;                         \
102                         REG_CPC_NFD11 &= ~(BIT_4 | BIT_5);              \
103                                 REG_CPC_NFD12 |= BIT_8 | BIT_9;                         \
104                         REG_CPC_NFD12 &= ~(BIT_4 | BIT_5);              \
105                                 REG_CPC_NFD13 |= BIT_8 | BIT_9;                         \
106                         REG_CPC_NFD13 &= ~(BIT_4 | BIT_5);              \
107                                 REG_CPC_NFD14 |= BIT_8 | BIT_9;                         \
108                         REG_CPC_NFD14 &= ~(BIT_4 | BIT_5);              \
109                                 REG_CPC_NFD15 |= BIT_8 | BIT_9;                         \
110                         REG_CPC_NFD15 &= ~(BIT_4 | BIT_5);              \
111         } while (0)
112 #else
113 #define set_gpio_as_nand()                              \
114 do {                                                    \
115         REG_CPC_NFWPN = BIT_0 | BIT_4 | BIT_5;          \
116         REG_CPC_NFWPN &= ~(BIT_6 | BIT_7);              \
117         REG_CPC_NFRB = BIT_0 | BIT_3 | BIT_4 | BIT_5;   \
118         REG_CPC_NFRB &= ~(BIT_6 | BIT_7);               \
119         REG_CPC_NFCLE |= BIT_4 | BIT_5;                 \
120         REG_CPC_NFCLE &= ~(BIT_6 | BIT_7);              \
121         REG_CPC_NFALE |= BIT_4 | BIT_5;                 \
122         REG_CPC_NFALE &= ~(BIT_6 | BIT_7);              \
123         REG_CPC_NFCEN |= BIT_4 | BIT_5;                 \
124         REG_CPC_NFCEN &= ~(BIT_6 | BIT_7);              \
125         REG_CPC_NFWEN |= BIT_4 | BIT_5;                 \
126         REG_CPC_NFWEN &= ~(BIT_6 | BIT_7);              \
127         REG_CPC_NFREN |= BIT_4 | BIT_5;                 \
128         REG_CPC_NFREN &= ~(BIT_6 | BIT_7);              \
129         REG_CPC_NFD0 |= BIT_4 | BIT_5;                 \
130         REG_CPC_NFD0 &= ~(BIT_6 | BIT_7);              \
131         REG_CPC_NFD1 |= BIT_4 | BIT_5;                 \
132         REG_CPC_NFD1 &= ~(BIT_6 | BIT_7);              \
133         REG_CPC_NFD2 |= BIT_4 | BIT_5;                 \
134         REG_CPC_NFD2 &= ~(BIT_6 | BIT_7);              \
135         REG_CPC_NFD3 |= BIT_4 | BIT_5;                 \
136         REG_CPC_NFD3 &= ~(BIT_6 | BIT_7);              \
137         REG_CPC_NFD4 |= BIT_4 | BIT_5;                 \
138         REG_CPC_NFD4 &= ~(BIT_6 | BIT_7);              \
139         REG_CPC_NFD5 |= BIT_4 | BIT_5;                 \
140         REG_CPC_NFD5 &= ~(BIT_6 | BIT_7);              \
141         REG_CPC_NFD6 |= BIT_4 | BIT_5;                 \
142         REG_CPC_NFD6 &= ~(BIT_6 | BIT_7);              \
143         REG_CPC_NFD7 |= BIT_4 | BIT_5;                 \
144         REG_CPC_NFD7 &= ~(BIT_6 | BIT_7);              \
145         REG_CPC_NFD8 |= BIT_4 | BIT_5;                 \
146         REG_CPC_NFD8 &= ~(BIT_6 | BIT_7);              \
147         REG_CPC_NFD9 |= BIT_4 | BIT_5 | BIT_6;         \
148         REG_CPC_NFD9 &= ~(BIT_7);                      \
149         REG_CPC_NFD10 |= BIT_4 | BIT_5 | BIT_6;        \
150         REG_CPC_NFD10 &= ~(BIT_7);                     \
151         REG_CPC_NFD11 |= BIT_4 | BIT_5 | BIT_6;        \
152         REG_CPC_NFD11 &= ~(BIT_7);                     \
153         REG_CPC_NFD12 |= BIT_4 | BIT_5 | BIT_6;        \
154         REG_CPC_NFD12 &= ~(BIT_7);                     \
155         REG_CPC_NFD13 |= BIT_4 | BIT_5 | BIT_6;        \
156         REG_CPC_NFD13 &= ~(BIT_7);                     \
157         REG_CPC_NFD14 |= BIT_4 | BIT_5 | BIT_6;        \
158         REG_CPC_NFD14 &= ~(BIT_7);                     \
159         REG_CPC_NFD15 |= BIT_4 | BIT_5 | BIT_6;        \
160         REG_CPC_NFD15 &= ~(BIT_7);                     \
161 } while (0)
162 #endif
163
164 struct sprd_platform_nand {
165         /* timing information for nand flash controller */
166         int     acs;
167         int     ach;
168         int     rwl;
169         int     rwh;
170         int     rr;
171         int     acr;
172         int     ceh;
173 };
174
175 struct sprd_nand_address {
176         int column;
177         int row;
178         int colflag;
179         int rowflag;
180 };
181
182 struct sprd_nand_info {
183         struct sprd_platform_nand       *platform;
184         struct clk      *clk;
185 };
186
187 typedef enum {
188         NO_OP,
189         WRITE_OP,
190         READ_OP,
191 } sprd_nand_wr_mode_t;
192
193 typedef enum {
194         NO_AREA,
195         DATA_AREA,
196         OOB_AREA,
197         DATA_OOB_AREA,
198 } sprd_nand_area_mode_t;
199
200 static struct mtd_info *sprd_mtd = NULL;
201 static unsigned long g_cmdsetting = 0;
202 static sprd_nand_wr_mode_t sprd_wr_mode = NO_OP;
203 static sprd_nand_area_mode_t sprd_area_mode = NO_AREA;
204 static unsigned long nand_flash_id = 0;
205 static struct sprd_nand_address sprd_colrow_addr = {0, 0, 0, 0};
206 static __attribute__((aligned(4))) unsigned char io_wr_port[NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZE];
207 static nand_ecc_modes_t sprd_ecc_mode = NAND_ECC_NONE;
208 #ifdef CONFIG_SC8800G
209 static unsigned long g_buswidth = 0; /* 0: X8 bus width 1: X16 bus width */
210 static unsigned long g_addr_cycle = 4; /* advance 0 : can be set 3 or 4; advance 1: can be set 4 or 5 */
211 #else
212 static unsigned long g_buswidth = 1; /* 0: X8 bus width 1: X16 bus width */
213 static unsigned long g_addr_cycle = 5; /* advance 0 : can be set 3 or 4; advance 1: can be set 4 or 5 */
214 #endif
215
216 #define NF_RESET                0xFF
217 #define NF_READ_STATUS          0x70
218 #define NF_READ_ID              0x90
219
220 static int nfc_wait_command_finish(void)
221 {
222         unsigned long nfc_cmd = REG_NFC_CMD;
223         unsigned long counter = 0;
224         
225         while ((nfc_cmd & (0x1 << 31)) && (counter < NF_TIMEOUT_VAL)) {
226                 nfc_cmd = REG_NFC_CMD;
227                 counter++;
228         }
229         
230         if (NF_TIMEOUT_VAL == counter) {
231                 return 2;
232         }
233         
234         return 0;
235 }
236
237 static void nfc_reset(void)
238 {
239         unsigned long cmd = NF_RESET | (0x1 << 31);
240
241         REG_NFC_CMD = cmd;
242         nfc_wait_command_finish();
243 }
244
245 static unsigned long nfc_read_status(void)
246 {
247         unsigned long status = 0;
248         unsigned long cmd = NF_READ_STATUS | (0x1 << 31);
249
250         REG_NFC_CMD = cmd;
251         nfc_wait_command_finish();
252
253         status = REG_NFC_IDSTATUS;
254         return status;  
255 }
256
257 static unsigned long nfc_read_id(void)
258 {
259         unsigned long id = 0;
260         unsigned long cmd =  NF_READ_ID | (0x1 << 31);
261
262         REG_NFC_CMD = cmd;
263         nfc_wait_command_finish();
264
265         id = REG_NFC_IDSTATUS;
266 #ifdef NAND_DEBUG
267         printk("\n%s  %s  %d  id = 0x%08x\n", __FILE__, __FUNCTION__, __LINE__, id);
268 #endif
269         return id;
270 }
271
272 /* 
273 *  1 : I/O 16bit
274 *  0 : I/O 8bit
275 */
276 static unsigned long nand_bit_width(unsigned long id)
277 {
278         unsigned long bw = (id & 0x40000000) >> 30;
279         return bw;
280 }
281 static void set_nfc_param(unsigned long ahb_clk)
282 {
283         unsigned long flags;
284
285         nfc_wait_command_finish();
286 //      local_irq_save(flags);
287
288         switch (ahb_clk) {
289         case 20:
290                 REG_NFC_PARA = NF_PARA_20M;
291         break;
292
293         case 40:
294                 REG_NFC_PARA = NF_PARA_40M;
295         break;
296
297         case 53:
298                 REG_NFC_PARA = NF_PARA_53M;
299         break;
300
301         case 80:
302                 REG_NFC_PARA = NF_PARA_80M;
303         break;
304
305         default:
306                 REG_NFC_PARA = NF_PARA_DEFAULT;    
307         }
308
309 //      local_irq_restore(flags);       
310 }
311
312
313 static void nand_copy(unsigned char *src, unsigned char *dst, unsigned long len)
314 {
315         unsigned long i;
316         unsigned long *pDst_32, *pSrc_32;
317         unsigned short *pDst_16, *pSrc_16;
318         unsigned long flag = 0;
319         
320         flag = (unsigned long *)dst;
321         flag = flag & 0x3;
322
323         switch (flag) {
324                 case 0://word alignment
325 #ifdef NAND_DEBUG
326                         printf("%s  %d\n", __FUNCTION__, __LINE__);
327 #endif
328                         pDst_32 = (unsigned long *)dst;
329                         pSrc_32 = (unsigned long *)src;
330                         for (i = 0; i < (len / 4); i++) {
331                                 *pDst_32 = *pSrc_32;
332                                 pDst_32++;
333                                 pSrc_32++;
334                         }
335                 break;
336                 case 2://half word alignment
337 #ifdef NAND_DEBUG
338                         printf("%s  %d\n", __FUNCTION__, __LINE__);
339 #endif
340                         pDst_16 = (unsigned short *)dst;
341                         pSrc_16 = (unsigned short *)src;
342                         for (i = 0; i < (len / 2); i++) {
343                                 *pDst_16 = *pSrc_16;
344                                 pDst_16++;
345                                 pSrc_16++;
346                         }
347                 break;
348                 default://byte alignment
349 #ifdef NAND_DEBUG
350                         printf("%s  %d\n", __FUNCTION__, __LINE__);
351 #endif
352                         for (i = 0; i < len; i++) {
353                                 *dst = *src;
354                                 dst++;
355                                 src++;
356                         }
357                 break;
358         }//switch       
359 }
360
361 #ifdef CONFIG_NAND_SPL
362 static u_char nand_read_byte(struct mtd_info *mtd)
363 {
364         struct nand_chip *this = mtd->priv;
365         return readb(this->IO_ADDR_R);
366 }
367 static u_char nand_read_byte16(struct mtd_info *mtd)
368 {
369         struct nand_chip *this = mtd->priv;
370 #ifdef CONFIG_MTD_NAND_SPRD
371         return (uint8_t)readl(this->IO_ADDR_R);
372 #else
373         return readb(this->IO_ADDR_R);
374 #endif
375 }
376
377 static void nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
378 {
379         int i;
380         struct nand_chip *this = mtd->priv;
381
382 #ifdef CONFIG_MTD_NAND_SPRD
383         nand_copy(buf,this->IO_ADDR_W, len);
384 #else
385         for (i = 0; i < len; i++)
386                 writeb(buf[i], this->IO_ADDR_W);
387 #endif
388 }
389
390 static void nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
391 {
392         int i;
393         struct nand_chip *this = mtd->priv;
394 #ifdef CONFIG_MTD_NAND_SPRD
395         nand_copy(this->IO_ADDR_R, buf, len);
396 #else
397         for (i = 0; i < len; i++)
398                 buf[i] = readb(this->IO_ADDR_R);
399 #endif
400 }
401 #endif
402
403 static int sprd_nand_inithw(struct sprd_nand_info *info, struct platform_device *pdev)
404 {
405 #if 0
406         struct sprd_platform_nand *plat = to_nand_plat(pdev);
407         unsigned long para = (plat->acs << 0) | 
408                                 (plat->ach << 2) |
409                                 (plat->rwl << 4) |
410                                 (plat->rwh << 8) |
411                                 (plat->rr << 10) |
412                                 (plat->acr << 13) |
413                                 (plat->ceh << 16);
414
415         writel(para, NFCPARAMADDR);
416 #endif
417         
418         return 0;
419 }
420
421
422 #ifndef CONFIG_SKIP_LOWLEVEL_INIT
423 void * memset(void * s, int c, size_t len)
424 {
425         unsigned long i = 0;
426         char *xs = (char *)s;
427         if(len < 1)
428                 return;
429         for(i = 0; i<len; i++)
430         {
431                 *(xs+i) = c;
432         }
433         return s;
434 }
435 #endif
436 static void sprd_nand_hwcontrol(struct mtd_info *mtd, int cmd,
437                                    unsigned int ctrl)
438 {
439         unsigned long phyblk, pageinblk, pageperblk;
440         unsigned long i;
441 //      unsigned long addr_cycle = 5; /* advance 0 : can be set 3 or 4; advance 1: can be set 4 or 5 */
442         unsigned long advance = 1; /* can be set 0 or 1 */
443         unsigned long pagetype; /* 0: small page; 1: large page*/
444 //      unsigned long buswidth = 1; /* 0: X8 bus width 1: X16 bus width */
445         unsigned long chipsel = 0;
446         unsigned long buswidth = g_buswidth;
447         unsigned long addr_cycle = g_addr_cycle;
448         //static unsigned long readaaa = 0;
449         struct nand_chip *this = (struct nand_chip *)(mtd->priv);
450         if (cmd == NAND_CMD_NONE)
451                 return;
452
453         if (512 == mtd->writesize)
454                 pagetype = 0;
455         else
456                 pagetype = 1;
457         if(addr_cycle == 3)
458                 addr_cycle = 0;
459         else if((addr_cycle == 4) &&(advance == 1))
460                 addr_cycle = 0;
461         else
462                 addr_cycle = 3;
463
464         if (ctrl & NAND_CLE) {
465                 switch (cmd) {
466                 case NAND_CMD_RESET:
467                         REG_NFC_CMD = cmd | (0x1 << 31);
468                         nfc_wait_command_finish();
469                 break;
470                 case NAND_CMD_STATUS:
471                         REG_NFC_CMD = cmd | (0x1 << 31);
472                         nfc_wait_command_finish();
473                         
474                         memset((unsigned char *)(this->IO_ADDR_R), 0xff, NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZE);
475                         nand_copy((unsigned char *)NFC_IDSTATUS, this->IO_ADDR_R, 4);
476 #if 0 
477                         /* transfer to big endian */
478                         i = io_wr_port[3]; io_wr_port[3] = io_wr_port[0]; io_wr_port[0] = i;
479                         i = io_wr_port[2]; io_wr_port[2] = io_wr_port[1]; io_wr_port[1] = i;
480 #endif
481 #ifdef NAND_DEBUG
482                         for (i = 0; i < 4; i++)
483                                         printf("io_wr_port[%d] = 0x%02x\n", i, io_wr_port[i]);
484 #endif
485                 break;
486                 case NAND_CMD_READID:
487                         REG_NFC_CMD = cmd | (0x1 << 31);
488                         nfc_wait_command_finish();
489                         nand_flash_id = REG_NFC_IDSTATUS;
490 #ifdef NAND_DEBUG
491                         printf("nand id: %x\n", nand_flash_id);
492 #endif
493                 break;
494                 case NAND_CMD_ERASE1:
495                         sprd_colrow_addr.column = 0;
496                         sprd_colrow_addr.row = 0;
497                         sprd_colrow_addr.colflag = 0;
498                         sprd_colrow_addr.rowflag = 0;
499                 break;
500                 case NAND_CMD_ERASE2:
501                         if ((0 == sprd_colrow_addr.colflag) && (0 == sprd_colrow_addr.rowflag)) {
502                                 printf("erase address error!\n");
503                                 return;
504                         } else {
505                                 if (1 == sprd_colrow_addr.colflag) {
506                                         sprd_colrow_addr.row = sprd_colrow_addr.column;
507                                         sprd_colrow_addr.column = 0;
508                                         sprd_colrow_addr.rowflag = 1;
509                                         sprd_colrow_addr.colflag = 0;   
510                                 }       
511                         }
512                         
513                         if ((0 == sprd_colrow_addr.colflag) && (1 == sprd_colrow_addr.rowflag)) {
514                                 g_cmdsetting = (chipsel << 26) | (addr_cycle << 24) | (advance << 23) | (buswidth << 19) | (pagetype << 18) | (0 << 16) | (0x1 << 31);
515                                         if (buswidth == 1)
516                                                 REG_NFC_STR0 = sprd_colrow_addr.row * mtd->writesize;
517                                         else
518                                                 REG_NFC_STR0 = sprd_colrow_addr.row * mtd->writesize * 2;
519
520                                 REG_NFC_CMD = g_cmdsetting | NAND_CMD_ERASE1;
521                                 nfc_wait_command_finish();
522                         }
523                 break;
524                 case NAND_CMD_READ0:
525                         sprd_colrow_addr.column = 0;
526                         sprd_colrow_addr.row = 0;
527                         sprd_colrow_addr.colflag = 0;
528                         sprd_colrow_addr.rowflag = 0;
529                         sprd_wr_mode = READ_OP;
530                         sprd_area_mode = NO_AREA;
531 memset(io_wr_port, 0xff, NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZE);
532                 break;
533                 case NAND_CMD_READSTART:
534                                 if (buswidth == 1) {
535                         if (sprd_colrow_addr.column == (mtd->writesize >> 1)) {
536                                 g_cmdsetting = (chipsel << 26) | (addr_cycle << 24) | (advance << 23) | (buswidth << 19) | (pagetype << 18) | (0 << 16) | (0x1 << 31);
537                                 REG_NFC_CMD = g_cmdsetting | NAND_CMD_READ0;
538                                 nfc_wait_command_finish();
539                                 nand_copy((unsigned long *)NFC_SBUF, (unsigned long *)io_wr_port, mtd->oobsize);
540
541                         } else if (sprd_colrow_addr.column == 0) {
542 if (sprd_area_mode == DATA_AREA)
543                                                 sprd_area_mode = DATA_OOB_AREA;
544
545                                         if (sprd_area_mode == DATA_OOB_AREA) {
546                                                 REG_NFC_END0 = 0xffffffff;
547                                                 g_cmdsetting = (chipsel << 26) | (addr_cycle << 24) | (advance << 23) | (1 << 21) | (buswidth << 19) | (pagetype << 18) | (0 << 16) | (0x1 << 31);
548                                                 REG_NFC_CMD = g_cmdsetting | NAND_CMD_READ0;
549                                                 nfc_wait_command_finish();
550                                                 nand_copy((unsigned char *)NFC_MBUF, io_wr_port, mtd->writesize);
551                                         } else if (sprd_colrow_addr.column == DATA_AREA) {
552                                                 g_cmdsetting = (chipsel << 26) | (addr_cycle << 24) | (advance << 23) | (buswidth << 19) | (pagetype << 18) | (0 << 16) | (0x1 << 31);
553                                                 REG_NFC_CMD = g_cmdsetting | NAND_CMD_READ0;
554                                                 nfc_wait_command_finish();
555                         
556                                                 nand_copy((unsigned char *)NFC_MBUF, io_wr_port, mtd->writesize);
557                                 }
558                         } else
559                                 printf("Operation !!! area.  %s  %s  %d\n", __FILE__, __FUNCTION__, __LINE__);
560                                 } else {  //if (buswidth == 1)
561                                         if (sprd_colrow_addr.column == mtd->writesize) {
562                                                 g_cmdsetting = (chipsel << 26) | (addr_cycle << 24) | (advance << 23) | (buswidth << 19) | \
563                                                                 (pagetype << 18) | (0 << 16) | (0x1 << 31);
564                                                 REG_NFC_CMD = g_cmdsetting | NAND_CMD_READ0;
565                                                 nfc_wait_command_finish();
566                                                 nand_copy((unsigned char *)NFC_SBUF, io_wr_port, mtd->oobsize);
567
568                                                 /*for (i = 0; i < mtd->oobsize; i++)
569                                                         printk(" Rport[%d]=%d ", i, io_wr_port[i]);*/
570                                         } else if (sprd_colrow_addr.column == 0) {
571                                                 if (sprd_area_mode == DATA_AREA)
572                                                         sprd_area_mode = DATA_OOB_AREA;
573
574                                                 if (sprd_area_mode == DATA_OOB_AREA) {
575                                                         /* read data and spare area, modify address */
576                                                         REG_NFC_END0 = 0xffffffff;
577                                                         g_cmdsetting = (chipsel << 26) | (addr_cycle << 24) | (advance << 23) | \
578                                                                         (1 << 21) | (buswidth << 19) | (pagetype << 18) | \
579                                                                         (0 << 16) | (0x1 << 31);
580
581                                                         REG_NFC_CMD = g_cmdsetting | NAND_CMD_READ0;
582                                                         nfc_wait_command_finish();
583                                                         
584                                                         nand_copy((unsigned char *)NFC_MBUF, io_wr_port, mtd->writesize);
585                                                         //if (readaaa < 6) {                                                    
586 #ifdef NAND_DEBUG
587                                                         if(1){
588                                                                 int i;
589                                                                 static int readaaa = 0;
590                                                                 if(readaaa<6){
591                                                                         printk("\nREADPAGE\n");
592                                                                         for (i = 0; i < mtd->writesize; i++)
593                                                                                 printk(",0x%02x", io_wr_port[i]);
594                                                                         printk("\n\n");
595                                                                         readaaa++;
596                                                                 }
597                                                         }
598 #endif
599
600                                                 } else if (sprd_colrow_addr.column == DATA_AREA) {
601                                                         g_cmdsetting = (chipsel << 26) | (addr_cycle << 24) | (advance << 23) | \
602                                                                         (buswidth << 19) | (pagetype << 18) | \
603                                                                         (0 << 16) | (0x1 << 31);
604                                                         REG_NFC_CMD = g_cmdsetting | NAND_CMD_READ0;
605                                                         nfc_wait_command_finish();
606                                 
607                                                         nand_copy((unsigned char *)NFC_MBUF, io_wr_port, mtd->writesize);
608                                                         /*for (i = 0; i < mtd->writesize; i++)
609                                                                 printk(" Rport[%d]=%d ", i, io_wr_port[i]);*/
610                                                 }
611                                         } else
612                                                 printk("Operation !!! area.  %s  %s  %d\n", __FILE__, __FUNCTION__, __LINE__);
613                                 }
614
615                         sprd_wr_mode = NO_OP;
616                         sprd_area_mode = NO_AREA;
617                 break;
618                 case NAND_CMD_SEQIN:
619                         sprd_colrow_addr.column = 0;
620                         sprd_colrow_addr.row = 0;
621                         sprd_colrow_addr.colflag = 0;
622                         sprd_colrow_addr.rowflag = 0;
623                         sprd_wr_mode = WRITE_OP;
624                         sprd_area_mode = NO_AREA;
625                         memset(io_wr_port, 0xff, NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZE);
626                 break;
627                 case NAND_CMD_PAGEPROG:
628                                 if (buswidth == 1) {
629
630                         if (sprd_colrow_addr.column == (mtd->writesize >> 1)) {
631                                 g_cmdsetting = (chipsel << 26) | (addr_cycle << 24) | (advance << 23) | (buswidth << 19) | (pagetype << 18) | (0 << 16) | (0x1 << 31);
632                 nand_copy((unsigned long *)io_wr_port, (unsigned long *)NFC_SBUF, mtd->oobsize);
633                                 REG_NFC_CMD = g_cmdsetting | NAND_CMD_SEQIN;
634                                 nfc_wait_command_finish();
635                         } else if (sprd_colrow_addr.column == 0) {
636
637                                 if (sprd_area_mode == DATA_OOB_AREA) {
638                                         REG_NFC_END0 = 0xffffffff;
639                                         g_cmdsetting = (chipsel << 26) | (addr_cycle << 24) | (advance << 23) | (buswidth << 19) | (pagetype << 18) | (0 << 16) | (0x1 << 31);
640
641                         
642                                         REG_NFC_CMD = g_cmdsetting | NAND_CMD_SEQIN;
643                                         nfc_wait_command_finish();
644                                 
645                                 } else if (sprd_colrow_addr.column == DATA_AREA) {
646                                         g_cmdsetting = (chipsel << 26) | (addr_cycle << 24) | (advance << 23) | (buswidth << 19) | (pagetype << 18) | (0 << 16) | (0x1 << 31);
647                                         nand_copy(io_wr_port, (unsigned char *)NFC_MBUF, mtd->writesize);
648                                         REG_NFC_CMD = g_cmdsetting | NAND_CMD_SEQIN;
649                                         nfc_wait_command_finish();
650                                 }
651                         } else
652                                 printf("Operation !!! area.  %s  %s  %d\n", __FILE__, __FUNCTION__, __LINE__);
653                                 } else {        //if (buswidth == 1)
654                                         if (sprd_colrow_addr.column == mtd->writesize) {
655                                                 /*for (i = 0; i < mtd->oobsize; i++)
656                                                         printk(" Wport[%d]=%d ", i, io_wr_port[i]);*/
657
658                                                 g_cmdsetting = (addr_cycle << 24) | (advance << 23) | (buswidth << 19) | \
659                                                                 (pagetype << 18) | (0 << 16) | (0x1 << 31);
660                                                 nand_copy(io_wr_port, (unsigned char *)NFC_SBUF, mtd->oobsize);
661                                                 REG_NFC_CMD = g_cmdsetting | NAND_CMD_SEQIN;
662                                                 nfc_wait_command_finish();
663                                         } else if (sprd_colrow_addr.column == 0) {
664                                                 if (sprd_area_mode == DATA_OOB_AREA) {
665                                                         /* write data and spare area, modify address */
666                                                         REG_NFC_END0 = 0xffffffff;
667                                                         g_cmdsetting = (addr_cycle << 24) | (advance << 23) | (buswidth << 19) | \
668                                                                         (pagetype << 18) | (0 << 16) | (0x1 << 31);
669                                 
670                                                         REG_NFC_CMD = g_cmdsetting | NAND_CMD_SEQIN;
671                                                         nfc_wait_command_finish();
672                                         
673                                                 } else if (sprd_colrow_addr.column == DATA_AREA) {
674                                                         g_cmdsetting = (addr_cycle << 24) | (advance << 23) | (buswidth << 19) | \
675                                                                         (pagetype << 18) | (0 << 16) | (0x1 << 31);
676                                 
677                                                         //nand_copy(this->IO_ADDR_W, (unsigned char *)NFC_MBUF, mtd->writesize);
678                                                         nand_copy(io_wr_port, (unsigned char *)NFC_MBUF, mtd->writesize);
679                                                         REG_NFC_CMD = g_cmdsetting | NAND_CMD_SEQIN;
680                                                         nfc_wait_command_finish();
681                                                 }
682                                         } else
683                                                 printk("Operation !!! area.  %s  %s  %d\n", __FILE__, __FUNCTION__, __LINE__);
684                                 }
685
686                         sprd_wr_mode = NO_OP;
687                         sprd_area_mode = NO_AREA;
688                 break;
689                 default:
690                 break;  
691                 }
692         } else {
693                 if (0 == sprd_colrow_addr.colflag) {
694                         sprd_colrow_addr.colflag = 1;
695                         sprd_colrow_addr.column = cmd;
696                         return;
697                 }
698                 
699                 if (0 == sprd_colrow_addr.rowflag) {
700                         sprd_colrow_addr.rowflag = 1;
701                         sprd_colrow_addr.row = cmd;
702                 }
703                 
704                 if ((1 == sprd_colrow_addr.colflag) && (1 == sprd_colrow_addr.rowflag)) {
705                         if (buswidth == 1) {
706
707                         if (sprd_colrow_addr.column == (mtd->writesize >> 1)) {
708                                 pageperblk = mtd->erasesize / mtd->writesize;
709
710                                 phyblk = sprd_colrow_addr.row / pageperblk;
711                                 pageinblk = sprd_colrow_addr.row % pageperblk;
712                                 REG_NFC_STR0 = phyblk * pageperblk * mtd->writesize + 
713                                                         pageinblk * mtd->writesize + 
714                                                         sprd_colrow_addr.column;
715                                 REG_NFC_END0 = phyblk * pageperblk * mtd->writesize + 
716                                                         pageinblk * mtd->writesize + 
717                                                         sprd_colrow_addr.column + (mtd->oobsize >> 1) -1;
718                                 sprd_area_mode = OOB_AREA;      
719
720                         } else if (sprd_colrow_addr.column == 0) {
721                                 pageperblk = mtd->erasesize / mtd->writesize;
722                                 phyblk = sprd_colrow_addr.row / pageperblk;
723                                 pageinblk = sprd_colrow_addr.row % pageperblk;
724                                 REG_NFC_STR0 = phyblk * pageperblk * mtd->writesize + 
725                                                         pageinblk * mtd->writesize + 
726                                                         sprd_colrow_addr.column;
727                                 REG_NFC_END0 = phyblk * pageperblk * mtd->writesize  + 
728                                                         pageinblk * mtd->writesize + 
729                                                         sprd_colrow_addr.column + (mtd->writesize >> 1) - 1;
730                                 sprd_area_mode = DATA_AREA;     
731                         } else
732                                 printf("Operation ??? area.  %s  %s  %d\n", __FILE__, __FUNCTION__, __LINE__);
733                         } else {   //if (buswidth == 0) {
734                                 if (sprd_colrow_addr.column == mtd->writesize) {
735                                         pageperblk = mtd->erasesize / mtd->writesize;
736                                         phyblk = sprd_colrow_addr.row / pageperblk;
737                                         pageinblk = sprd_colrow_addr.row % pageperblk;
738
739                                         REG_NFC_STR0 = phyblk * pageperblk * mtd->writesize * 2 + 
740                                                                 pageinblk * mtd->writesize * 2 + 
741                                                                 sprd_colrow_addr.column;
742                                         REG_NFC_END0 = phyblk * pageperblk * mtd->writesize * 2 + 
743                                                                 pageinblk * mtd->writesize * 2 + 
744                                                                 sprd_colrow_addr.column + mtd->oobsize -1;
745                                         sprd_area_mode = OOB_AREA;      
746                                         /*printk("Operation OOB area.  %s  %s  %d   row=0x%08x  column=0x%08x\n", 
747                                                 __FILE__, __FUNCTION__, __LINE__, sprd_colrow_addr.row, sprd_colrow_addr.column);*/
748                                 } else if (sprd_colrow_addr.column == 0) {                              
749                                         pageperblk = mtd->erasesize / mtd->writesize;
750                                         phyblk = sprd_colrow_addr.row / pageperblk;
751                                         pageinblk = sprd_colrow_addr.row % pageperblk;
752 #ifdef NAND_DEBUG
753                 printf("function: %s pageperblk: 0x%x phyblk: 0x%x pageinblk: 0x%x\n", __FUNCTION__,  pageperblk, phyblk,  pageinblk);
754 #endif
755
756                                         REG_NFC_STR0 = phyblk * pageperblk * mtd->writesize * 2 + 
757                                                                 pageinblk * mtd->writesize * 2 + 
758                                                                 sprd_colrow_addr.column;
759                                         REG_NFC_END0 = phyblk * pageperblk * mtd->writesize * 2 + 
760                                                                 pageinblk * mtd->writesize * 2 + 
761                                                                 sprd_colrow_addr.column + mtd->writesize - 1;
762                                         sprd_area_mode = DATA_AREA;     
763                                         /*printk("Operation DATA area.  %s  %s  %d   row=0x%08x  column=0x%08x\n", 
764                                                 __FILE__, __FUNCTION__, __LINE__, sprd_colrow_addr.row, sprd_colrow_addr.column);*/
765                                 } else
766                                         printk("Operation ??? area for 8 Bits.  %s  %s  %d\n", __FILE__, __FUNCTION__, __LINE__);
767                         }
768
769                 }
770         }               
771 }
772
773 static unsigned long sprd_nand_readid(struct mtd_info *mtd)
774 {
775         return(nand_flash_id);
776 }
777
778 static int sprd_nand_devready(struct mtd_info *mtd)
779 {
780         unsigned long status = 0;
781         unsigned long cmd = NAND_CMD_STATUS | (0x1 << 31);
782
783         REG_NFC_CMD = cmd;
784         nfc_wait_command_finish();
785
786         status = REG_NFC_IDSTATUS;
787         if ((status & 0x1) != 0)        
788                 return -1; /* fail */
789         else if ((status & 0x40) == 0)
790                 return 0; /* busy */
791         else                                                    
792                 return 1; /* ready */
793 }
794 static void sprd_nand_select_chip(struct mtd_info *mtd, int chip)
795 {
796         struct nand_chip *this = mtd->priv;
797         struct sprd_nand_info *info = this->priv;
798
799 #if 0   
800         if (chip != -1)
801                 clk_enable(info->clk);
802         else
803                 clk_disable(info->clk);
804 #endif
805 }
806
807 static void sprd_nand_enable_hwecc(struct mtd_info *mtd, int mode)
808 {
809         sprd_ecc_mode = mode;
810 }
811
812 static unsigned long sprd_nand_wr_oob(struct mtd_info *mtd)
813 {
814         unsigned int i;
815         nand_copy(io_wr_port, (unsigned char *)NFC_SBUF, mtd->oobsize);
816 #ifdef NAND_DEBUG
817         printf("%s\n", __FUNCTION__);
818         for(i=0;i<64;i++) {
819                 printf("%x ", io_wr_port[i]);
820                 if(i!=0 && i%8==7)
821                   printf("\n");
822         }
823 #endif
824         /* write oob area */
825         if (sprd_area_mode == NO_AREA)
826                 sprd_area_mode = OOB_AREA;
827         else if (sprd_area_mode == DATA_AREA)
828                 sprd_area_mode = DATA_OOB_AREA;
829
830         return 0;
831 }
832
833 void nand_ecc_trans(unsigned char *pEccIn, unsigned char *pEccOut, unsigned char nSct)
834 {
835 #if 1
836         /* little endian */
837         switch(nSct)
838         {
839            case 1:
840                  pEccOut[0] = pEccIn[0];
841                  pEccOut[1] = pEccIn[1];
842                  pEccOut[2] = pEccIn[2];
843                  break;
844            case 2:
845                  pEccOut[0] = pEccIn[0];
846                  pEccOut[1] = pEccIn[1];
847                  pEccOut[2] = pEccIn[2];
848                  pEccOut[4] = pEccIn[4];
849                  pEccOut[5] = pEccIn[5];
850                  pEccOut[6] = pEccIn[6];
851                  break;
852            case 3:
853                  pEccOut[0] = pEccIn[0];
854                  pEccOut[1] = pEccIn[1];
855                  pEccOut[2] = pEccIn[2];
856                  pEccOut[4] = pEccIn[4];
857                  pEccOut[5] = pEccIn[5];
858                  pEccOut[6] = pEccIn[6];
859                  pEccOut[8] = pEccIn[8];
860                  pEccOut[9] = pEccIn[9];
861                  pEccOut[10] = pEccIn[10];
862                  break;
863            case 4:
864                  pEccOut[0] = pEccIn[0];
865                  pEccOut[1] = pEccIn[1];
866                  pEccOut[2] = pEccIn[2];
867                  pEccOut[4] = pEccIn[4];
868                  pEccOut[5] = pEccIn[5];
869                  pEccOut[6] = pEccIn[6];
870                  pEccOut[8] = pEccIn[8];
871                  pEccOut[9] = pEccIn[9];
872                  pEccOut[10] = pEccIn[10];
873                  pEccOut[12] = pEccIn[12];
874                  pEccOut[13] = pEccIn[13];
875                  pEccOut[14] = pEccIn[14];
876                  break;
877            default:
878                  break;     
879         }
880 #else
881         /* big endian */
882         switch(nSct)
883         {
884            case 1:
885                  pEccOut[0] = pEccIn[2];
886                  pEccOut[1] = pEccIn[1];
887                  pEccOut[2] = pEccIn[3];
888                  break;
889            case 2:
890                  pEccOut[0] = pEccIn[2];
891                  pEccOut[1] = pEccIn[1];
892                  pEccOut[2] = pEccIn[3];
893                  pEccOut[4] = pEccIn[6];
894                  pEccOut[5] = pEccIn[5];
895                  pEccOut[6] = pEccIn[7];
896                  break;
897            case 3:
898                  pEccOut[0] = pEccIn[2];
899                  pEccOut[1] = pEccIn[1];
900                  pEccOut[2] = pEccIn[3];
901                  pEccOut[4] = pEccIn[6];
902                  pEccOut[5] = pEccIn[5];
903                  pEccOut[6] = pEccIn[7];
904                  pEccOut[8] = pEccIn[10];
905                  pEccOut[9] = pEccIn[9];
906                  pEccOut[10] = pEccIn[11];
907                  break;
908            case 4:
909                  pEccOut[0] = pEccIn[2];
910                  pEccOut[1] = pEccIn[1];
911                  pEccOut[2] = pEccIn[3];
912                  pEccOut[4] = pEccIn[6];
913                  pEccOut[5] = pEccIn[5];
914                  pEccOut[6] = pEccIn[7];
915                  pEccOut[8] = pEccIn[10];
916                  pEccOut[9] = pEccIn[9];
917                  pEccOut[10] = pEccIn[11];
918                  pEccOut[12] = pEccIn[14];
919                  pEccOut[13] = pEccIn[13];
920                  pEccOut[14] = pEccIn[15];
921                  break;
922            default:
923                  break;     
924         }
925 #endif
926 }
927
928 static int sprd_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code)
929 {
930         unsigned long *pecc_val;
931         unsigned int i, j;
932
933         pecc_val=(unsigned long*)ecc_code;
934
935         if (sprd_ecc_mode == NAND_ECC_WRITE) {
936                 REG_NFC_ECCEN = 0x1;
937                 nand_copy(io_wr_port, (unsigned char *)NFC_MBUF, mtd->writesize);
938                 /* large page */
939                 pecc_val[0] = REG_NFC_PAGEECC0;
940                 pecc_val[1] = REG_NFC_PAGEECC1;
941                 pecc_val[2] = REG_NFC_PAGEECC2;
942                 pecc_val[3] = REG_NFC_PAGEECC3;
943 #ifdef NAND_DEBUG
944                 static unsigned int print_times =0;
945                 if(print_times < 10){
946                         for(i= 0; i< mtd->writesize;i++){
947                                 printf("%02x ", dat[i]);
948                                 if(i%32 == 31)
949                                   printf("\n");
950                         }
951                         print_times++;
952                 }
953                 for(i = 0; i< 4; i++)
954                         printf("write ecc %d is %x\n", i, pecc_val[i]);
955 #endif
956                 REG_NFC_ECCEN = 0;
957                 memset(io_wr_port, 0xff, NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZE); 
958         } else if (sprd_ecc_mode == NAND_ECC_READ) {
959                 /* large page */
960                 pecc_val[0] = REG_NFC_PAGEECC0;
961                 pecc_val[1] = REG_NFC_PAGEECC1;
962                 pecc_val[2] = REG_NFC_PAGEECC2;
963                 pecc_val[3] = REG_NFC_PAGEECC3;
964 #ifdef NAND_DEBUG
965                 for(i = 0; i< 4; i++)
966                         printf("read ecc %d is %x\n", i, pecc_val[i]);
967 #endif
968
969                 memset(io_wr_port, 0xff, NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZE);
970                 nand_copy((unsigned char *)NFC_SBUF, io_wr_port, mtd->oobsize);
971 //#ifdef NAND_DEBUG
972 #if 0
973                 printf("read oob \n");
974                 for(i = 0; i<16; i++){
975                         printf("%x ", ecc_code[i]);
976                         if(i!=0 && i%8 == 7)
977                           printf("\n");
978                 }
979 #endif
980         }       
981         sprd_ecc_mode = NAND_ECC_NONE;
982
983         return 0;
984 }
985
986 static int countbits(unsigned long byte)
987 {
988         int res = 0;
989
990         for (;byte; byte >>= 1)
991                 res += byte & 0x01;
992         return res;
993 }
994 static void ecc_trans(unsigned char *ecc)
995 {
996         unsigned char trans;
997         
998         trans = ecc[0];
999         ecc[0] = ecc[1];
1000         ecc[1] = ecc[2];
1001         ecc[2] = trans;
1002 }
1003
1004
1005 static int ECC_CompM(unsigned char *pEcc1, unsigned char *pEcc2, unsigned char *pBuf, unsigned char nBW)
1006 {
1007         unsigned long  nEccComp = 0, nEccSum = 0;
1008         unsigned long  nEBit    = 0;
1009         unsigned long  nEByte   = 0;
1010         unsigned long  nXorT1   = 0, nXorT2 = 0;
1011         unsigned long  nCnt;
1012
1013         for (nCnt = 0; nCnt < 2; nCnt++) {
1014                 nXorT1 ^= (((*pEcc1) >> nCnt) & 0x01);
1015                 nXorT2 ^= (((*pEcc2) >> nCnt) & 0x01);
1016         }
1017
1018         for (nCnt = 0; nCnt < 3; nCnt++) {
1019                 nEccComp |= ((~pEcc1[nCnt] ^ ~pEcc2[nCnt]) << (nCnt * 8));
1020         }
1021         for(nCnt = 0; nCnt < 24; nCnt++) {
1022                 nEccSum += ((nEccComp >> nCnt) & 0x01);
1023         }
1024 #ifdef NAND_DEBUG
1025                 printf("function: %s line: %d nEccSum: %d\n", __FUNCTION__, __LINE__, nEccSum);
1026 #endif
1027         switch (nEccSum) {
1028         case 0 :
1029                 return 0;
1030         case 1 :
1031                 return 1;
1032         case 12 :
1033                 if (nXorT1 != nXorT2) {
1034                                 ecc_trans(pEcc1);
1035                                 ecc_trans(pEcc2);
1036 /*
1037                         if (nBW == 0) {
1038                                 nEByte  = ((nEccComp >>  9) & 0x100) +
1039                                         ((nEccComp >>  8) & 0x80) + ((nEccComp >>  7) & 0x40) +
1040                                         ((nEccComp >>  6) & 0x20) + ((nEccComp >>  5) & 0x10) +
1041                                         ((nEccComp >>  4) & 0x08) + ((nEccComp >>  3) & 0x04) +
1042                                         ((nEccComp >>  2) & 0x02) + ((nEccComp >>  1) & 0x01);
1043                                 nEBit   = ((nEccComp >> 21) & 0x04) +
1044                                         ((nEccComp >> 20) & 0x02) + ((nEccComp >> 19) & 0x01);
1045                         } else */{   /* (nBW == BW_X16) */
1046                                 nEByte  = ((nEccComp >>  7) & 0x100) +
1047                                         ((nEccComp >>  6) & 0x80) + ((nEccComp >>  5) & 0x40) +
1048                                         ((nEccComp >>  4) & 0x20) + ((nEccComp >>  3) & 0x10) +
1049                                         ((nEccComp >>  2) & 0x08) + ((nEccComp >>  1) & 0x04) +
1050                                         (nEccComp & 0x02)         + ((nEccComp >> 23) & 0x01);
1051                                 nEBit   = (unsigned char)(((nEccComp >> 19) & 0x04) +
1052                                         ((nEccComp >> 18) & 0x02) + ((nEccComp >> 17) & 0x01));
1053                         }
1054                         if (pBuf != NULL) {
1055                                         pBuf[nEByte] = (unsigned char)(pBuf[nEByte] ^ (1 << nEBit));
1056                         }
1057                         return 1;
1058                 }
1059         default :
1060  
1061            break;
1062         }
1063         return -1;
1064 }
1065
1066 static int correct(u_char *dat, u_char *read_ecc, u_char *calc_ecc)
1067 {
1068 #ifdef CONFIG_SC8800G
1069         ecc_trans(read_ecc);
1070         ecc_trans(calc_ecc);
1071 #endif
1072         return ECC_CompM(read_ecc, calc_ecc, dat, 1);
1073 }
1074
1075 #if 0
1076
1077 static int sprd_nand_correct_data(struct mtd_info *mtd, uint8_t *dat,
1078                                      uint8_t *read_ecc, uint8_t *calc_ecc)
1079 {
1080         int i, retval = 0;
1081
1082         if (mtd->writesize > 512) {
1083                 for (i = 0; i < 4; i++) {
1084                         if (correct(dat + 512 * i, read_ecc + 4*i + 1, calc_ecc + 4*i + 1) == -1) {                             
1085                                 retval = -1;
1086                         }
1087                 }
1088         } else
1089                 retval = correct(dat, read_ecc, calc_ecc);
1090         
1091         return retval;
1092 }
1093 #else
1094 static int sprd_nand_correct_data(struct mtd_info *mtd, uint8_t *dat,
1095                                      uint8_t *read_ecc, uint8_t *calc_ecc)
1096 {
1097         int i, retval = 0;
1098         int retval0, retval1, retval2, retval3;
1099 #if 0
1100         printk("\nthe all data\n");
1101         for(i = 0; i < 2048; i++) {
1102                 printk("%02x ", *(dat + i));
1103                 if(i % 16 == 15)
1104                   printk("\n");
1105         }
1106
1107         printk("\nthe read ecc\n");
1108         for(i = 0; i < 16; i ++) {
1109                         printk("%02x ", *(read_ecc + i));
1110                         if(i % 4 == 3)
1111                                 printk("\n");
1112         }
1113
1114         printk("\nthe calc ecc\n");
1115         for(i = 0; i < 16; i ++) {
1116                         printk("%02x ", *(calc_ecc + i));
1117                         if(i % 4 == 3)
1118                                 printk("\n");
1119         }
1120 #endif
1121         if (mtd->writesize > 512) {
1122 #if 0
1123                 for (i = 0; i < 4; i++) {
1124                         if (correct(dat + 512 * i, read_ecc + 4 * i, calc_ecc + 4 * i) == -1) {                         
1125                                 retval = -1;
1126                         }
1127                 }
1128 #else
1129         retval0 = correct(dat + 512 * 0, read_ecc + 4 * 0, calc_ecc + 4 * 0);
1130         retval1 = correct(dat + 512 * 1, read_ecc + 4 * 1, calc_ecc + 4 * 1);
1131         retval2 = correct(dat + 512 * 2, read_ecc + 4 * 2, calc_ecc + 4 * 2);
1132         retval3 = correct(dat + 512 * 3, read_ecc + 4 * 3, calc_ecc + 4 * 3);
1133 #ifdef NAND_DEBUG
1134         printf("function: %s retval0: %d\n", __FUNCTION__, retval0);
1135         printf("function: %s retval1: %d\n", __FUNCTION__, retval1);
1136         printf("function: %s retval2: %d\n", __FUNCTION__, retval2);
1137         printf("function: %s retval3: %d\n", __FUNCTION__, retval3);
1138 #endif
1139
1140         if ((retval0 == -1) || (retval1 == -1) || (retval2 == -1) || (retval3 == -1))
1141                 retval = -1;
1142         else
1143                 retval = retval0 + retval1 + retval2 + retval3;
1144 #endif
1145         } else
1146                 retval = correct(dat, read_ecc, calc_ecc);
1147         
1148 #ifdef NAND_DEBUG
1149         printf("function: %s retval: %d\n", __FUNCTION__, retval);
1150 #endif
1151         return retval;
1152 }
1153
1154 #endif
1155
1156 static struct sprd_nand_info g_info = {0,0};
1157 static struct sprd_platform_nand g_plat = {0};
1158
1159 int board_nand_init(struct nand_chip *this)
1160 {
1161         //struct mtd_info *mtd;
1162         unsigned long i, id, type;
1163         volatile int ik_cnt = 0;
1164         
1165         /*structs must be linked */
1166         //mtd = &host->mtd;
1167 //      mtd->priv = this;
1168         //host->nand = this;
1169         
1170         g_info.platform = &g_plat;
1171                 /* set sprd_colrow_addr */
1172         sprd_colrow_addr.column = 0;
1173         sprd_colrow_addr.row = 0;
1174         sprd_colrow_addr.colflag = 0;
1175         sprd_colrow_addr.rowflag = 0;
1176         sprd_wr_mode = NO_OP;
1177         sprd_area_mode = NO_AREA;
1178         sprd_ecc_mode = NAND_ECC_NONE;
1179
1180         REG_AHB_CTL0 |= BIT_8;//no BIT_9
1181         REG_AHB_SOFT_RST |= BIT_5;
1182         for(ik_cnt = 0; ik_cnt < 0xffff; ik_cnt++);
1183         REG_AHB_SOFT_RST &= ~BIT_5;
1184         REG_NFC_INTSRC |= BIT_0 | BIT_4 | BIT_5;
1185         /* 0x1 : WPN disable, and micron nand flash status is 0xeo 
1186  *         0x0 : WPN enable, and micron nand flash status is 0x60 */
1187         REG_NFC_WPN = 0x1;
1188         
1189         set_sc8800g_gpio_as_nand_8bit();
1190         set_nfc_param(0);//53MHz
1191         memset(io_wr_port, 0xff, NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZE);
1192
1193         nfc_reset();
1194         //udelay(2000);
1195
1196         for(ik_cnt = 0; ik_cnt < 0xfffff; ik_cnt++)
1197           ;
1198         nfc_read_status();
1199         id = nfc_read_id();
1200         type = nand_bit_width(id);
1201
1202         if (type == 1) {
1203                 this->options |= NAND_BUSWIDTH_16;
1204                 g_buswidth = 1;
1205                 g_addr_cycle = 5;
1206                 printk("16 Bit");       
1207         } else {
1208                 g_buswidth = 0;
1209                 g_addr_cycle = 4;
1210                 printk("8 Bit ");
1211         }
1212
1213
1214 /* set the timing for nand controller */
1215         /* 16-bit bus width */
1216         this->IO_ADDR_R = this->IO_ADDR_W = io_wr_port;
1217         this->cmd_ctrl = sprd_nand_hwcontrol;
1218         this->dev_ready = sprd_nand_devready;
1219         this->select_chip = sprd_nand_select_chip;
1220
1221 #ifdef CONFIG_NAND_SPL
1222         this->read_byte = nand_read_byte;
1223         this->write_buf = nand_write_buf;
1224         this->read_buf  = nand_read_buf;
1225 #endif
1226         this->nfc_readid = sprd_nand_readid;
1227         this->nfc_wr_oob = sprd_nand_wr_oob;
1228
1229 #ifdef CONFIG_SPRD_NAND_HWECC
1230         this->ecc.calculate = sprd_nand_calculate_ecc;
1231         this->ecc.correct = sprd_nand_correct_data;
1232         this->ecc.hwctl = sprd_nand_enable_hwecc;
1233         this->ecc.mode = NAND_ECC_HW;
1234         this->ecc.size = CONFIG_SYS_NAND_ECCSIZE;//512;
1235         this->ecc.bytes = CONFIG_SYS_NAND_ECCBYTES;//3
1236 #else
1237         this->ecc.mode = NAND_ECC_SOFT;
1238 #endif
1239
1240         this->chip_delay = 20;
1241         this->priv = &g_info;
1242         return 0;
1243 }
1244
1245 int sprd_scan_one_block(int blk, int erasesize, int writesize)
1246 {
1247         unsigned long phyblk, pageinblk, pageperblk;
1248         unsigned long i;
1249         //unsigned long addr_cycle = 5; /* advance 0 : can be set 3 or 4; advance 1: can be set 4 or 5 */
1250         unsigned long advance = 1; /* can be set 0 or 1 */
1251         unsigned long pagetype; /* 0: small page; 1: large page*/
1252         //unsigned long buswidth = 1; /* 0: X8 bus width 1: X16 bus width */
1253         unsigned long chipsel = 0;
1254         unsigned long buswidth = g_buswidth;
1255         unsigned long addr_cycle = g_addr_cycle;
1256         int status = 1, ii;
1257         unsigned long column = writesize >> 1;
1258         unsigned long row = blk * (erasesize / writesize);
1259         int aaa;
1260
1261         if (512 == writesize)
1262                 pagetype = 0;
1263         else
1264                 pagetype = 1;
1265
1266         if (addr_cycle == 3)
1267                 addr_cycle = 0;
1268         else if ((addr_cycle == 4) && (advance == 1))
1269                 addr_cycle = 0;
1270         else
1271                 addr_cycle = 3;
1272
1273         memset(io_wr_port, 0x0, NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZE);
1274         if (buswidth == 1) {
1275                 if (column == (writesize >> 1)) {
1276                         for (ii = 0; ii < 2; ii ++) {
1277                                 row += ii;
1278                                 pageperblk = (erasesize / writesize);
1279
1280                                 phyblk = row / pageperblk;
1281                                 pageinblk = row % pageperblk;
1282                                 //printf("ii = %d phyblk = %d  pageinblk = %d\n", ii, phyblk, pageinblk);
1283                                 REG_NFC_STR0 = phyblk * pageperblk * writesize + 
1284                                                 pageinblk * writesize + 
1285                                                 column;
1286                                 REG_NFC_END0 = phyblk * pageperblk * writesize + 
1287                                                 pageinblk * writesize + 
1288                                                 column + (writesize >> 1) - 1;  
1289
1290                                 g_cmdsetting = (chipsel << 26) | (addr_cycle << 24) | (advance << 23) | (buswidth << 19) | (pagetype << 18) | (0 << 16) | (0x1 << 31);
1291                                 REG_NFC_CMD = g_cmdsetting | NAND_CMD_READ0;
1292                                 nfc_wait_command_finish();
1293                                 nand_copy((unsigned long *)NFC_SBUF, (unsigned long *)io_wr_port, 64);
1294                                 if ((io_wr_port[0] != 0xff) || (io_wr_port[1] != 0xff))
1295                                         break;
1296                         }
1297                 }
1298         }
1299
1300         if ((io_wr_port[0] == 0xff) && (io_wr_port[1] == 0xff))
1301                 status = 0; //good block
1302         else
1303                 status = 1; //bad block
1304
1305         return status;
1306 }
1307
1308 int nand_ctl_erase_block(unsigned long addr, int writesize)
1309 {
1310         unsigned long phyblk, pageinblk, pageperblk;
1311         unsigned long i;
1312         //unsigned long addr_cycle = 5; /* advance 0 : can be set 3 or 4; advance 1: can be set 4 or 5 */
1313         unsigned long advance = 1; /* can be set 0 or 1 */
1314         unsigned long pagetype; /* 0: small page; 1: large page*/
1315         //unsigned long buswidth = 1; /* 0: X8 bus width 1: X16 bus width */
1316         unsigned long chipsel = 0;
1317         unsigned long buswidth = g_buswidth;
1318         unsigned long addr_cycle = g_addr_cycle;
1319         int status = 0;
1320
1321         if (512 == writesize)
1322                 pagetype = 0;
1323         else
1324                 pagetype = 1;
1325
1326         if (addr_cycle == 3)
1327                 addr_cycle = 0;
1328         else if ((addr_cycle == 4) && (advance == 1))
1329                 addr_cycle = 0;
1330         else
1331                 addr_cycle = 3;
1332
1333         g_cmdsetting = (chipsel << 26) | (addr_cycle << 24) | (advance << 23) | (buswidth << 19) | (pagetype << 18) | (0 << 16) | (0x1 << 31);
1334         if (buswidth == 1)
1335                 REG_NFC_STR0 = addr;
1336         else
1337                 REG_NFC_STR0 = addr * 2;
1338
1339         REG_NFC_CMD = g_cmdsetting | NAND_CMD_ERASE1;
1340         nfc_wait_command_finish();
1341
1342         status = nfc_read_status();
1343         return status;
1344 }
1345
1346 void nand_scan_patition(int blocks, int erasesize, int writesize)
1347 {
1348         int blk;
1349         int ret;
1350
1351         //printf("blocks = %d  erasesize = 0x%08x\n", blocks, erasesize);
1352         for (blk = 0; blk < blocks; blk ++) {
1353                 ret = sprd_scan_one_block(blk, erasesize, writesize);
1354                 if (ret != 0) {
1355                         printf("\n%d is bad, scrub to erase it, ", blk);
1356                         ret = nand_ctl_erase_block(blk * erasesize, writesize);
1357                         printf("0x%02x\n", ret);
1358                 } else {
1359                         ret = nand_ctl_erase_block(blk * erasesize, writesize);
1360                         printf("erasing block : %d    %d % \r", blk, (blk * 100 ) / blocks);
1361                 }
1362         }
1363 }
1364