807b4b102a3e5694c46fef1494d0fd562c875289
[profile/mobile/platform/kernel/u-boot-tm1.git] / drivers / mtd / nand / sc8810_nand.c
1 #include <config.h>\r
2 #include <common.h>\r
3 #include <asm/arch/bits.h>\r
4 #include <asm/arch/chip_drv_config_extern.h>\r
5 #include <asm/arch/regs_nfc.h>\r
6 #include <asm/arch/regs_cpc.h>\r
7 #include <asm/arch/sdram_cfg.h>\r
8 #include <nand.h>\r
9 #include <asm/io.h>\r
10 #include <linux/mtd/nand.h>\r
11 \r
12 #ifdef CONFIG_NAND_SPL\r
13 #define printf(arg...) do{}while(0)\r
14 #endif\r
15 \r
16 #define NFC_ECC_EVENT           1\r
17 #define NFC_DONE_EVENT          2\r
18 #define NFC_TX_DMA_EVENT        4\r
19 #define NFC_RX_DMA_EVENT        8\r
20 #define NFC_ERR_EVENT           16\r
21 #define NFC_TIMEOUT_EVENT       32\r
22 #define NFC_TIMEOUT_VAL         0x1000000\r
23 \r
24 /* 2 bit correct, sc8810 support 1, 2, 4, 8, 12,14, 24 */\r
25 #define CONFIG_SYS_NAND_ECC_MODE        2\r
26 /* Number of ECC bytes per OOB - S3C6400 calculates 4 bytes ECC in 1-bit mode */\r
27 #define CONFIG_SYS_NAND_ECCBYTES        4\r
28 /* Size of the block protected by one OOB (Spare Area in Samsung terminology) */\r
29 #define CONFIG_SYS_NAND_ECCSIZE 512\r
30 \r
31 struct sc8810_nand_timing_param {\r
32         u8 acs_time;\r
33         u8 rwh_time;\r
34         u8 rwl_time;\r
35         u8 acr_time;\r
36         u8 rr_time;\r
37         u8 ceh_time;\r
38 };\r
39 struct sc8810_nand_info {\r
40         struct clk      *clk;\r
41         struct nand_chip *chip;\r
42         unsigned int cfg0_setting;\r
43         unsigned int ecc0_cfg_setting;\r
44         unsigned int ecc1_cfg_setting;\r
45         u8      asy_cle; //address cycles, can be set 3, 4, 5\r
46         u8      advance;// advance property, can be set 0, 1\r
47         u8      bus_width; //bus width, can be 0 or 1\r
48         u8      ecc_mode; // ecc mode can be 1, 2, 4, 8, 12, 16,24\r
49         u8      mc_ins_num; // micro instruction number\r
50         u8      mc_addr_ins_num; //micro address instruction number\r
51         u16     ecc_postion; //ecc postion\r
52         u16     b_pointer; // nfc buffer pointer\r
53         u16     addr_array[5];// the addrss of the flash to operation   \r
54 };\r
55 \r
56 struct sc8810_nand_page_oob {\r
57         unsigned char m_c;\r
58         unsigned char d_c;\r
59         unsigned char cyc_3;\r
60         unsigned char cyc_4;\r
61         unsigned char cyc_5;\r
62         int pagesize;\r
63         int oobsize; /* total oob size */\r
64         int eccsize; /* per ??? bytes data for ecc calcuate once time */\r
65         int eccbit; /* ecc level per eccsize */\r
66 };\r
67 \r
68 struct nand_spec_str{\r
69     u8          mid;\r
70     u8          did;\r
71     u8          id3;\r
72     u8          id4;\r
73     u8          id5;\r
74     struct sc8810_nand_timing_param timing_cfg;\r
75 };\r
76 \r
77 static struct nand_spec_str *ptr_nand_spec = NULL;\r
78 \r
79 #define NF_MC_CMD_ID    (0xFD)\r
80 #define NF_MC_ADDR_ID   (0xF1)\r
81 #define NF_MC_WAIT_ID   (0xF2)\r
82 #define NF_MC_RWORD_ID  (0xF3)\r
83 #define NF_MC_RBLK_ID   (0xF4)\r
84 #define NF_MC_WWORD_ID  (0xF6)\r
85 #define NF_MC_WBLK_ID   (0xF7)\r
86 #define NF_MC_DEACTV_ID (0xF9)\r
87 #define NF_MC_NOP_ID    (0xFA)\r
88 #define NF_PARA_20M             0x7ac05      //trwl = 0  trwh = 0\r
89 #define NF_PARA_40M             0x7ac15      //trwl = 1  trwh = 0\r
90 #define NF_PARA_53M             0x7ad26      //trwl = 2  trwh = 1\r
91 #define NF_PARA_80M             0x7ad37      //trwl = 3  trwh = 1\r
92 #define NF_PARA_DEFAULT         0x7ad77      //trwl = 7  trwh = 1\r
93 \r
94 #define REG_AHB_CTL0                            (*((volatile unsigned int *)(AHB_CTL0)))\r
95 #define REG_AHB_SOFT_RST                                (*((volatile unsigned int *)(AHB_SOFT_RST)))\r
96 \r
97 #define REG_GR_NFC_MEM_DLY                      (*((volatile unsigned int *)(GR_NFC_MEM_DLY)))\r
98 \r
99 static int mtderasesize = 0;\r
100 static int mtdwritesize = 0;\r
101 static int mtdoobsize = 0;\r
102 \r
103 static struct sc8810_nand_info g_info ={0};\r
104 static nand_ecc_modes_t sprd_ecc_mode = NAND_ECC_NONE;\r
105 static __attribute__((aligned(4))) unsigned char io_wr_port[NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZE];\r
106 static char nand_id_table[5]={0};\r
107 static int  re_oob_layout=0;\r
108 \r
109 struct nand_ecclayout _nand_oob_64 = {\r
110         .eccbytes = 24,\r
111         .eccpos = {\r
112                    40, 41, 42, 43, 44, 45, 46, 47,\r
113                    48, 49, 50, 51, 52, 53, 54, 55,\r
114                    56, 57, 58, 59, 60, 61, 62, 63},\r
115         .oobfree = {\r
116                 {.offset = 2,\r
117                  .length = 38}}\r
118 };\r
119 \r
120 struct nand_ecclayout _nand_oob_64_4bit = {\r
121         .eccbytes = 28,\r
122         .eccpos = {\r
123                        36, 37, 38, 39, 40, 41, 42, 43,\r
124                    44, 45, 46, 47, 48, 49, 50, 51,\r
125                    52, 53, 54, 55, 56, 57, 58, 59,\r
126                    60, 61, 62, 63},\r
127         .oobfree = {\r
128                 {.offset = 2,\r
129                  .length = 34}}\r
130 };\r
131 \r
132 \r
133 static struct nand_ecclayout nand_oob_128 = {\r
134         .eccbytes = 48,\r
135         .eccpos = {\r
136                     80,  81,  82,  83,  84,  85,  86,  87,\r
137                     88,  89,  90,  91,  92,  93,  94,  95,\r
138                     96,  97,  98,  99, 100, 101, 102, 103,\r
139                    104, 105, 106, 107, 108, 109, 110, 111,\r
140                    112, 113, 114, 115, 116, 117, 118, 119,\r
141                    120, 121, 122, 123, 124, 125, 126, 127},\r
142         .oobfree = {\r
143                 {.offset = 2,\r
144                  .length = 78}}\r
145 };\r
146 \r
147 static struct nand_ecclayout _nand_oob_128 = {\r
148         .eccbytes = 56,\r
149         .eccpos = {\r
150                 72, 73, 74, 75, 76, 77, 78, 79,\r
151                 80,  81,  82,  83,  84,  85,  86,  87,\r
152                 88,  89,  90,  91,  92,  93,  94,  95,\r
153                 96,  97,  98,  99, 100, 101, 102, 103,\r
154                 104, 105, 106, 107, 108, 109, 110, 111,\r
155                 112, 113, 114, 115, 116, 117, 118, 119,\r
156                 120, 121, 122, 123, 124, 125, 126, 127},\r
157         .oobfree = {\r
158                 {.offset = 2,\r
159                 .length = 70}}\r
160 };\r
161 \r
162 static struct nand_ecclayout _nand_oob_224 = {\r
163         .eccbytes = 112,\r
164         .eccpos = {\r
165                 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124,\r
166                 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137,\r
167                 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150,\r
168                 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163,\r
169                 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176,\r
170                 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189,\r
171                 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202,\r
172                 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215,\r
173                 216, 217, 218, 219, 220, 221, 222, 223},\r
174         .oobfree = {\r
175                 {.offset = 2,\r
176                 .length = 110}}\r
177 };\r
178 \r
179 \r
180 \r
181 static struct nand_ecclayout _nand_oob_256 = {\r
182         .eccbytes = 112,\r
183         .eccpos = {\r
184                 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156,\r
185                 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169,\r
186                 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182,\r
187                 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195,\r
188                 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208,\r
189                 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221,\r
190                 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234,\r
191                 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247,\r
192                 248, 249, 250, 251, 252, 253, 254, 255},\r
193         .oobfree = {\r
194                 {.offset = 2,\r
195                 .length = 142}}\r
196 };\r
197 \r
198 #if 0\r
199 struct sc8810_nand_timing_param nand_timing =\r
200 {\r
201         50,\r
202         30,\r
203         40,\r
204         40,\r
205         40,\r
206         50\r
207 };\r
208 #endif\r
209 \r
210 /* only for special 4kpage or 8kpage nand flash, no 2kpage or normal 4kpage or normal 8kpage */\r
211 static struct sc8810_nand_page_oob nand_config_table[] =\r
212 {\r
213         {0xec, 0xbc, 0x00, 0x66, 0x56, 4096, 128, 512, 4},\r
214         {0x2c, 0xb3, 0x90, 0x66, 0x64, 4096, 224, 512, 8},\r
215         {0x2c, 0xbc, 0x90, 0x66, 0x54, 4096, 224, 512, 8},\r
216         {0xec, 0xb3, 0x01, 0x66, 0x5a, 4096, 128, 512, 4},\r
217         {0xec, 0xbc, 0x00, 0x6a, 0x56, 4096, 256, 512, 8},\r
218         {0xad, 0xbc, 0x90, 0x55, 0x56, 2048, 64,  512, 4},\r
219         {0x2c, 0xbc, 0x90, 0x55, 0x56, 2048, 64,  512, 4},\r
220         {0x2c, 0xb3, 0xd1, 0x55, 0x56, 2048, 64,  512, 4},\r
221         {0xc8, 0xbc, 0x90, 0x55, 0x54, 2048, 64,  512, 4}\r
222 };\r
223 \r
224 /* some nand id could not be calculated the pagesize by mtd, replace it with a known id which has the same format. */\r
225 static unsigned char nand_id_replace_table[][10] =\r
226 {\r
227     {0xad, 0xb3, 0x91, 0x11, 0x00, /*replace with*/ 0xec, 0xbc, 0x00, 0x66, 0x56},\r
228     {0xad, 0xbc, 0x90, 0x11, 0x00, /*replace with*/ 0xec, 0xbc, 0x00, 0x66, 0x56}\r
229 };\r
230 \r
231 #if !defined(CONFIG_NAND_SPL)\r
232 static const struct nand_spec_str nand_spec_table[] = {\r
233     {0x2c, 0xb3, 0xd1, 0x55, 0x5a, {10, 10, 12, 10, 20, 50}},// MT29C8G96MAAFBACKD-5, MT29C4G96MAAHBACKD-5\r
234     {0x2c, 0xba, 0x80, 0x55, 0x50, {10, 10, 12, 10, 20, 50}},// MT29C2G48MAKLCJA-5 IT\r
235     {0x2c, 0xbc, 0x90, 0x55, 0x56, {10, 10, 12, 10, 20, 50}},// KTR0405AS-HHg1, KTR0403AS-HHg1, MT29C4G96MAZAPDJA-5 IT\r
236 \r
237     {0x98, 0xac, 0x90, 0x15, 0x76, {12, 10, 12, 10, 20, 50}},// TYBC0A111392KC\r
238     {0x98, 0xbc, 0x90, 0x55, 0x76, {12, 15, 15, 10, 20, 50}},// TYBC0A111430KC, KSLCBBL1FB4G3A, KSLCBBL1FB2G3A\r
239     {0x98, 0xbc, 0x90, 0x66, 0x76, {12, 15, 15, 10, 20, 50}},// KSLCCBL1FB2G3A_mvr400\r
240 \r
241     {0xad, 0xbc, 0x90, 0x11, 0x00, {25, 15, 25, 10, 20, 50}},// H9DA4VH4JJMMCR-4EMi, H9DA4VH2GJMMCR-4EM\r
242     {0xad, 0xbc, 0x90, 0x55, 0x54, {25, 15, 25, 10, 20, 50}},//\r
243     {0xad, 0xbc, 0x90, 0x55, 0x56, {25, 20, 30, 10, 20, 50}},//H9DA4GH2GJBMCR\r
244 \r
245     {0xec, 0xb3, 0x01, 0x66, 0x5a, {21, 10, 21, 10, 20, 50}},// KBY00U00VA-B450\r
246     {0xec, 0xbc, 0x00, 0x55, 0x54, {21, 10, 21, 10, 20, 50}},// KA100O015M-AJTT\r
247     {0xec, 0xbc, 0x00, 0x6a, 0x56, {21, 10, 21, 10, 20, 50}},// K524G2GACH-B050\r
248     {0xec, 0xbc, 0x01, 0x55, 0x48, {21, 15, 21, 10, 20, 50}},// KBY00N00HM-A448\r
249 \r
250     {0, 0, 0, 0, 0, {0, 0, 0, 0, 0, 0}}\r
251 };\r
252 #endif\r
253 \r
254 void read_chip_id(void);\r
255 static void nfc_reg_write(unsigned int addr, unsigned int value)\r
256 {\r
257         writel(value, addr);\r
258 }\r
259 static unsigned int nfc_reg_read(unsigned int addr)\r
260 {\r
261         return readl(addr);\r
262 }\r
263 \r
264 static void  nfc_mcr_inst_init(void)\r
265 {\r
266         g_info.mc_ins_num = 0;\r
267         g_info.b_pointer = 0;\r
268         g_info.mc_addr_ins_num = 0;\r
269 }\r
270 void  nfc_mcr_inst_add(u32 ins, u32 mode)\r
271 {\r
272         unsigned int offset;\r
273         unsigned int high_flag;\r
274         unsigned int reg_value;\r
275         offset = g_info.mc_ins_num >> 1;\r
276         high_flag = g_info.mc_ins_num & 0x1;\r
277         if(NF_MC_ADDR_ID == mode)\r
278         {\r
279                 g_info.addr_array[g_info.mc_addr_ins_num ++] = ins;\r
280         }\r
281         if(high_flag)\r
282         {\r
283                 reg_value = nfc_reg_read(NFC_START_ADDR0 + (offset << 2));\r
284                 reg_value &= 0x0000ffff;\r
285                 reg_value |= ins << 24;\r
286                 reg_value |= mode << 16;\r
287         }\r
288         else\r
289         {\r
290                 reg_value = nfc_reg_read(NFC_START_ADDR0 + (offset << 2));\r
291                 reg_value &= 0xffff0000;\r
292                 reg_value |= ins << 8;\r
293                 reg_value |= mode;              \r
294         }\r
295         nfc_reg_write(NFC_START_ADDR0 + (offset << 2), reg_value);\r
296         g_info.mc_ins_num ++;\r
297 }\r
298 static unsigned int nfc_mcr_inst_exc(void)\r
299 {\r
300         unsigned int value;\r
301         value = nfc_reg_read(NFC_CFG0);\r
302         if(g_info.chip->options & NAND_BUSWIDTH_16)\r
303         {\r
304                 value |= NFC_BUS_WIDTH_16;\r
305         }\r
306         else\r
307         {\r
308                 value &= ~NFC_BUS_WIDTH_16;\r
309         }\r
310         value |= (1 << NFC_CMD_SET_OFFSET);\r
311         nfc_reg_write(NFC_CFG0, value);\r
312         value = NFC_CMD_VALID | ((unsigned int)NF_MC_NOP_ID) |  ((g_info.mc_ins_num - 1) << 16);\r
313         nfc_reg_write(NFC_CMD, value);\r
314         return 0;\r
315 }\r
316 \r
317 static unsigned int nfc_mcr_inst_exc_for_id(void)\r
318 {\r
319         unsigned int value;\r
320 \r
321         value = nfc_reg_read(NFC_CFG0);\r
322         value &= ~NFC_BUS_WIDTH_16;\r
323         value |= (1 << NFC_CMD_SET_OFFSET);\r
324 \r
325         nfc_reg_write(NFC_CFG0, value);\r
326         value = NFC_CMD_VALID | ((unsigned int)NF_MC_NOP_ID) |((g_info.mc_ins_num - 1) << 16);\r
327         nfc_reg_write(NFC_CMD, value);\r
328         return 0;\r
329 }\r
330 \r
331 static void sc8810_nand_wp_en(int en)\r
332 {\r
333         unsigned int value;\r
334         if(en)\r
335         {\r
336                 value = nfc_reg_read(NFC_CFG0);\r
337                 value &= ~ NFC_WPN;\r
338                 nfc_reg_write(NFC_CFG0, value);\r
339         }\r
340         else\r
341         {\r
342                 value = nfc_reg_read(NFC_CFG0);\r
343                 value |= NFC_WPN;\r
344                 nfc_reg_write(NFC_CFG0, value);         \r
345         }\r
346 }\r
347 static int sc8810_nfc_wait_command_finish(unsigned int flag)\r
348 {\r
349         unsigned int event = 0;\r
350         unsigned int value;\r
351         unsigned int counter = 0;\r
352         while(((event & flag) != flag) && (counter < NFC_TIMEOUT_VAL/*time out*/))\r
353         {\r
354                 value = nfc_reg_read(NFC_CLR_RAW);\r
355                 if(value & NFC_ECC_DONE_RAW)\r
356                 {\r
357                         event |= NFC_ECC_EVENT;\r
358                 }\r
359                 if(value & NFC_DONE_RAW)\r
360                 {\r
361                         event |= NFC_DONE_EVENT;\r
362                 }\r
363                 counter ++;\r
364         }\r
365         nfc_reg_write(NFC_CLR_RAW, 0xffff0000); //clear all interrupt status\r
366         if(counter > NFC_TIMEOUT_VAL)\r
367         {\r
368             int i;\r
369             for (i=0; i<40; i++)\r
370             {\r
371             printk("\r\nnfc cmd reg addr:0x%x, value:0x%xx!\r\n", NFC_CMD+i);\r
372         }\r
373                 while (1);\r
374                 return -1;\r
375         }\r
376         return 0;\r
377 }\r
378 unsigned int ecc_mode_convert(u32 mode)\r
379 {\r
380         u32 mode_m;\r
381         switch(mode)\r
382         {\r
383         case 1:\r
384                 mode_m = 0;\r
385                 break;\r
386         case 2:\r
387                 mode_m = 1;\r
388                 break;\r
389         case 4:\r
390                 mode_m = 2;\r
391                 break;\r
392         case 8:\r
393                 mode_m = 3;\r
394                 break;\r
395         case 12:\r
396                 mode_m = 4;\r
397                 break;\r
398         case 16:\r
399                 mode_m = 5;\r
400                 break;\r
401         case 24:\r
402                 mode_m = 6;\r
403                 break;\r
404         default:\r
405                 mode_m = 0;\r
406                 break;\r
407         }\r
408         return mode_m;\r
409 }\r
410 unsigned int sc8810_ecc_encode(struct sc8810_ecc_param *param)\r
411 {\r
412         u32 reg;\r
413         reg = (param->m_size - 1);\r
414         memcpy((void *)NFC_MBUF_ADDR, param->p_mbuf, param->m_size);\r
415         nfc_reg_write(NFC_ECC_CFG1, reg);       \r
416         reg = 0;\r
417         reg = (ecc_mode_convert(param->mode)) << NFC_ECC_MODE_OFFSET;\r
418         reg |= (param->ecc_pos << NFC_ECC_SP_POS_OFFSET) | ((param->sp_size - 1) << NFC_ECC_SP_SIZE_OFFSET) | ((param->ecc_num -1)<< NFC_ECC_NUM_OFFSET);\r
419         reg |= NFC_ECC_ACTIVE;\r
420         nfc_reg_write(NFC_ECC_CFG0, reg);\r
421         sc8810_nfc_wait_command_finish(NFC_ECC_EVENT);\r
422         memcpy(param->p_sbuf, (u8 *)NFC_SBUF_ADDR,param->sp_size);\r
423         return 0;\r
424 }\r
425 static u32 sc8810_get_decode_sts(void)\r
426 {\r
427         u32 err;\r
428         err = nfc_reg_read(NFC_ECC_STS0);\r
429         err &= 0x1f;\r
430         if(err == 0x1f)\r
431         {\r
432                 return -1;\r
433         }\r
434         return err;\r
435 }\r
436 static u32 sc8810_ecc_decode(struct sc8810_ecc_param *param)\r
437 {\r
438         u32 reg;\r
439         u32 ret = 0;\r
440         s32 size = 0;\r
441         memcpy((void *)NFC_MBUF_ADDR, param->p_mbuf, param->m_size);\r
442         memcpy((void *)NFC_SBUF_ADDR, param->p_sbuf, param->sp_size);\r
443         reg = (param->m_size - 1);\r
444         nfc_reg_write(NFC_ECC_CFG1, reg);       \r
445         reg = 0;\r
446         reg = (ecc_mode_convert(param->mode)) << NFC_ECC_MODE_OFFSET;\r
447         reg |= (param->ecc_pos << NFC_ECC_SP_POS_OFFSET) | ((param->sp_size - 1) << NFC_ECC_SP_SIZE_OFFSET) | ((param->ecc_num -1)<< NFC_ECC_NUM_OFFSET);\r
448         reg |= NFC_ECC_DECODE;\r
449         reg |= NFC_ECC_ACTIVE;\r
450         nfc_reg_write(NFC_ECC_CFG0, reg);\r
451         sc8810_nfc_wait_command_finish(NFC_ECC_EVENT);\r
452         ret = sc8810_get_decode_sts();\r
453         if (ret != 0 && ret != -1) {\r
454         //printk(KERN_INFO "sc8810_ecc_decode sts = %x\n",ret);\r
455         }\r
456         if (ret == -1) {\r
457                 size = param->sp_size;\r
458                 if (size > 0) {\r
459                         while (size--)\r
460                         {\r
461                                 if (param->p_sbuf[size] != 0xff)\r
462                                         break;\r
463                         }\r
464                         if (size < 0)\r
465                         {\r
466                                 size = param->m_size;\r
467                                 if (size > 0)\r
468                                 {\r
469                                         while (size--)\r
470                                         {\r
471                                                 if (param->p_mbuf[size] != 0xff)\r
472                                                         break;\r
473                                         }\r
474                                         if (size < 0) {\r
475                                                 ret = 0;\r
476                                         }\r
477                                 }\r
478                         }\r
479                 }\r
480         }\r
481         if((ret != -1) && (ret != 0))\r
482         {\r
483                 memcpy(param->p_mbuf, (void *)NFC_MBUF_ADDR, param->m_size);\r
484                 memcpy(param->p_sbuf, (void *)NFC_SBUF_ADDR, param->sp_size);   \r
485                 ret = 0;\r
486         }\r
487         return  ret;\r
488 }\r
489 \r
490 #if 0\r
491 static void set_nfc_param(unsigned long nfc_clk)\r
492 {\r
493         u32 value = 0;\r
494         u32 cycles;\r
495         cycles = nand_timing.acs_time / (1000000000 / nfc_clk);\r
496         value |= (cycles << NFC_ACS_OFFSET);\r
497         \r
498         cycles = nand_timing.rwh_time / (1000000000 / nfc_clk);\r
499         value |= (cycles << NFC_RWH_OFFSET);\r
500         \r
501         cycles = nand_timing.rwl_time / (1000000000 / nfc_clk);\r
502         value |= (cycles << NFC_RWL_OFFSET);\r
503         \r
504         cycles = nand_timing.acr_time / (1000000000 / nfc_clk);\r
505         value |= (cycles << NFC_ACR_OFFSET);\r
506         \r
507         cycles = nand_timing.rr_time / (1000000000 / nfc_clk);\r
508         value |= (cycles << NFC_RR_OFFSET);\r
509         \r
510         cycles = nand_timing.ceh_time / (1000000000 / nfc_clk);\r
511         value |= (cycles << NFC_CEH_OFFSET);\r
512         nfc_reg_write(NFC_TIMING, value);\r
513 \r
514 //      local_irq_restore(flags);       \r
515 }\r
516 #endif\r
517 \r
518 #if !defined(CONFIG_NAND_SPL)\r
519 static struct nand_spec_str *get_nand_spec(u8 *nand_id)\r
520 {\r
521     int i = 0;\r
522     while(nand_spec_table[i].mid != 0){\r
523         if (\r
524                 (nand_id[0] == nand_spec_table[i].mid)\r
525                 && (nand_id[1] == nand_spec_table[i].did)\r
526                 && (nand_id[2] == nand_spec_table[i].id3)\r
527                 && (nand_id[3] == nand_spec_table[i].id4)\r
528                 && (nand_id[4] == nand_spec_table[i].id5)\r
529            ){\r
530                 return &nand_spec_table[i];\r
531         }\r
532         i++;\r
533     }\r
534     return (struct nand_spec_str *)0;\r
535 }\r
536 \r
537 #define DELAY_NFC_TO_PAD 9\r
538 #define DELAY_PAD_TO_NFC 6\r
539 #define DELAY_RWL (DELAY_NFC_TO_PAD + DELAY_PAD_TO_NFC)\r
540 \r
541 static void set_nfc_timing(struct sc8810_nand_timing_param *nand_timing, u32 nfc_clk_MHz)\r
542 {\r
543         u32 value = 0;\r
544         u32 cycles;\r
545         cycles = nand_timing->acs_time * nfc_clk_MHz / 1000 + 1;\r
546         value |= ((cycles & 0x1F) << NFC_ACS_OFFSET);\r
547 \r
548         cycles = nand_timing->rwh_time * nfc_clk_MHz / 1000 + 2;\r
549         value |= ((cycles & 0x1F) << NFC_RWH_OFFSET);\r
550 \r
551         cycles = (nand_timing->rwl_time+DELAY_RWL) * nfc_clk_MHz / 1000 + 1;\r
552         value |= ((cycles & 0x3F) << NFC_RWL_OFFSET);\r
553 \r
554         cycles = nand_timing->acr_time * nfc_clk_MHz / 1000 + 1;\r
555         value |= ((cycles & 0x1F) << NFC_ACR_OFFSET);\r
556 \r
557         cycles = nand_timing->rr_time * nfc_clk_MHz / 1000 + 1;\r
558         value |= ((cycles & 0x1F) << NFC_RR_OFFSET);\r
559 \r
560         cycles = nand_timing->ceh_time * nfc_clk_MHz / 1000 + 1;\r
561         value |= ((cycles & 0x3F) << NFC_CEH_OFFSET);\r
562 \r
563         nfc_reg_write(NFC_TIMING, value);\r
564 \r
565     debug("set_nfc_timing NFC_TIMING: %x ", nfc_reg_read(NFC_TIMING));\r
566 }\r
567 #endif\r
568 \r
569 static void sc8810_nand_hw_init(void)\r
570 {\r
571         int ik_cnt = 0;\r
572 \r
573         REG_AHB_CTL0 |= BIT_8;//no BIT_9\r
574         REG_AHB_SOFT_RST |= BIT_5;\r
575         for(ik_cnt = 0; ik_cnt < 0xffff; ik_cnt++);\r
576         REG_AHB_SOFT_RST &= ~BIT_5;\r
577 \r
578         sc8810_nand_wp_en(0);\r
579         //nfc_reg_write(NFC_TIMING, ((6 << 0) | (6 << 5) | (10 << 10) | (6 << 16) | (5 << 21) | (5 << 26)));\r
580         nfc_reg_write(NFC_TIMING, ((12 << 0) | (7 << 5) | (10 << 10) | (6 << 16) | (5 << 21) | (7 << 26)));\r
581         nfc_reg_write(NFC_TIMING+0X4, 0xffffffff);//TIMEOUT\r
582         //set_nfc_param(0);//53MHz\r
583 }\r
584 static void sc8810_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)\r
585 {\r
586         memcpy(buf, g_info.b_pointer + io_wr_port,len);\r
587         g_info.b_pointer += len;\r
588 }\r
589 static void sc8810_nand_write_buf(struct mtd_info *mtd, const uint8_t *buf,\r
590                                    int len)\r
591 {\r
592         memcpy(g_info.b_pointer + io_wr_port, (unsigned char*)buf,len);\r
593         g_info.b_pointer += len;\r
594 }\r
595 static u_char sc8810_nand_read_byte(struct mtd_info *mtd)\r
596 {\r
597         u_char ch;\r
598         ch = io_wr_port[g_info.b_pointer ++];\r
599         return ch;\r
600 }\r
601 static u16 sc8810_nand_read_word(struct mtd_info *mtd)\r
602 {\r
603         u16 ch = 0;\r
604         ch = io_wr_port[g_info.b_pointer ++];\r
605         ch |= io_wr_port[g_info.b_pointer ++] << 8;\r
606         return ch;\r
607 }\r
608 \r
609 static void sc8810_nand_data_add(unsigned int bytes, unsigned int bus_width, unsigned int read)\r
610 {\r
611         unsigned int word;\r
612         unsigned int blk;\r
613         if(!bus_width)\r
614         {\r
615                 blk = bytes >> 8;\r
616                 word = bytes & 0xff;\r
617         }\r
618         else\r
619         {\r
620                 blk = bytes >> 9;\r
621                 word = (bytes & 0x1ff) >> 1;\r
622         }\r
623         if(read)\r
624         {\r
625                 if(blk)\r
626                 {\r
627                         nfc_mcr_inst_add(blk - 1, NF_MC_RBLK_ID);\r
628                 }\r
629                 if(word)\r
630                 {\r
631                         nfc_mcr_inst_add(word - 1, NF_MC_RWORD_ID);\r
632                 }\r
633         }\r
634         else\r
635         {\r
636                 if(blk)\r
637                 {\r
638                         nfc_mcr_inst_add(blk - 1, NF_MC_WBLK_ID);\r
639                 }\r
640                 if(word)\r
641                 {\r
642                         nfc_mcr_inst_add(word - 1, NF_MC_WWORD_ID);\r
643                 }\r
644         }\r
645 }\r
646 \r
647 static void correct_invalid_id(unsigned char *buf)\r
648 {\r
649         unsigned char id[5];\r
650 \r
651         int num = sizeof(nand_id_replace_table) / sizeof(nand_id_replace_table[0]);\r
652         int index;\r
653 \r
654         memcpy(id, (void *)NFC_MBUF_ADDR, 5);\r
655 \r
656         for (index=0; index<num; index++)\r
657         {\r
658                 if (id[0] == nand_id_replace_table[index][0] &&\r
659                         id[1] == nand_id_replace_table[index][1] &&\r
660                         id[2] == nand_id_replace_table[index][2] &&\r
661                         id[3] == nand_id_replace_table[index][3] &&\r
662                         id[4] == nand_id_replace_table[index][4])\r
663                 {\r
664                         break;\r
665                 }\r
666         }\r
667 \r
668         if (index < num)\r
669         {\r
670                 buf[0] = nand_id_replace_table[index][5];\r
671                 buf[1] = nand_id_replace_table[index][6];\r
672                 buf[2] = nand_id_replace_table[index][7];\r
673                 buf[3] = nand_id_replace_table[index][8];\r
674                 buf[4] = nand_id_replace_table[index][9];\r
675 \r
676                 printf("nand id(%02x,%02x,%02x,%02x,%02x) is invalid, correct it by(%02x,%02x,%02x,%02x,%02x)\n",\r
677                         id[0],id[1],id[2],id[3],id[4], buf[0],buf[1],buf[2],buf[3],buf[4]);\r
678         }\r
679         else\r
680         {\r
681                 memcpy(buf, (void *)NFC_MBUF_ADDR, 5);\r
682         }\r
683 }\r
684 \r
685 static void sc8810_nand_hwcontrol(struct mtd_info *mtd, int cmd,\r
686                                    unsigned int ctrl)\r
687 {\r
688         struct nand_chip *chip = (struct nand_chip *)(mtd->priv);\r
689         u32 size = 0;\r
690         if (ctrl & NAND_CLE) {\r
691                 switch (cmd) {\r
692                 case NAND_CMD_RESET:\r
693                         nfc_mcr_inst_init();\r
694                         nfc_mcr_inst_add(cmd, NF_MC_CMD_ID);\r
695                         nfc_mcr_inst_exc();\r
696                         sc8810_nfc_wait_command_finish(NFC_DONE_EVENT);\r
697                         break;\r
698                 case NAND_CMD_STATUS:\r
699                         nfc_mcr_inst_init();\r
700                         //nfc_reg_write(NFC_CMD, 0x80000070);\r
701                         //sc8810_nfc_wait_command_finish(NFC_DONE_EVENT);\r
702                         //memcpy(io_wr_port, (void *)NFC_ID_STS, 1);\r
703                         nfc_mcr_inst_add(0x70, NF_MC_CMD_ID);\r
704                         nfc_mcr_inst_add(0x10, NF_MC_NOP_ID);//add nop clk for twrh timing param\r
705                         nfc_mcr_inst_add(3, NF_MC_RWORD_ID);\r
706                         nfc_mcr_inst_exc_for_id();\r
707                         sc8810_nfc_wait_command_finish(NFC_DONE_EVENT);\r
708                         memcpy(io_wr_port, (void *)NFC_MBUF_ADDR, 1);\r
709                         //printf("read status3  0x%x, 0x%x\r\n", io_wr_port[0], nfc_reg_read(NFC_MBUF_ADDR));\r
710                         break;\r
711                 case NAND_CMD_READID:\r
712                         nfc_mcr_inst_init();\r
713                         nfc_mcr_inst_add(cmd, NF_MC_CMD_ID);\r
714                         nfc_mcr_inst_add(0x00, NF_MC_ADDR_ID);\r
715                         nfc_mcr_inst_add(0x10, NF_MC_NOP_ID);//add nop clk for twrh timing param\r
716                         nfc_mcr_inst_add(7, NF_MC_RWORD_ID);\r
717                         nfc_mcr_inst_exc_for_id();\r
718                         sc8810_nfc_wait_command_finish(NFC_DONE_EVENT);\r
719                         //memcpy(io_wr_port, (void *)NFC_MBUF_ADDR, 5);\r
720                         correct_invalid_id(io_wr_port);\r
721                         break;                                  \r
722                 case NAND_CMD_ERASE1:\r
723                         nfc_mcr_inst_init();\r
724                         nfc_mcr_inst_add(cmd, NF_MC_CMD_ID);\r
725                         break;\r
726                 case NAND_CMD_ERASE2:\r
727                         nfc_mcr_inst_add(cmd, NF_MC_CMD_ID);\r
728                         nfc_mcr_inst_add(0, NF_MC_WAIT_ID);     \r
729                         nfc_mcr_inst_exc();\r
730                         sc8810_nfc_wait_command_finish(NFC_DONE_EVENT);\r
731                         break;  \r
732                 case NAND_CMD_READ0:\r
733                         nfc_mcr_inst_init();\r
734                         nfc_mcr_inst_add(cmd, NF_MC_CMD_ID);\r
735                         break;  \r
736                 case NAND_CMD_READSTART:\r
737                         nfc_mcr_inst_add(cmd, NF_MC_CMD_ID);\r
738                         nfc_mcr_inst_add(0x10, NF_MC_NOP_ID); /* add nop clk */\r
739                         nfc_mcr_inst_add(0, NF_MC_WAIT_ID);                     \r
740                         if((!g_info.addr_array[0]) && (!g_info.addr_array[1]) )//main part\r
741                                 size = mtd->writesize +mtd->oobsize;\r
742                         else\r
743                                 size = mtd->oobsize;\r
744                         sc8810_nand_data_add(size, chip->options & NAND_BUSWIDTH_16, 1);\r
745                         nfc_mcr_inst_exc();\r
746                         sc8810_nfc_wait_command_finish(NFC_DONE_EVENT);\r
747                         memcpy(io_wr_port, (void *)NFC_MBUF_ADDR, size);\r
748                         break;  \r
749                 case NAND_CMD_SEQIN:\r
750                         nfc_mcr_inst_init();\r
751                         nfc_mcr_inst_add(NAND_CMD_SEQIN, NF_MC_CMD_ID);\r
752                         break;  \r
753                 case NAND_CMD_PAGEPROG:\r
754                         memcpy((void *)NFC_MBUF_ADDR, io_wr_port, g_info.b_pointer);\r
755                         nfc_mcr_inst_add(0x10, NF_MC_NOP_ID);//add nop clk for twrh timing param\r
756                         sc8810_nand_data_add(g_info.b_pointer, chip->options & NAND_BUSWIDTH_16, 0);\r
757                         nfc_mcr_inst_add(cmd, NF_MC_CMD_ID);\r
758                         nfc_mcr_inst_add(0, NF_MC_WAIT_ID);\r
759                         nfc_mcr_inst_exc();\r
760                         sc8810_nfc_wait_command_finish(NFC_DONE_EVENT);\r
761                         break;  \r
762                 default :\r
763                 break;                                          \r
764                 }\r
765         }\r
766         else if(ctrl & NAND_ALE) {\r
767                 nfc_mcr_inst_add(cmd & 0xff, NF_MC_ADDR_ID);\r
768         }\r
769 }\r
770 static int sc8810_nand_devready(struct mtd_info *mtd)\r
771 {\r
772         unsigned long value = 0;\r
773 \r
774         value = nfc_reg_read(NFC_CMD);\r
775         if ((value & NFC_CMD_VALID) != 0)       \r
776         {\r
777                 return 0; \r
778         }else{\r
779                 return 1; /* ready */\r
780         }\r
781 }\r
782 \r
783 static void sc8810_nand_select_chip(struct mtd_info *mtd, int chip)\r
784 {\r
785         //struct nand_chip *this = mtd->priv;\r
786         //struct sprd_nand_info *info = this->priv;\r
787 #ifdef CONFIG_NAND_SPL\r
788         mtd->erasesize = mtderasesize;\r
789         mtd->writesize = mtdwritesize;\r
790         mtd->oobsize = mtdoobsize;\r
791 #endif\r
792 }\r
793 \r
794 static int sc8810_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code)\r
795 {\r
796         struct sc8810_ecc_param param;\r
797         struct nand_chip *this = (struct nand_chip *)(mtd->priv);\r
798         param.mode = g_info.ecc_mode;\r
799         param.ecc_num = 1;\r
800         param.sp_size = this->ecc.bytes;\r
801         param.ecc_pos = 0;\r
802         param.m_size = this->ecc.size;\r
803         param.p_mbuf = (u8 *)dat;\r
804         param.p_sbuf = ecc_code;        \r
805         if (sprd_ecc_mode == NAND_ECC_WRITE) {\r
806                 sc8810_ecc_encode(&param);\r
807                 sprd_ecc_mode = NAND_ECC_NONE;\r
808         }       \r
809         return 0;\r
810 }\r
811 static void sc8810_nand_enable_hwecc(struct mtd_info *mtd, int mode)\r
812 {\r
813         sprd_ecc_mode = mode;\r
814 }\r
815 static int sc8810_nand_correct_data(struct mtd_info *mtd, uint8_t *dat,\r
816                                      uint8_t *read_ecc, uint8_t *calc_ecc)\r
817 {\r
818         struct sc8810_ecc_param param;\r
819         struct nand_chip *this = (struct nand_chip *)(mtd->priv);\r
820         int ret = 0;\r
821         param.mode = g_info.ecc_mode;\r
822         param.ecc_num = 1;\r
823         param.sp_size = this->ecc.bytes;\r
824         param.ecc_pos = 0;\r
825         param.m_size = this->ecc.size;\r
826         param.p_mbuf = dat;\r
827         param.p_sbuf = read_ecc;\r
828         ret = sc8810_ecc_decode(&param);\r
829         return ret;     \r
830 }\r
831 \r
832 void nand_spl_hardware_config(struct nand_chip *this, u8 id[5])\r
833 {\r
834         int index;\r
835         int array;\r
836         \r
837         array = sizeof(nand_config_table) / sizeof(struct sc8810_nand_page_oob);\r
838         for (index = 0; index < array; index ++) {\r
839                 if ((nand_config_table[index].m_c == id[0]) && (nand_config_table[index].d_c == id[1]) && (nand_config_table[index].cyc_3 == id[2]) && (nand_config_table[index].cyc_4 == id[3]) && (nand_config_table[index].cyc_5 == id[4]))\r
840                         break;\r
841         }\r
842 \r
843         if (index < array) {\r
844                 this->ecc.size = nand_config_table[index].eccsize;\r
845                 g_info.ecc_mode = nand_config_table[index].eccbit;\r
846                 this->eccbitmode = g_info.ecc_mode;\r
847                 /* 4 bit ecc, per 512 bytes can creat 13 * 4 = 52 bit , 52 / 8 = 7 bytes\r
848                    8 bit ecc, per 512 bytes can creat 13 * 8 = 104 bit , 104 / 8 = 13 bytes, junqiang say use 14 bytes */\r
849                 switch (g_info.ecc_mode) {\r
850                         case 4:\r
851                                 /* 4 bit ecc, per 512 bytes can creat 13 * 4 = 52 bit , 52 / 8 = 7 bytes */\r
852                                 this->ecc.bytes = 7;\r
853                                 if(nand_config_table[index].oobsize == 64)\r
854                                     this->ecc.layout = &_nand_oob_64_4bit;\r
855                                 else\r
856                                     this->ecc.layout = &_nand_oob_128;\r
857                         break;\r
858                         case 8:\r
859                                 /* 8 bit ecc, per 512 bytes can creat 13 * 8 = 104 bit , 104 / 8 = 14 bytes */\r
860                                 this->ecc.bytes = 14;\r
861                                 if (nand_config_table[index].oobsize == 224)\r
862                                         this->ecc.layout = &_nand_oob_224;\r
863                                 else\r
864                                         this->ecc.layout = &_nand_oob_256;\r
865                                 mtdoobsize = nand_config_table[index].oobsize;\r
866                         break;\r
867                 }\r
868         }\r
869 }\r
870 \r
871 #ifndef CONFIG_NAND_SPL\r
872 void nand_hardware_config(struct mtd_info *mtd, struct nand_chip *this, unsigned char id[8])\r
873 {\r
874         int index;\r
875         int array;\r
876         \r
877         /*for (index = 0; index < 5; index ++)\r
878                 printk(" %02x ", id[index]);\r
879         printk("\n");*/\r
880 \r
881         for (index = 0; index < 5; index ++)\r
882                 this->nandid[index] = id[index];\r
883 \r
884         array = sizeof(nand_config_table) / sizeof(nand_config_table[0]);\r
885         for (index = 0; index < array; index ++) {\r
886                 if ((nand_config_table[index].m_c == id[0])\r
887                         && (nand_config_table[index].d_c == id[1])\r
888                         && (nand_config_table[index].cyc_3 == id[2])\r
889                         && (nand_config_table[index].cyc_4 == id[3])\r
890                         && (nand_config_table[index].cyc_5 == id[4])\r
891                     )\r
892                         break;\r
893         }\r
894 \r
895         if (index < array) {\r
896                 this->ecc.size = nand_config_table[index].eccsize;\r
897                 g_info.ecc_mode = nand_config_table[index].eccbit;\r
898                 this->eccbitmode = g_info.ecc_mode;\r
899                 /* 4 bit ecc, per 512 bytes can creat 13 * 4 = 52 bit , 52 / 8 = 7 bytes\r
900                    8 bit ecc, per 512 bytes can creat 13 * 8 = 104 bit , 104 / 8 = 14 bytes */\r
901                 switch (g_info.ecc_mode) {\r
902                         case 4:\r
903                                 /* 4 bit ecc, per 512 bytes can creat 14 * 4 = 56 bit , 56 / 8 = 7 bytes */\r
904                                 this->ecc.bytes = 7;\r
905                                 if(nand_config_table[index].oobsize == 64)\r
906                                     this->ecc.layout = &_nand_oob_64_4bit;\r
907                                 else\r
908                                  this->ecc.layout = &_nand_oob_128;\r
909                         break;\r
910                         case 8:\r
911                                 /* 8 bit ecc, per 512 bytes can creat 13 * 8 = 104 bit , 104 / 8 = 14 bytes */\r
912                                 this->ecc.bytes = 14;\r
913                                 if (nand_config_table[index].oobsize == 224)\r
914                                         this->ecc.layout = &_nand_oob_224;\r
915                                 else\r
916                                         this->ecc.layout = &_nand_oob_256;\r
917                                 mtd->oobsize = nand_config_table[index].oobsize;\r
918                         break;\r
919                 }\r
920                 mtdoobsize = nand_config_table[index].oobsize;\r
921         } else \r
922                 printk("The type of nand flash is 2KB page, so use default configuration!\n");\r
923 }\r
924 #endif\r
925 \r
926 int board_nand_init(struct nand_chip *this)\r
927 {\r
928         int extid;\r
929 \r
930         g_info.chip = this;\r
931         sc8810_nand_hw_init();\r
932         //nfc_reset();\r
933         this->IO_ADDR_R = this->IO_ADDR_W = (void __iomem       *)NFC_MBUF_ADDR;\r
934         this->cmd_ctrl = sc8810_nand_hwcontrol;\r
935         this->dev_ready = sc8810_nand_devready;\r
936         this->select_chip = sc8810_nand_select_chip;\r
937 \r
938         this->ecc.calculate = sc8810_nand_calculate_ecc;\r
939         this->ecc.correct = sc8810_nand_correct_data;\r
940         this->ecc.hwctl = sc8810_nand_enable_hwecc;\r
941         this->ecc.mode = NAND_ECC_HW;\r
942         this->read_buf = sc8810_nand_read_buf;\r
943         this->write_buf = sc8810_nand_write_buf;\r
944         this->read_byte = sc8810_nand_read_byte;\r
945         this->read_word = sc8810_nand_read_word;\r
946 \r
947         read_chip_id();\r
948         /* The 4th id byte is the important one */\r
949 \r
950 #if !defined(CONFIG_NAND_SPL)\r
951         ptr_nand_spec = get_nand_spec(io_wr_port);\r
952 \r
953         if (ptr_nand_spec != NULL)\r
954                 set_nfc_timing(&ptr_nand_spec->timing_cfg, 153);\r
955         else\r
956                 //nfc_reg_write(NFC_TIMING, ((6 << 0) | (6 << 5) | (10 << 10) | (6 << 16) | (5 << 21) | (5 << 26)));\r
957                 nfc_reg_write(NFC_TIMING, ((12 << 0) | (7 << 5) | (10 << 10) | (6 << 16) | (5 << 21) | (7 << 26)));\r
958 #endif\r
959 \r
960         extid = io_wr_port[3];\r
961         /* Calc pagesize */\r
962         mtdwritesize = 1024 << (extid & 0x3);\r
963         extid >>= 2;\r
964         /* Calc oobsize */\r
965         mtdoobsize = (8 << (extid & 0x01)) * (mtdwritesize >> 9);\r
966         extid >>= 2;\r
967         /* Calc blocksize. Blocksize is multiples of 64KiB */\r
968         mtderasesize = (64 * 1024) << (extid & 0x03);\r
969 \r
970         this->ecc.bytes = CONFIG_SYS_NAND_ECCBYTES;\r
971         g_info.ecc_mode = CONFIG_SYS_NAND_ECC_MODE;\r
972         this->eccbitmode = g_info.ecc_mode;\r
973         this->ecc.size = CONFIG_SYS_NAND_ECCSIZE;\r
974 #ifdef CONFIG_NAND_SPL\r
975         if (mtdoobsize == 64)\r
976                 this->ecc.layout = &_nand_oob_64;\r
977         else if (mtdoobsize == 128)\r
978                 this->ecc.layout = &nand_oob_128;\r
979         nand_spl_hardware_config(this, io_wr_port);\r
980 #endif\r
981         this->chip_delay = 20;\r
982         this->priv = &g_info;\r
983         this->options |= NAND_BUSWIDTH_16 | NAND_USE_FLASH_BBT;\r
984         return 0;\r
985 }\r
986 \r
987 #ifndef CONFIG_NAND_SPL\r
988 static unsigned long nfc_read_status(void)\r
989 {\r
990         unsigned long status = 0;\r
991         int i, cmd = NAND_CMD_STATUS;\r
992 \r
993         nfc_mcr_inst_init();\r
994         nfc_reg_write(NFC_CMD, 0x80000070);\r
995         sc8810_nfc_wait_command_finish(NFC_DONE_EVENT);\r
996         memcpy(io_wr_port, (void *)NFC_ID_STS, 1);\r
997         \r
998         status = io_wr_port[0];\r
999         return status;\r
1000 }\r
1001 \r
1002 static int sprd_scan_one_block(int blk, int erasesize, int writesize)\r
1003 {\r
1004         int i, cmd;\r
1005         int status = 1, ii;\r
1006         u32 size = 0;\r
1007         int oobsize = mtdoobsize;\r
1008         int column, page_addr;\r
1009 \r
1010         page_addr = blk * (erasesize / writesize);\r
1011         for (ii = 0; ii < 2; ii ++) {\r
1012                 nfc_mcr_inst_init();\r
1013                 cmd = NAND_CMD_READ0;\r
1014                 nfc_mcr_inst_add(cmd, NF_MC_CMD_ID);\r
1015                 page_addr += ii;\r
1016                 column = writesize;\r
1017                 if (column != -1) {\r
1018                         /* Adjust columns for 16 bit buswidth */\r
1019                         column >>= 1;\r
1020                         nfc_mcr_inst_add(column & 0xff, NF_MC_ADDR_ID);\r
1021                         nfc_mcr_inst_add((column >> 8) & 0xff, NF_MC_ADDR_ID);\r
1022                 }\r
1023                 \r
1024                 if (page_addr != -1) {\r
1025                         nfc_mcr_inst_add(page_addr & 0xff, NF_MC_ADDR_ID);\r
1026                         nfc_mcr_inst_add((page_addr >> 8) & 0xff, NF_MC_ADDR_ID);\r
1027                         /* One more address cycle for devices > 128MiB */\r
1028                         nfc_mcr_inst_add((page_addr >> 16) & 0xff, NF_MC_ADDR_ID);\r
1029                 }\r
1030         \r
1031                 cmd = NAND_CMD_READSTART;\r
1032                 nfc_mcr_inst_add(cmd, NF_MC_CMD_ID);\r
1033                 nfc_mcr_inst_add(0, NF_MC_WAIT_ID);                     \r
1034                         \r
1035                 if((!g_info.addr_array[0]) && (!g_info.addr_array[1]) )\r
1036                         size = writesize + oobsize;//main part\r
1037                 else\r
1038                         size = oobsize;\r
1039                 sc8810_nand_data_add(size, 1, 1);\r
1040 \r
1041                 nfc_mcr_inst_exc();\r
1042                 sc8810_nfc_wait_command_finish(NFC_DONE_EVENT);\r
1043         \r
1044                 memcpy(io_wr_port, (void *)NFC_MBUF_ADDR, size);\r
1045 #if 0\r
1046                 for (i = 0; i < size; i++) {\r
1047                         /*if ((i % 16) == 0)\r
1048                                 printf("\n");*/\r
1049                         printf("io_wr_port[%d] = 0x%02x\n", i, io_wr_port[i]);\r
1050                 }\r
1051 #endif\r
1052                 if ((io_wr_port[0] != 0xff) || (io_wr_port[1] != 0xff))\r
1053                         break;\r
1054         } //for (ii = 0; ii < 2; ii ++)\r
1055 \r
1056         if ((io_wr_port[0] == 0xff) && (io_wr_port[1] == 0xff))\r
1057                 status = 0; //good block\r
1058         else\r
1059                 status = 1; //bad block\r
1060 \r
1061         return status;\r
1062 }\r
1063 \r
1064 static unsigned long nand_ctl_erase_block(int blk, int erasesize, int writesize)\r
1065 {\r
1066         int cmd, status;\r
1067         int page_addr;\r
1068 \r
1069         nfc_mcr_inst_init();\r
1070         cmd = NAND_CMD_ERASE1;\r
1071         nfc_mcr_inst_add(cmd, NF_MC_CMD_ID);\r
1072         page_addr = blk * (erasesize / writesize);\r
1073         if (page_addr != -1) {\r
1074                 nfc_mcr_inst_add(page_addr & 0xff, NF_MC_ADDR_ID);\r
1075                 nfc_mcr_inst_add((page_addr >> 8) & 0xff, NF_MC_ADDR_ID);\r
1076                 /* One more address cycle for devices > 128MiB */\r
1077                 nfc_mcr_inst_add((page_addr >> 16) & 0xff, NF_MC_ADDR_ID);\r
1078         }               \r
1079 \r
1080         cmd = NAND_CMD_ERASE2;\r
1081         nfc_mcr_inst_add(cmd, NF_MC_CMD_ID);\r
1082         nfc_mcr_inst_add(0, NF_MC_WAIT_ID);     \r
1083         nfc_mcr_inst_exc();\r
1084         sc8810_nfc_wait_command_finish(NFC_DONE_EVENT);\r
1085 \r
1086         status = nfc_read_status();\r
1087         return status;\r
1088 }\r
1089 #endif\r
1090 \r
1091 void read_chip_id(void)\r
1092 {\r
1093         int i, cmd = NAND_CMD_READID;\r
1094 \r
1095         nfc_mcr_inst_init();\r
1096         nfc_mcr_inst_add(cmd, NF_MC_CMD_ID);\r
1097         nfc_mcr_inst_add(0x00, NF_MC_ADDR_ID);\r
1098         nfc_mcr_inst_add(0x10, NF_MC_NOP_ID);//add nop clk for twrh timing param\r
1099         nfc_mcr_inst_add(7, NF_MC_RWORD_ID);\r
1100         nfc_mcr_inst_exc_for_id();\r
1101         sc8810_nfc_wait_command_finish(NFC_DONE_EVENT);\r
1102         //memcpy(io_wr_port, (void *)NFC_MBUF_ADDR, 5);\r
1103         correct_invalid_id(io_wr_port);\r
1104 #ifndef CONFIG_NAND_SPL\r
1105         for (i = 0; i < 5; i++)\r
1106                 printf(" %02x ", io_wr_port[i]);\r
1107         printf("\n");\r
1108 #endif\r
1109 }\r
1110 \r
1111 #ifndef CONFIG_NAND_SPL\r
1112 void nand_scan_patition(int blocks, int erasesize, int writesize)\r
1113 {\r
1114         int blk;\r
1115         int ret;\r
1116         int status;\r
1117         \r
1118         //read_chip_id();\r
1119         for (blk = 0; blk < blocks; blk ++) {\r
1120                 ret = sprd_scan_one_block(blk, erasesize, writesize);\r
1121                 if (ret != 0) {\r
1122                         printf("\n%d is bad, scrub to erase it, ", blk);\r
1123                         ret = nand_ctl_erase_block(blk, erasesize, writesize);\r
1124                         printf("0x%02x\n", ret);\r
1125                 } else {\r
1126                         ret = nand_ctl_erase_block(blk, erasesize, writesize);\r
1127                         printf("erasing block : %d    %d % \r", blk, (blk * 100 ) / blocks);\r
1128                 }\r
1129         }\r
1130 }\r
1131 int nand_scan_block(int block, int erasesize, int writesize){\r
1132         int ret = 0;\r
1133         ret = nand_ctl_erase_block(block, erasesize, writesize);\r
1134         ret = ret&1;\r
1135 \r
1136         return ret;\r
1137 }\r
1138 #endif\r