tizen 2.4 release
[kernel/u-boot-tm1.git] / drivers / mtd / nand / sc9630_nand.c
1 /*\r
2  * Copyright (C) 2012 Spreadtrum Communications Inc.\r
3  *\r
4  * This software is licensed under the terms of the GNU General Public\r
5  * License version 2, as published by the Free Software Foundation, and\r
6  * may be copied, distributed, and modified under those terms.\r
7  *\r
8  * This program is distributed in the hope that it will be useful,\r
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
11  * GNU General Public License for more details.\r
12  */\r
13 \r
14 #define DOLPHIN_UBOOT    \r
15 \r
16 #ifdef DOLPHIN_UBOOT\r
17 #include <common.h>\r
18 #include <asm/io.h>\r
19 #include <asm/errno.h>\r
20 #include <config.h>\r
21 \r
22 #include <asm/arch/sci_types.h>\r
23 #include <asm/arch/pinmap.h>\r
24 #include <asm/arch/bits.h>\r
25 \r
26 #include <nand.h>\r
27 #include <linux/mtd/nand.h>\r
28 \r
29 #include <asm/arch-sc9630/sprd_nfc_reg_v2.h>\r
30 //#include <asm/arch/sc8810_reg_base.h>\r
31 #include <asm/arch/regs_ana.h>\r
32 #include <asm/arch/analog_reg_v3.h>\r
33 //#include <asm/arch/sc8810_reg_ahb.h>\r
34 //#include <asm/arch/sc8810_reg_global.h>\r
35 #include <asm/arch/gpio_drvapi.h>\r
36 #include <asm/arch/regs_global.h>\r
37 //#include <asm/arch/regs_cpc.h>\r
38 //#include <asm/arch/pin_reg_v3.h>\r
39 \r
40 #define mdelay(ms) do{ int volatile i = 0; for(i; i < 0xFFFF; i++); } while(0)\r
41 \r
42 //#define NAND_DBG\r
43 #ifdef CONFIG_NAND_SPL\r
44 #define printf(arg...) do{}while(0)\r
45 #endif\r
46 #ifndef NAND_DBG\r
47 #define printf(arg...) do{}while(0)\r
48 #endif\r
49 \r
50 #define DPRINT(arg...) do{}while(0)\r
51 \r
52 /* 2 bit correct, sc8810 support 1, 2, 4, 8, 12,14, 24 */\r
53 #define CONFIG_SYS_NAND_ECC_MODE        2\r
54 //#define CONFIG_SYS_NAND_ECC_MODE      4\r
55 /* Number of ECC bytes per OOB - S3C6400 calculates 4 bytes ECC in 1-bit mode */\r
56 #define CONFIG_SYS_NAND_ECCBYTES        4\r
57 //#define CONFIG_SYS_NAND_ECCBYTES      7\r
58 /* Size of the block protected by one OOB (Spare Area in Samsung terminology) */\r
59 #define CONFIG_SYS_NAND_ECCSIZE 512\r
60 #define CONFIG_SYS_NAND_5_ADDR_CYCLE    5\r
61 \r
62 #define NFC_MC_ICMD_ID  (0xCD)\r
63 #define NFC_MC_ADDR_ID  (0x0A)\r
64 #define NFC_MC_WRB0_ID  (0xB0)\r
65 #define NFC_MC_WRB1_ID  (0xB1)\r
66 #define NFC_MC_MRDT_ID  (0xD0)\r
67 #define NFC_MC_MWDT_ID  (0xD1)\r
68 #define NFC_MC_SRDT_ID  (0xD2)\r
69 #define NFC_MC_SWDT_ID  (0xD3)\r
70 #define NFC_MC_IDST_ID  (0xDD)\r
71 #define NFC_MC_CSEN_ID  (0xCE)\r
72 #define NFC_MC_NOP_ID   (0xF0)\r
73 #define NFC_MC_DONE_ID  (0xFF)\r
74 #define NFC_MAX_CHIP    1\r
75 #define NFC_TIMEOUT_VAL         0x1000000\r
76 \r
77 #define NAND_MC_CMD(x)  (uint16_t)(((x & 0xff) << 8) | NFC_MC_ICMD_ID)\r
78 #define NAND_MC_ADDR(x) (uint16_t)(((x & 0xff) << 8) | (NFC_MC_ADDR_ID << 4))\r
79 #define NAND_MC_WRB0(x) (uint16_t)(NFC_MC_WRB0_ID)\r
80 #define NAND_MC_MRDT    (uint16_t)(NFC_MC_MRDT_ID)\r
81 #define NAND_MC_MWDT    (uint16_t)(NFC_MC_MWDT_ID)\r
82 #define NAND_MC_SRDT    (uint16_t)(NFC_MC_SRDT_ID)\r
83 #define NAND_MC_SWDT    (uint16_t)(NFC_MC_SWDT_ID)\r
84 #define NAND_MC_IDST(x) (uint16_t)((NFC_MC_IDST_ID) | ((x -1) << 8))\r
85 #define NAND_MC_NOP(x)  (uint16_t)(((x & 0xff) << 8) | NFC_MC_NOP_ID)\r
86 \r
87 \r
88 #define NAND_MC_BUFFER_SIZE (24)\r
89 \r
90 static int mtderasesize = 0;\r
91 static int mtdwritesize = 0;\r
92 static int mtdoobsize = 0;\r
93 \r
94 #endif  //DOLPHIN_UBOOT end\r
95 \r
96 \r
97 #ifdef DOLPHIN_KERNEL\r
98 #include <linux/kernel.h>\r
99 #include <linux/module.h>\r
100 #include <linux/interrupt.h>\r
101 #include <linux/dma-mapping.h>\r
102 #include <linux/platform_device.h>\r
103 #include <linux/delay.h>\r
104 #include <linux/mtd/mtd.h>\r
105 #include <linux/mtd/nand.h>\r
106 #include <linux/mtd/partitions.h>\r
107 #include <linux/io.h>\r
108 #include <linux/irq.h>\r
109 #include <linux/slab.h>\r
110 #include <linux/spinlock.h>\r
111 #include <mach/globalregs.h>\r
112 #include "sc9630_nand.h"\r
113 #include <mach/pinmap.h>\r
114 \r
115 #define DPRINT(arg...) do{}while(0)\r
116 #endif  //DOLPHIN_KERNEL\r
117 \r
118 \r
119 struct sprd_dolphin_nand_param {\r
120         uint8_t id[5];\r
121         uint8_t bus_width;\r
122         uint8_t a_cycles;\r
123         uint8_t sct_pg; //sector per page\r
124         uint8_t oob_size; /* oob size per sector*/\r
125         uint8_t ecc_pos; /* oob size per sector*/\r
126         uint8_t info_pos; /* oob size per sector*/\r
127         uint8_t info_size; /* oob size per sector*/\r
128         uint8_t eccbit; /* ecc level per eccsize */\r
129         uint16_t eccsize; /*bytes per sector for ecc calcuate once time */\r
130         uint8_t ace_ns; /* ALE, CLE end of delay timing, unit: ns */\r
131         uint8_t rwl_ns; /* WE, RE, IO, pulse  timing, unit: ns */\r
132         uint8_t rwh_ns; /* WE, RE, IO, high hold  timing, unit: ns */\r
133 };\r
134 \r
135 struct sprd_dolphin_nand_info {\r
136         struct mtd_info *mtd;\r
137         struct nand_chip *nand;\r
138 \r
139         #ifdef DOLPHIN_UBOOT\r
140         struct device *pdev;\r
141         #endif\r
142 \r
143         #ifdef DOLPHIN_KERNEL\r
144         struct platform_device *pdev;\r
145         #endif\r
146 \r
147         struct sprd_dolphin_nand_param *param;\r
148         uint32_t chip; //chip index\r
149         uint32_t v_mbuf; //virtual main buffer address\r
150         uint32_t p_mbuf; //phy main buffer address\r
151         uint32_t v_oob; // virtual oob buffer address\r
152         uint32_t p_oob; //phy oob buffer address\r
153         uint32_t page; //page address\r
154         uint16_t column; //column address\r
155         uint16_t oob_size;\r
156         uint16_t m_size; //main part size per sector\r
157         uint16_t s_size; //oob size per sector\r
158         uint8_t a_cycles;//address cycles, 3, 4, 5\r
159         uint8_t sct_pg; //sector per page\r
160         uint8_t info_pos;\r
161         uint8_t info_size;\r
162         uint8_t ecc_mode;//0-1bit, 1-2bit, 2-4bit, 3-8bit,4-12bit,5-16bit,6-24bit\r
163         uint8_t ecc_pos; // ecc postion\r
164         uint8_t wp_en; //write protect enable\r
165         uint16_t write_size;\r
166         uint16_t page_per_bl;//page per block\r
167         uint16_t  buf_head;\r
168         uint16_t _buf_tail;\r
169         uint8_t ins_num;//instruction number\r
170         uint32_t ins[NAND_MC_BUFFER_SIZE >> 1]; \r
171 };\r
172 \r
173 \r
174 #define mtd_to_dolphin(m) (&g_dolphin)\r
175 \r
176 //gloable variable \r
177 static struct nand_ecclayout sprd_dolphin_nand_oob_default = {\r
178         .eccbytes = 0,\r
179         .eccpos = {0},\r
180         .oobfree = {\r
181                 {.offset = 2,\r
182                  .length = 46}}\r
183 };\r
184 struct sprd_dolphin_nand_info g_dolphin = {0};\r
185 //save the data read by read_byte and read_word api interface functon\r
186 static __attribute__((aligned(4))) uint8_t s_oob_data[NAND_MAX_OOBSIZE];\r
187 //static __attribute__((aligned(4))) uint8_t s_oob_data[8];\r
188 //static __attribute__((aligned(4))) uint8_t s_id_status[8];\r
189 \r
190 static void sprd_dolphin_nand_read_id(struct sprd_dolphin_nand_info *dolphin, uint32_t *buf);\r
191 static void sprd_dolphin_nand_reset(struct sprd_dolphin_nand_info *dolphin);\r
192 static int sprd_dolphin_nand_wait_finish(struct sprd_dolphin_nand_info *dolphin); \r
193 \r
194 static uint32_t sprd_dolphin_reg_read(uint32_t addr)\r
195 {\r
196         return readl(addr);\r
197 }\r
198 static void sprd_dolphin_reg_write(uint32_t addr, uint32_t val)\r
199 {\r
200         writel(val, addr);\r
201 }\r
202 static void sprd_dolphin_reg_or(uint32_t addr, uint32_t val)\r
203 {\r
204         sprd_dolphin_reg_write(addr, sprd_dolphin_reg_read(addr) | val);\r
205 }\r
206 static void sprd_dolphin_reg_and(uint32_t addr, uint32_t mask)\r
207 {\r
208         sprd_dolphin_reg_write(addr, sprd_dolphin_reg_read(addr) & mask);\r
209 }\r
210 static void sprd_dolphin_nand_int_clr(uint32_t bit_clear)\r
211 {\r
212         sprd_dolphin_reg_write(NFC_INT_REG, bit_clear);\r
213 }\r
214 unsigned int ecc_mode_convert(uint32_t mode)\r
215 {\r
216         uint32_t mode_m;\r
217         switch(mode)\r
218         {\r
219         case 1:\r
220                 mode_m = 0;\r
221                 break;\r
222         case 2:\r
223                 mode_m = 1;\r
224                 break;\r
225         case 4:\r
226                 mode_m = 2;\r
227                 break;\r
228         case 8:\r
229                 mode_m = 3;\r
230                 break;\r
231         case 12:\r
232                 mode_m = 4;\r
233                 break;\r
234         case 16:\r
235                 mode_m = 5;\r
236                 break;\r
237         case 24:\r
238                 mode_m = 6;\r
239                 break;\r
240         case 40:\r
241                 mode_m = 7;\r
242                 break;\r
243         case 60:\r
244                 mode_m = 8;\r
245                 break;\r
246         default:\r
247                 mode_m = 0;\r
248                 break;\r
249         }\r
250         return mode_m;\r
251 }\r
252 \r
253 /*spare info must be align to ecc pos, info_pos + info_size = ecc_pos, \r
254  *the hardware must be config info_size and info_pos when ecc enable,and the ecc_info size can't be zero,\r
255  *to simplify the nand_param_tb, the info is align with ecc and ecc at the last postion in one sector\r
256 */\r
257 static struct sprd_dolphin_nand_param sprd_dolphin_nand_param_tb[] = {\r
258         {{0xec, 0xbc, 0x00,0x55, 0x54},         1,      5,      4,      16,     12,     11,     1,      2,      512, 5, 21, 10},\r
259         {{0xec, 0xbc, 0x00,0x6A, 0x56},         1,      5,      8,      16,     12,     11,     1,      2,      512, 10, 25, 15},\r
260         //{{0xec, 0xbc, 0x00,0x6A, 0x56},       1,      5,      8,      16,     12,     11,     1,      2,      512, 5, 21, 10},\r
261         //{{0xec, 0xbc, 0x00,0x6A, 0x56},       1,      5,      8,      8,              4,              3,              1,      2,      512, 5, 21, 10},\r
262         {{0xad, 0xbc, 0x90,0x55, 0x54},         1,      5,      4,      16,     12,     11,     1,      2,      512, 10, 25, 15},\r
263         {{0x2c, 0xbc, 0x90,0x66, 0x54},         1,      5,      8,      16,     12,     11,     1,      2,      512, 10, 25, 15},\r
264 };\r
265 \r
266 \r
267 \r
268 #ifdef CONFIG_NAND_SPL\r
269 struct sprd_dolphin_boot_header_info {\r
270         uint32_t check_sum;\r
271         uint32_t sct_size; //\r
272         uint32_t acycle; // 3, 4, 5\r
273         uint32_t bus_width; //0 ,1\r
274         uint32_t spare_size; //spare part sise for one sector\r
275         uint32_t ecc_mode; //0--1bit, 1--2bit,2--4bit,3--8bit,4--12bit, 5--16bit, 6--24bit\r
276         uint32_t ecc_pos; // ecc postion at spare part\r
277         uint32_t sct_per_page; //sector per page\r
278         uint32_t info_pos;\r
279         uint32_t info_size;\r
280         uint32_t magic_num; //0xaa55a5a5        \r
281         uint32_t ecc_value[27];\r
282 };\r
283 void boad_nand_param_init(struct sprd_dolphin_nand_info *dolphin, struct nand_chip *chip, uint8 *id)\r
284 {\r
285         int extid;\r
286         uint32_t writesize;\r
287         uint32_t oobsize;\r
288         uint32_t erasesize;\r
289         uint32_t busw;\r
290         \r
291         /* The 4th id byte is the important one */\r
292         extid = id[3];\r
293         writesize = 1024 << (extid & 0x3);\r
294         extid >>= 2;\r
295         /* Calc oobsize */\r
296         oobsize = (8 << (extid & 0x01)) * (writesize >> 9);\r
297         extid >>= 2;\r
298         /* Calc blocksize. Blocksize is multiples of 64KiB */\r
299         erasesize = (64 * 1024) << (extid & 0x03);\r
300         extid >>= 2;\r
301         /* Get buswidth information */\r
302         busw = (extid & 0x01) ? NAND_BUSWIDTH_16 : 0;\r
303         dolphin->write_size = writesize;\r
304         dolphin->m_size =CONFIG_SYS_NAND_ECCSIZE;\r
305         dolphin->sct_pg = writesize / CONFIG_SYS_NAND_ECCSIZE;\r
306         dolphin->s_size = oobsize / dolphin->sct_pg;\r
307         dolphin->ecc_mode = ecc_mode_convert(CONFIG_SYS_NAND_ECC_MODE);\r
308         dolphin->ecc_pos = dolphin->s_size - ((14 * CONFIG_SYS_NAND_ECC_MODE + 7) / 8);\r
309         dolphin->info_pos = dolphin->ecc_pos - 1;\r
310         dolphin->info_size = 1;\r
311         dolphin->page_per_bl = erasesize / dolphin->write_size;\r
312         dolphin->a_cycles = CONFIG_SYS_NAND_5_ADDR_CYCLE;\r
313         if(NAND_BUSWIDTH_16 == busw)\r
314         {\r
315                 chip->options |= NAND_BUSWIDTH_16;\r
316         }\r
317         else\r
318         {\r
319                 chip->options &= ~NAND_BUSWIDTH_16;\r
320         }\r
321 }\r
322 \r
323 /*\r
324  * because the dolphin firmware use the nand identify process\r
325  * and the data at the header of nand_spl is the nand param used at nand read and write,\r
326  * so in nand_spl, don't need read the id or use the onfi spec to calculate the nand param,\r
327  * just use the param at the nand_spl header instead of\r
328  */\r
329 void nand_hardware_config(struct mtd_info *mtd,struct nand_chip *chip)\r
330 {\r
331         struct sprd_dolphin_nand_info *dolphin = mtd_to_dolphin(mtd);\r
332         struct sprd_dolphin_boot_header_info *header;\r
333         int index;\r
334         int array;\r
335         struct sprd_dolphin_nand_param * param;\r
336         uint8 *id;\r
337         sprd_dolphin_nand_reset(dolphin);\r
338         sprd_dolphin_nand_read_id(dolphin, (uint32_t *)s_oob_data);\r
339         boad_nand_param_init(dolphin, dolphin->nand, s_oob_data);\r
340         id = s_oob_data;\r
341         array = ARRAY_SIZE(sprd_dolphin_nand_param_tb);\r
342 \r
343         for (index = 0; index < array; index ++) {\r
344                 param = sprd_dolphin_nand_param_tb + index;\r
345                 if ((param->id[0] == id[0]) \r
346                         && (param->id[1] == id[1]) \r
347                         && (param->id[2] == id[2]) \r
348                         && (param->id[3] == id[3]) \r
349                         && (param->id[4] == id[4]))\r
350                         break;\r
351         }\r
352         if (index < array) {\r
353                 dolphin->ecc_mode = ecc_mode_convert(param->eccbit);\r
354                 dolphin->m_size = param->eccsize;\r
355                 dolphin->s_size = param->oob_size;\r
356                 dolphin->a_cycles = param->a_cycles;\r
357                 dolphin->sct_pg = param->sct_pg;\r
358                 dolphin->info_pos = param->info_pos;\r
359                 dolphin->info_size = param->info_size;\r
360                 dolphin->write_size = dolphin->m_size * dolphin->sct_pg;\r
361                 dolphin->ecc_pos = param->ecc_pos;\r
362                 if(param->bus_width)\r
363                 {\r
364                         chip->options |= NAND_BUSWIDTH_16;\r
365                 }\r
366                 else\r
367                 {\r
368                         chip->options &= ~NAND_BUSWIDTH_16;\r
369                 }\r
370                 mtd->writesize = dolphin->write_size;\r
371                 mtd->oobsize = dolphin->s_size * dolphin->sct_pg;\r
372                 dolphin->nand=chip;\r
373         }\r
374         mtd->writesize = dolphin->write_size;\r
375         mtd->oobsize = dolphin->s_size * dolphin->sct_pg;\r
376         mtd->erasesize = dolphin->page_per_bl * dolphin->write_size;\r
377 }\r
378 #else \r
379 \r
380 static void sprd_dolphin_nand_ecc_layout_gen(struct sprd_dolphin_nand_info *dolphin, struct sprd_dolphin_nand_param *param, struct nand_ecclayout *layout)\r
381 {\r
382         uint32_t sct = 0;\r
383         uint32_t i = 0;\r
384         uint32_t offset;\r
385         uint32_t used_len ; //one sector ecc data size(byte)\r
386         uint32_t eccbytes = 0; //one page ecc data size(byte)\r
387         uint32_t oobfree_len = 0;\r
388         used_len = (14 * param->eccbit + 7) / 8 + param->info_size;\r
389         if(param->sct_pg > ARRAY_SIZE(layout->oobfree))\r
390         {\r
391                 while(1);\r
392         }\r
393         for(sct = 0; sct < param->sct_pg; sct++)\r
394         {\r
395                 //offset = (oob_size * sct) + ecc_pos;\r
396                 //for(i = 0; i < ecc_len; i++)\r
397                 offset = (param->oob_size * sct) + param->info_pos;\r
398                 for(i = 0; i < used_len; i++)\r
399                 {\r
400                         layout->eccpos[eccbytes++] = offset + i;\r
401                 }\r
402                 layout->oobfree[sct].offset = param->oob_size * sct + param->info_pos;\r
403                 layout->oobfree[sct].length = param->info_size ;\r
404                 oobfree_len += param->info_size;\r
405         }\r
406         \r
407         layout->oobavail = oobfree_len;\r
408         layout->eccbytes = used_len * param->sct_pg;\r
409 }\r
410 \r
411 void nand_hardware_config(struct mtd_info *mtd, struct nand_chip *chip, u8 id[5])\r
412 {\r
413         int index;\r
414         int array;\r
415         struct sprd_dolphin_nand_param * param;\r
416         struct sprd_dolphin_nand_info *dolphin = mtd_to_dolphin(mtd);\r
417         \r
418         array = ARRAY_SIZE(sprd_dolphin_nand_param_tb);\r
419         for (index = 0; index < array; index ++) {\r
420                 param = sprd_dolphin_nand_param_tb + index;\r
421                 if ((param->id[0] == id[0]) \r
422                         && (param->id[1] == id[1]) \r
423                         && (param->id[2] == id[2]) \r
424                         && (param->id[3] == id[3]) \r
425                         && (param->id[4] == id[4]))\r
426                         break;\r
427         }\r
428         if (index < array) {\r
429                 //save the param config\r
430                 dolphin->ecc_mode = ecc_mode_convert(param->eccbit);\r
431                 dolphin->m_size = param->eccsize;\r
432                 dolphin->s_size = param->oob_size;\r
433                 dolphin->a_cycles = param->a_cycles;\r
434                 dolphin->sct_pg = param->sct_pg;\r
435                 dolphin->info_pos = param->info_pos;\r
436                 dolphin->info_size = param->info_size;\r
437                 dolphin->write_size = dolphin->m_size * dolphin->sct_pg;\r
438                 dolphin->ecc_pos = param->ecc_pos;\r
439                 chip->eccbitmode = param->eccbit;\r
440                 chip->ecc.bytes  = (param->eccbit*14+7)/8;\r
441                 //dolphin->bus_width = param->bus_width;\r
442                 if(param->bus_width)\r
443                 {\r
444                         chip->options |= NAND_BUSWIDTH_16;\r
445                 }\r
446                 else\r
447                 {\r
448                         chip->options &= ~NAND_BUSWIDTH_16;\r
449                 }\r
450                 dolphin->param = param;\r
451                 //update the mtd and nand default param after nand scan\r
452                 mtd->writesize = dolphin->write_size;\r
453                 mtd->oobsize = dolphin->s_size * dolphin->sct_pg;\r
454                 dolphin->oob_size = mtd->oobsize;\r
455                 /* Calculate the address shift from the page size */\r
456                 chip->page_shift = ffs(mtd->writesize) - 1;\r
457                 /* Convert chipsize to number of pages per chip -1. */\r
458                 chip->pagemask = (chip->chipsize >> chip->page_shift) - 1;\r
459                 sprd_dolphin_nand_ecc_layout_gen(dolphin, param, &sprd_dolphin_nand_oob_default);\r
460                 chip->ecc.layout = &sprd_dolphin_nand_oob_default;\r
461                 dolphin->mtd = mtd;\r
462         }\r
463         else {\r
464                 int steps;\r
465                 struct sprd_dolphin_nand_param  param1;\r
466                 \r
467                 //save the param config\r
468                 steps = mtd->writesize / CONFIG_SYS_NAND_ECCSIZE;\r
469                 dolphin->ecc_mode = ecc_mode_convert(CONFIG_SYS_NAND_ECC_MODE);\r
470                 dolphin->m_size = CONFIG_SYS_NAND_ECCSIZE;\r
471                 dolphin->s_size = mtd->oobsize / steps;\r
472                 dolphin->a_cycles = mtd->writesize / CONFIG_SYS_NAND_ECCSIZE;\r
473                 dolphin->sct_pg = steps;\r
474                 dolphin->info_pos = dolphin->s_size - CONFIG_SYS_NAND_ECCBYTES - 1;\r
475                 dolphin->info_size = 1;\r
476                 dolphin->write_size = mtd->writesize;\r
477                 dolphin->oob_size = mtd->oobsize;\r
478                 dolphin->ecc_pos = dolphin->s_size - CONFIG_SYS_NAND_ECCBYTES;\r
479                 param1.sct_pg = dolphin->sct_pg;\r
480                 param1.info_pos = dolphin->info_pos;\r
481                 param1.info_size = dolphin->info_size;\r
482                 param1.oob_size = dolphin->s_size;\r
483                 param1.eccbit = CONFIG_SYS_NAND_ECC_MODE;\r
484                 param1.eccsize = dolphin->s_size;\r
485 \r
486                 chip->eccbitmode = CONFIG_SYS_NAND_ECC_MODE;\r
487                 chip->ecc.bytes  = (CONFIG_SYS_NAND_ECC_MODE * 14 + 7) / 8;\r
488                 //printf("hardware default eccbitmode %d\n", chip->eccbitmode);\r
489                 \r
490                 if(chip->chipsize > (128 << 20)) {\r
491                         dolphin->a_cycles = 5;\r
492                 }\r
493                 else {\r
494                         dolphin->a_cycles = 4;\r
495                 }\r
496 \r
497                 sprd_dolphin_nand_ecc_layout_gen(dolphin, &param1, &sprd_dolphin_nand_oob_default);\r
498                 chip->ecc.layout = &sprd_dolphin_nand_oob_default;\r
499                 dolphin->mtd = mtd;\r
500         }\r
501         dolphin->mtd = mtd;\r
502 }\r
503 #endif  //end CONFIG_NAND_SPL\r
504 \r
505 \r
506 \r
507 #ifdef DOLPHIN_UBOOT\r
508 #ifndef CONFIG_NAND_SPL\r
509 typedef struct {\r
510         uint8_t *m_buf;\r
511         uint8_t *s_buf;\r
512         uint8_t m_sct;\r
513         uint8_t s_sct;\r
514         uint8_t dir; //if dir is 0, read dadta from NFC buffer, if 1, write data to NFC buffer\r
515         uint16_t m_size;\r
516         uint16_t s_size;\r
517 } sprd_dolphin_nand_data_param;\r
518 \r
519 static unsigned int sprd_dolphin_data_trans(sprd_dolphin_nand_data_param *param)\r
520 {\r
521         uint32_t cfg0 = 0;\r
522         uint32_t cfg1 = 0;\r
523         uint32_t cfg2 = 0;\r
524         cfg0 = NFC_ONLY_MST_MODE | MAIN_SPAR_APT | NFC_WPN;\r
525         if(param->dir)\r
526         {\r
527                 cfg0 |= NFC_RW;\r
528         }\r
529         if(param->m_sct != 0)\r
530         {\r
531                 cfg0 |= (param->m_sct - 1) << SECTOR_NUM_OFFSET;\r
532                 cfg0 |= MAIN_USE;\r
533                 cfg1 |= (param->m_size - 1);\r
534                 sprd_dolphin_reg_write(NFC_MAIN_ADDR_REG, (uint32_t)param->m_buf);\r
535         }\r
536         if(param->s_sct != 0)\r
537         {\r
538                 cfg0 |= SPAR_USE;\r
539                 cfg1 |= (param->s_size - 1) << SPAR_SIZE_OFFSET;\r
540                 cfg2 |= (param->s_sct - 1) << SPAR_SECTOR_NUM_OFFSET;\r
541                 sprd_dolphin_reg_write(NFC_SPAR_ADDR_REG, (uint32_t)param->s_buf);\r
542         }\r
543         sprd_dolphin_reg_write(NFC_CFG0_REG, cfg0);\r
544         sprd_dolphin_reg_write(NFC_CFG1_REG, cfg1);\r
545         sprd_dolphin_reg_write(NFC_CFG2_REG, cfg2);\r
546         sprd_dolphin_nand_int_clr(INT_STSMCH_CLR | INT_WP_CLR | INT_TO_CLR | INT_DONE_CLR);//clear all interrupt\r
547         sprd_dolphin_reg_write(NFC_START_REG, NFC_START);\r
548         sprd_dolphin_nand_wait_finish(&g_dolphin);\r
549         return 0;\r
550 }\r
551 void sprd_ecc_ctrl(struct sprd_ecc_param *param, uint32_t dir)\r
552 {\r
553         uint32_t cfg0 = 0;\r
554         uint32_t cfg1 = 0;\r
555         uint32_t cfg2 = 0;\r
556         cfg0 = NFC_ONLY_ECC_MODE | MAIN_SPAR_APT;\r
557         if(dir)\r
558         {\r
559                 cfg0 |= NFC_RW;\r
560         }\r
561         cfg1 |=(param->sinfo_size - 1) << SPAR_INFO_SIZE_OFFSET;\r
562         cfg1 |=(param->sp_size - 1) << SPAR_SIZE_OFFSET;\r
563         cfg1 |= (param->m_size - 1);\r
564         \r
565         cfg2 |= (param->sinfo_pos)<< SPAR_INFO_POS_OFFSET;\r
566         cfg2 |= ecc_mode_convert(param->mode) << ECC_MODE_OFFSET;\r
567         cfg2 |= param->ecc_pos;\r
568         sprd_dolphin_reg_write(NFC_CFG0_REG, cfg0);\r
569         sprd_dolphin_reg_write(NFC_CFG1_REG, cfg1);\r
570         sprd_dolphin_reg_write(NFC_CFG2_REG, cfg2);\r
571         sprd_dolphin_nand_int_clr(INT_STSMCH_CLR | INT_WP_CLR | INT_TO_CLR | INT_DONE_CLR);//clear all interrupt\r
572         sprd_dolphin_reg_write(NFC_START_REG, NFC_START);\r
573         sprd_dolphin_nand_wait_finish(&g_dolphin);\r
574 }\r
575 \r
576 unsigned int sprd_ecc_encode(struct sprd_ecc_param *param)\r
577 {\r
578         struct sprd_dolphin_nand_info *dolphin;\r
579         sprd_dolphin_nand_data_param d_param;\r
580 \r
581         dolphin = &g_dolphin;\r
582         memset(&d_param, 0, sizeof(d_param));\r
583 \r
584         d_param.m_buf = param->p_mbuf;\r
585         d_param.s_buf = param->p_sbuf;\r
586         d_param.m_sct = param->ecc_num;\r
587         d_param.s_sct = param->ecc_num;\r
588         d_param.dir = 1;\r
589         d_param.m_size = param->m_size;\r
590         d_param.s_size = param->sp_size;\r
591 \r
592         Dcache_CleanRegion((unsigned int)d_param.m_buf, d_param.m_sct*d_param.m_size);\r
593         Dcache_CleanRegion((unsigned int)d_param.s_buf, d_param.s_sct*d_param.s_size);\r
594 \r
595         sprd_dolphin_data_trans(&d_param);\r
596         sprd_ecc_ctrl(param, 1);\r
597         d_param.dir = 0;\r
598         d_param.m_sct = 0;\r
599 \r
600         Dcache_InvalRegion((unsigned int)d_param.m_buf , d_param.m_sct*d_param.m_size);\r
601         Dcache_InvalRegion((unsigned int)d_param.s_buf , d_param.s_sct*d_param.s_size);\r
602 \r
603         sprd_dolphin_data_trans(&d_param); //read the ecc value from nfc buffer\r
604         return 0;\r
605 }\r
606 #endif  //CONFIG_NAND_SPL end\r
607 #endif  //DOLPHIN_UBOOT END\r
608 \r
609 \r
610 \r
611 //add one macro instruction to nand controller\r
612 /*static */void sprd_dolphin_nand_ins_init(struct sprd_dolphin_nand_info *dolphin)\r
613 {\r
614         dolphin->ins_num = 0;\r
615 }\r
616 /*static */void sprd_dolphin_nand_ins_add(uint16_t ins, struct sprd_dolphin_nand_info *dolphin)\r
617 {\r
618         uint16_t *buf = (uint16_t *)dolphin->ins;\r
619         if(dolphin->ins_num >= NAND_MC_BUFFER_SIZE)\r
620         {\r
621                 while(1);\r
622         }\r
623         *(buf + dolphin->ins_num) = ins;\r
624         dolphin->ins_num++;\r
625 }\r
626 \r
627 static void sprd_dolphin_nand_ins_exec(struct sprd_dolphin_nand_info *dolphin)\r
628 {\r
629         uint32_t i;\r
630         uint32_t cfg0;\r
631         \r
632         for(i = 0; i < ((dolphin->ins_num + 1) >> 1); i++)\r
633         {\r
634                 sprd_dolphin_reg_write(NFC_INST0_REG + (i << 2), dolphin->ins[i]);\r
635         }\r
636         cfg0 = sprd_dolphin_reg_read(NFC_CFG0_REG);\r
637         if(dolphin->wp_en)\r
638         {\r
639                 cfg0 &= ~NFC_WPN;\r
640         }\r
641         else\r
642         {\r
643                 cfg0 |= NFC_WPN;\r
644         }\r
645         if(dolphin->chip)\r
646         {\r
647                 cfg0 |= CS_SEL;\r
648         }\r
649         else\r
650         {\r
651                 cfg0 &= ~CS_SEL;\r
652         }\r
653         sprd_dolphin_nand_int_clr(INT_STSMCH_CLR | INT_WP_CLR | INT_TO_CLR | INT_DONE_CLR);//clear all interrupt\r
654         sprd_dolphin_reg_write(NFC_CFG0_REG, cfg0);\r
655         sprd_dolphin_reg_write(NFC_START_REG, NFC_START);\r
656 }\r
657 static int sprd_dolphin_nand_wait_finish(struct sprd_dolphin_nand_info *dolphin)\r
658 {\r
659         unsigned int value;\r
660         unsigned int counter = 0;\r
661         while((counter < NFC_TIMEOUT_VAL/*time out*/))\r
662         {\r
663                 value = sprd_dolphin_reg_read(NFC_INT_REG);\r
664                 if(value & INT_DONE_RAW)\r
665                 {\r
666                         break;\r
667                 }\r
668                 counter ++;\r
669         }\r
670         sprd_dolphin_reg_write(NFC_INT_REG, 0xf00); //clear all interrupt status\r
671         if(counter > NFC_TIMEOUT_VAL)\r
672         {\r
673                 while (1);\r
674                 return -1;\r
675         }\r
676         return 0;\r
677 }\r
678 static void sprd_dolphin_nand_wp_en(struct sprd_dolphin_nand_info *dolphin, int en)\r
679 {\r
680         if(en)\r
681         {\r
682                 dolphin->wp_en = 1;\r
683         }\r
684         else\r
685         {\r
686                 dolphin->wp_en = 0;\r
687         }\r
688 }\r
689 static void sprd_dolphin_select_chip(struct mtd_info *mtd, int chip)\r
690 {\r
691         struct sprd_dolphin_nand_info *dolphin = mtd_to_dolphin(mtd);\r
692         if(chip < 0) { //for release caller\r
693                 return;\r
694         }\r
695         //DPRINT("sprd_dolphin_select_chip, %x\r\n", chip);\r
696         dolphin->chip = chip;\r
697 #ifdef CONFIG_NAND_SPL\r
698         nand_hardware_config(mtd,dolphin->nand);\r
699 #endif\r
700 }\r
701 static void sprd_dolphin_nand_read_status(struct sprd_dolphin_nand_info *dolphin)\r
702 {\r
703         uint32_t *buf;\r
704         //DPRINT("sprd_dolphin_nand_read_status\r\n");\r
705         sprd_dolphin_nand_ins_init(dolphin);\r
706         sprd_dolphin_nand_ins_add(NAND_MC_CMD(NAND_CMD_STATUS), dolphin);\r
707         sprd_dolphin_nand_ins_add(NAND_MC_NOP(10), dolphin);\r
708         sprd_dolphin_nand_ins_add(NAND_MC_IDST(1), dolphin);\r
709         sprd_dolphin_nand_ins_add(NFC_MC_DONE_ID, dolphin);\r
710         sprd_dolphin_reg_write(NFC_CFG0_REG, NFC_ONLY_NAND_MODE);\r
711         sprd_dolphin_nand_ins_exec(dolphin);\r
712         sprd_dolphin_nand_wait_finish(dolphin);\r
713         buf = (uint32_t *)s_oob_data;\r
714         *buf = sprd_dolphin_reg_read(NFC_STATUS0_REG);\r
715         dolphin->buf_head = 0;\r
716         dolphin->_buf_tail = 1;\r
717         //DPRINT("--sprd_dolphin_nand_read_status--\r\n");\r
718 }\r
719 static void sprd_dolphin_nand_read_id(struct sprd_dolphin_nand_info *dolphin, uint32_t *buf)\r
720 {\r
721         //DPRINT("sprd_dolphin_nand_read_id\r\n");\r
722         sprd_dolphin_nand_ins_init(dolphin);\r
723         sprd_dolphin_nand_ins_add(NAND_MC_CMD(NAND_CMD_READID), dolphin);\r
724         sprd_dolphin_nand_ins_add(NAND_MC_ADDR(0), dolphin);\r
725         sprd_dolphin_nand_ins_add(NAND_MC_NOP(10), dolphin);\r
726         sprd_dolphin_nand_ins_add(NAND_MC_IDST(8), dolphin);\r
727         sprd_dolphin_nand_ins_add(NFC_MC_DONE_ID, dolphin);\r
728         \r
729         sprd_dolphin_reg_write(NFC_CFG0_REG, NFC_ONLY_NAND_MODE);\r
730         sprd_dolphin_nand_ins_exec(dolphin);\r
731         sprd_dolphin_nand_wait_finish(dolphin);\r
732         *buf = sprd_dolphin_reg_read(NFC_STATUS0_REG);\r
733         *(buf + 1) = sprd_dolphin_reg_read(NFC_STATUS1_REG);\r
734         dolphin->buf_head = 0;\r
735         dolphin->_buf_tail = 8;\r
736         //DPRINT("--sprd_dolphin_nand_read_id--\r\n");\r
737 }\r
738 static void sprd_dolphin_nand_reset(struct sprd_dolphin_nand_info *dolphin)\r
739 {\r
740         //DPRINT("sprd_dolphin_nand_reset\r\n");\r
741         sprd_dolphin_nand_ins_init(dolphin);\r
742         sprd_dolphin_nand_ins_add(NAND_MC_CMD(NAND_CMD_RESET), dolphin);\r
743         sprd_dolphin_nand_ins_add(NFC_MC_WRB0_ID, dolphin); //wait rb\r
744         sprd_dolphin_nand_ins_add(NFC_MC_DONE_ID, dolphin);\r
745         //config register\r
746         sprd_dolphin_reg_write(NFC_CFG0_REG, NFC_ONLY_NAND_MODE);\r
747         sprd_dolphin_nand_ins_exec(dolphin);\r
748         sprd_dolphin_nand_wait_finish(dolphin);\r
749         //DPRINT("--sprd_dolphin_nand_reset--\r\n");\r
750 }\r
751 static u32 sprd_dolphin_get_decode_sts(u32 index)\r
752 {\r
753         uint32_t err;\r
754         uint32_t shift;\r
755         uint32_t reg_addr;\r
756         reg_addr = NFC_STATUS0_REG + (index & 0xfffffffc);\r
757         shift = (index & 0x3) << 3;\r
758         err = sprd_dolphin_reg_read(reg_addr);\r
759         err >>= shift;\r
760         if((err & ECC_ALL_FF))\r
761         {\r
762                 err &= ERR_ERR_NUM0_MASK;\r
763         }\r
764         else\r
765         {\r
766                 err = 0;\r
767         }\r
768         return err;\r
769 }\r
770 \r
771 \r
772 #ifdef DOLPHIN_UBOOT\r
773 //read large page\r
774 static int sprd_dolphin_nand_read_lp(struct mtd_info *mtd,uint8_t *mbuf, uint8_t *sbuf,uint32_t raw)\r
775 {\r
776         struct sprd_dolphin_nand_info *dolphin = mtd_to_dolphin(mtd);\r
777         struct nand_chip *chip = dolphin->nand;\r
778         uint32_t column;\r
779         uint32_t page_addr;\r
780         uint32_t cfg0;\r
781         uint32_t cfg1;\r
782         uint32_t cfg2;\r
783         uint32_t i;\r
784         uint32_t err;\r
785         page_addr = dolphin->page;\r
786         \r
787         if(sbuf) {\r
788                 column = mtd->writesize;\r
789         }\r
790         else\r
791         {\r
792                 column = 0;\r
793         }\r
794         if(chip->options & NAND_BUSWIDTH_16)\r
795         {\r
796                 column >>= 1;\r
797         }\r
798         //DPRINT("sprd_dolphin_nand_read_lp,page_addr = %x,column = %x\r\n",page_addr, column);\r
799         sprd_dolphin_nand_ins_init(dolphin);\r
800         sprd_dolphin_nand_ins_add(NAND_MC_CMD(NAND_CMD_READ0), dolphin);\r
801         sprd_dolphin_nand_ins_add(NAND_MC_ADDR(column & 0xff), dolphin);\r
802         column >>= 8;\r
803         sprd_dolphin_nand_ins_add(NAND_MC_ADDR(column & 0xff), dolphin);\r
804 \r
805         sprd_dolphin_nand_ins_add(NAND_MC_ADDR(page_addr & 0xff), dolphin);\r
806         page_addr >>= 8;\r
807         sprd_dolphin_nand_ins_add(NAND_MC_ADDR(page_addr & 0xff), dolphin);\r
808         \r
809         if (5 == dolphin->a_cycles)// five address cycles\r
810         {\r
811                 page_addr >>= 8;\r
812                 sprd_dolphin_nand_ins_add(NAND_MC_ADDR(page_addr & 0xff), dolphin);\r
813         }\r
814         sprd_dolphin_nand_ins_add(NAND_MC_CMD(NAND_CMD_READSTART), dolphin);\r
815         \r
816         sprd_dolphin_nand_ins_add(NFC_MC_WRB0_ID, dolphin); //wait rb\r
817         if(mbuf && sbuf)\r
818         {\r
819                 sprd_dolphin_nand_ins_add(NAND_MC_SRDT, dolphin);\r
820                 //switch to main part\r
821                 sprd_dolphin_nand_ins_add(NAND_MC_CMD(NAND_CMD_RNDOUT), dolphin);\r
822                 sprd_dolphin_nand_ins_add(NAND_MC_ADDR(0), dolphin);\r
823                 sprd_dolphin_nand_ins_add(NAND_MC_ADDR(0), dolphin);\r
824                 sprd_dolphin_nand_ins_add(NAND_MC_CMD(NAND_CMD_RNDOUTSTART), dolphin);\r
825                 sprd_dolphin_nand_ins_add(NAND_MC_MRDT, dolphin);\r
826         }\r
827         else\r
828         {\r
829                 sprd_dolphin_nand_ins_add(NAND_MC_MRDT, dolphin);\r
830         }\r
831         sprd_dolphin_nand_ins_add(NFC_MC_DONE_ID, dolphin);\r
832         //config registers \r
833         cfg0 = NFC_AUTO_MODE | MAIN_SPAR_APT | ((dolphin->sct_pg - 1)<< SECTOR_NUM_OFFSET);\r
834         if((!raw) && mbuf && sbuf)\r
835         {\r
836                 cfg0 |= ECC_EN | DETECT_ALL_FF;\r
837         }\r
838         if(chip->options & NAND_BUSWIDTH_16)\r
839         {\r
840                 cfg0 |= BUS_WIDTH;\r
841         }\r
842         cfg1 = (dolphin->info_size) << SPAR_INFO_SIZE_OFFSET;\r
843         cfg2 = (dolphin->ecc_mode << 12) | (dolphin->info_pos << SPAR_INFO_POS_OFFSET) | ((dolphin->sct_pg - 1) << SPAR_SECTOR_NUM_OFFSET) | dolphin->ecc_pos;\r
844 \r
845 #ifndef CONFIG_NAND_SPL\r
846         if (mbuf)\r
847         {\r
848                 Dcache_CleanRegion((unsigned int)mbuf, dolphin->m_size*dolphin->sct_pg);\r
849                 Dcache_InvalRegion((unsigned int)mbuf, dolphin->m_size*dolphin->sct_pg);\r
850         }\r
851 \r
852         if (sbuf)\r
853         {\r
854                 Dcache_CleanRegion((unsigned int)sbuf, dolphin->s_size*dolphin->sct_pg);\r
855                 Dcache_InvalRegion((unsigned int)sbuf, dolphin->s_size*dolphin->sct_pg);\r
856         }\r
857 #endif\r
858 \r
859         if(mbuf && sbuf)\r
860         {\r
861                 cfg1 |= (dolphin->m_size - 1) | ((dolphin->s_size  - 1)<< SPAR_SIZE_OFFSET);\r
862                 sprd_dolphin_reg_write(NFC_MAIN_ADDR_REG, (uint32_t)mbuf);\r
863                 sprd_dolphin_reg_write(NFC_SPAR_ADDR_REG, (uint32_t)sbuf);\r
864                 cfg0 |= MAIN_USE | SPAR_USE;\r
865         }\r
866         else\r
867         {\r
868                 if(mbuf)\r
869                 {\r
870                         cfg1 |= (dolphin->m_size - 1);\r
871                         sprd_dolphin_reg_write(NFC_MAIN_ADDR_REG, (uint32_t)mbuf);\r
872                 }\r
873                 if(sbuf)\r
874                 {\r
875                         cfg1 |= (dolphin->s_size - 1);\r
876                         sprd_dolphin_reg_write(NFC_MAIN_ADDR_REG, (uint32_t)sbuf);\r
877                 }\r
878                 cfg0 |= MAIN_USE;\r
879         }       \r
880         sprd_dolphin_reg_write(NFC_CFG0_REG, cfg0);\r
881         sprd_dolphin_reg_write(NFC_CFG1_REG, cfg1);\r
882         sprd_dolphin_reg_write(NFC_CFG2_REG, cfg2);\r
883         \r
884         sprd_dolphin_nand_ins_exec(dolphin);\r
885         sprd_dolphin_nand_wait_finish(dolphin);\r
886         if(!raw) {\r
887                 for(i = 0; i < dolphin->sct_pg; i++) {\r
888                         err = sprd_dolphin_get_decode_sts(i);\r
889                         if(err == ERR_ERR_NUM0_MASK) {\r
890                                 mtd->ecc_stats.failed++;\r
891                         }\r
892                         else {\r
893                                 mtd->ecc_stats.corrected += err;\r
894                         }\r
895                 }\r
896         }\r
897 \r
898         return 0;\r
899 }\r
900 \r
901 \r
902 static int sprd_dolphin_nand_write_lp(struct mtd_info *mtd,const uint8_t *mbuf, uint8_t *sbuf,uint32_t raw)\r
903 {\r
904         struct sprd_dolphin_nand_info *dolphin = mtd_to_dolphin(mtd);\r
905         struct nand_chip *chip = dolphin->nand;\r
906         uint32_t column;\r
907         uint32_t page_addr;\r
908         uint32_t cfg0;\r
909         uint32_t cfg1;\r
910         uint32_t cfg2;\r
911         page_addr = dolphin->page;\r
912         if(mbuf) {\r
913                 column = 0;\r
914         }\r
915         else {\r
916                 column = mtd->writesize;\r
917         }       \r
918         if(chip->options & NAND_BUSWIDTH_16)\r
919         {\r
920                 column >>= 1;\r
921         }\r
922 \r
923         sprd_dolphin_nand_ins_init(dolphin);\r
924         sprd_dolphin_nand_ins_add(NAND_MC_CMD(NAND_CMD_SEQIN), dolphin);\r
925         sprd_dolphin_nand_ins_add(NAND_MC_ADDR(column & 0xff), dolphin);\r
926         column >>= 8;\r
927         sprd_dolphin_nand_ins_add(NAND_MC_ADDR(column & 0xff), dolphin);\r
928         sprd_dolphin_nand_ins_add(NAND_MC_ADDR(page_addr & 0xff), dolphin);\r
929         page_addr >>= 8;\r
930         sprd_dolphin_nand_ins_add(NAND_MC_ADDR(page_addr & 0xff), dolphin);\r
931         \r
932         if (5 == dolphin->a_cycles)// five address cycles\r
933         {\r
934                 page_addr >>= 8;\r
935                 sprd_dolphin_nand_ins_add(NAND_MC_ADDR(page_addr & 0xff), dolphin);\r
936         }\r
937         \r
938         sprd_dolphin_nand_ins_add(NAND_MC_MWDT, dolphin);\r
939         if(mbuf && sbuf)\r
940         {\r
941                 sprd_dolphin_nand_ins_add(NAND_MC_SWDT, dolphin);\r
942         }\r
943         sprd_dolphin_nand_ins_add(NAND_MC_CMD(NAND_CMD_PAGEPROG), dolphin);\r
944         sprd_dolphin_nand_ins_add(NFC_MC_WRB0_ID, dolphin); //wait rb\r
945 \r
946         sprd_dolphin_nand_ins_add(NFC_MC_DONE_ID, dolphin);\r
947         //config registers \r
948         cfg0 = NFC_AUTO_MODE | NFC_RW |  NFC_WPN | MAIN_SPAR_APT | ((dolphin->sct_pg - 1)<< SECTOR_NUM_OFFSET);\r
949         if((!raw) && mbuf && sbuf)\r
950         {\r
951                 cfg0 |= ECC_EN;\r
952         }\r
953         if(chip->options & NAND_BUSWIDTH_16)\r
954         {\r
955                 cfg0 |= BUS_WIDTH;\r
956         }\r
957         cfg1 = ((dolphin->info_size) << SPAR_INFO_SIZE_OFFSET);\r
958         cfg2 = (dolphin->ecc_mode << 12) | (dolphin->info_pos << SPAR_INFO_POS_OFFSET) | ((dolphin->sct_pg - 1) << SPAR_SECTOR_NUM_OFFSET) | dolphin->ecc_pos;\r
959 \r
960 #ifndef CONFIG_NAND_SPL\r
961         if (mbuf)\r
962         {\r
963                 Dcache_CleanRegion((unsigned int)mbuf, dolphin->m_size*dolphin->sct_pg);\r
964                 Dcache_InvalRegion((unsigned int)mbuf, dolphin->m_size*dolphin->sct_pg);\r
965         }\r
966 \r
967         if (sbuf)\r
968         {\r
969                 Dcache_CleanRegion((unsigned int)sbuf, dolphin->s_size*dolphin->sct_pg);\r
970                 Dcache_InvalRegion((unsigned int)sbuf, dolphin->s_size*dolphin->sct_pg);\r
971         }\r
972 #endif\r
973 \r
974         if(mbuf && sbuf)\r
975         {\r
976                 cfg0 |= MAIN_USE | SPAR_USE;\r
977                 cfg1 |= (dolphin->m_size - 1) | ((dolphin->s_size - 1) << SPAR_SIZE_OFFSET);\r
978                 sprd_dolphin_reg_write(NFC_MAIN_ADDR_REG, (uint32_t)mbuf);\r
979                 sprd_dolphin_reg_write(NFC_SPAR_ADDR_REG, (uint32_t)sbuf);\r
980         }\r
981         else\r
982         {\r
983                 cfg0 |= MAIN_USE;\r
984                 if(mbuf)\r
985                 {\r
986                         cfg1 |= dolphin->m_size - 1;\r
987                         sprd_dolphin_reg_write(NFC_MAIN_ADDR_REG, (uint32_t)mbuf);\r
988                 }\r
989                 else\r
990                 {\r
991                         cfg1 |= dolphin->s_size - 1;\r
992                         sprd_dolphin_reg_write(NFC_MAIN_ADDR_REG, (uint32_t)sbuf);\r
993                 }\r
994         }\r
995         sprd_dolphin_reg_write(NFC_CFG0_REG, cfg0);\r
996         sprd_dolphin_reg_write(NFC_CFG1_REG, cfg1);\r
997         sprd_dolphin_reg_write(NFC_CFG2_REG, cfg2);\r
998         sprd_dolphin_nand_ins_exec(dolphin);\r
999         sprd_dolphin_nand_wait_finish(dolphin);\r
1000         return 0;\r
1001 }\r
1002 #endif\r
1003 \r
1004 \r
1005 \r
1006 #ifdef DOLPHIN_KERNEL\r
1007 //read large page\r
1008 static int sprd_dolphin_nand_read_lp(struct mtd_info *mtd,uint8_t *mbuf, uint8_t *sbuf,uint32_t raw)\r
1009 {\r
1010         struct sprd_dolphin_nand_info *dolphin = mtd_to_dolphin(mtd);\r
1011         struct nand_chip *chip = dolphin->nand;\r
1012         uint32_t column;\r
1013         uint32_t page_addr;\r
1014         uint32_t cfg0;\r
1015         uint32_t cfg1;\r
1016         uint32_t cfg2;\r
1017         uint32_t i;\r
1018         uint32_t err;\r
1019         page_addr = dolphin->page;\r
1020         \r
1021         if(sbuf) {\r
1022                 column = mtd->writesize;\r
1023         }\r
1024         else\r
1025         {\r
1026                 column = 0;\r
1027         }\r
1028         if(chip->options & NAND_BUSWIDTH_16)\r
1029         {\r
1030                 column >>= 1;\r
1031         }\r
1032         //DPRINT("sprd_dolphin_nand_read_lp,page_addr = %x,column = %x\r\n",page_addr, column);\r
1033         sprd_dolphin_nand_ins_init(dolphin);\r
1034         sprd_dolphin_nand_ins_add(NAND_MC_CMD(NAND_CMD_READ0), dolphin);\r
1035         sprd_dolphin_nand_ins_add(NAND_MC_ADDR(column & 0xff), dolphin);\r
1036         column >>= 8;\r
1037         sprd_dolphin_nand_ins_add(NAND_MC_ADDR(column & 0xff), dolphin);\r
1038 \r
1039         sprd_dolphin_nand_ins_add(NAND_MC_ADDR(page_addr & 0xff), dolphin);\r
1040         page_addr >>= 8;\r
1041         sprd_dolphin_nand_ins_add(NAND_MC_ADDR(page_addr & 0xff), dolphin);\r
1042         \r
1043         if (5 == dolphin->a_cycles)// five address cycles\r
1044         {\r
1045                 page_addr >>= 8;\r
1046                 sprd_dolphin_nand_ins_add(NAND_MC_ADDR(page_addr & 0xff), dolphin);\r
1047         }\r
1048         sprd_dolphin_nand_ins_add(NAND_MC_CMD(NAND_CMD_READSTART), dolphin);\r
1049         \r
1050         sprd_dolphin_nand_ins_add(NFC_MC_WRB0_ID, dolphin); //wait rb\r
1051         if(mbuf && sbuf)\r
1052         {\r
1053                 sprd_dolphin_nand_ins_add(NAND_MC_SRDT, dolphin);\r
1054                 //switch to main part\r
1055                 sprd_dolphin_nand_ins_add(NAND_MC_CMD(NAND_CMD_RNDOUT), dolphin);\r
1056                 sprd_dolphin_nand_ins_add(NAND_MC_ADDR(0), dolphin);\r
1057                 sprd_dolphin_nand_ins_add(NAND_MC_ADDR(0), dolphin);\r
1058                 sprd_dolphin_nand_ins_add(NAND_MC_CMD(NAND_CMD_RNDOUTSTART), dolphin);\r
1059                 sprd_dolphin_nand_ins_add(NAND_MC_MRDT, dolphin);\r
1060         }\r
1061         else\r
1062         {\r
1063                 sprd_dolphin_nand_ins_add(NAND_MC_MRDT, dolphin);\r
1064         }\r
1065         sprd_dolphin_nand_ins_add(NFC_MC_DONE_ID, dolphin);\r
1066         //config registers \r
1067         cfg0 = NFC_AUTO_MODE | MAIN_SPAR_APT | ((dolphin->sct_pg - 1)<< SECTOR_NUM_OFFSET);\r
1068         if((!raw) && mbuf && sbuf)\r
1069         {\r
1070                 cfg0 |= ECC_EN | DETECT_ALL_FF;\r
1071         }\r
1072         if(chip->options & NAND_BUSWIDTH_16)\r
1073         {\r
1074                 cfg0 |= BUS_WIDTH;\r
1075         }\r
1076         cfg1 = (dolphin->info_size) << SPAR_INFO_SIZE_OFFSET;\r
1077         cfg2 = (dolphin->ecc_mode << 12) | (dolphin->info_pos << SPAR_INFO_POS_OFFSET) | ((dolphin->sct_pg - 1) << SPAR_SECTOR_NUM_OFFSET) | dolphin->ecc_pos;\r
1078 \r
1079         if(mbuf && sbuf)\r
1080         {\r
1081                 cfg1 |= (dolphin->m_size - 1) | ((dolphin->s_size  - 1)<< SPAR_SIZE_OFFSET);\r
1082                 sprd_dolphin_reg_write(NFC_MAIN_ADDR_REG, dolphin->p_mbuf);\r
1083                 sprd_dolphin_reg_write(NFC_SPAR_ADDR_REG, dolphin->p_oob);\r
1084                 cfg0 |= MAIN_USE | SPAR_USE;\r
1085         }\r
1086         else\r
1087         {\r
1088                 if(mbuf)\r
1089                 {\r
1090                         cfg1 |= (dolphin->m_size - 1);\r
1091                         sprd_dolphin_reg_write(NFC_MAIN_ADDR_REG, dolphin->p_mbuf);\r
1092                 }\r
1093                 if(sbuf)\r
1094                 {\r
1095                         cfg1 |= (dolphin->s_size - 1);\r
1096                         sprd_dolphin_reg_write(NFC_MAIN_ADDR_REG, dolphin->p_oob);\r
1097                 }\r
1098                 cfg0 |= MAIN_USE;\r
1099         }       \r
1100         sprd_dolphin_reg_write(NFC_CFG0_REG, cfg0);\r
1101         sprd_dolphin_reg_write(NFC_CFG1_REG, cfg1);\r
1102         sprd_dolphin_reg_write(NFC_CFG2_REG, cfg2);\r
1103         \r
1104         sprd_dolphin_nand_ins_exec(dolphin);\r
1105         sprd_dolphin_nand_wait_finish(dolphin);\r
1106         if(!raw) {\r
1107                 for(i = 0; i < dolphin->sct_pg; i++) {\r
1108                         err = sprd_dolphin_get_decode_sts(i);\r
1109                         if(err == ERR_ERR_NUM0_MASK) {\r
1110                                 mtd->ecc_stats.failed++;\r
1111                         }\r
1112                         else {\r
1113                                 mtd->ecc_stats.corrected += err;\r
1114                         }\r
1115                 }\r
1116         }\r
1117 \r
1118         if(mbuf) {\r
1119                 memcpy(mbuf, (const void *)dolphin->v_mbuf, dolphin->write_size);\r
1120         }\r
1121         if(sbuf) {\r
1122                 memcpy(sbuf, (const void *)dolphin->v_oob, dolphin->oob_size);\r
1123         }\r
1124 \r
1125         return 0;\r
1126 }\r
1127 \r
1128 \r
1129 \r
1130 static int sprd_dolphin_nand_write_lp(struct mtd_info *mtd,const uint8_t *mbuf, uint8_t *sbuf,uint32_t raw)\r
1131 {\r
1132         struct sprd_dolphin_nand_info *dolphin = mtd_to_dolphin(mtd);\r
1133         struct nand_chip *chip = dolphin->nand;\r
1134         uint32_t column;\r
1135         uint32_t page_addr;\r
1136         uint32_t cfg0;\r
1137         uint32_t cfg1;\r
1138         uint32_t cfg2;\r
1139         page_addr = dolphin->page;\r
1140         if(mbuf) {\r
1141                 column = 0;\r
1142         }\r
1143         else {\r
1144                 column = mtd->writesize;\r
1145         }       \r
1146         if(chip->options & NAND_BUSWIDTH_16)\r
1147         {\r
1148                 column >>= 1;\r
1149         }\r
1150         \r
1151         if(mbuf) {\r
1152                 memcpy((void *)dolphin->v_mbuf, (const void *)mbuf, dolphin->write_size);\r
1153         }\r
1154         if(sbuf) {\r
1155                 memcpy((void *)dolphin->v_oob, (const void *)sbuf, dolphin->oob_size);\r
1156         }\r
1157 \r
1158         sprd_dolphin_nand_ins_init(dolphin);\r
1159         sprd_dolphin_nand_ins_add(NAND_MC_CMD(NAND_CMD_SEQIN), dolphin);\r
1160         sprd_dolphin_nand_ins_add(NAND_MC_ADDR(column & 0xff), dolphin);\r
1161         column >>= 8;\r
1162         sprd_dolphin_nand_ins_add(NAND_MC_ADDR(column & 0xff), dolphin);\r
1163         sprd_dolphin_nand_ins_add(NAND_MC_ADDR(page_addr & 0xff), dolphin);\r
1164         page_addr >>= 8;\r
1165         sprd_dolphin_nand_ins_add(NAND_MC_ADDR(page_addr & 0xff), dolphin);\r
1166         \r
1167         if (5 == dolphin->a_cycles)// five address cycles\r
1168         {\r
1169                 page_addr >>= 8;\r
1170                 sprd_dolphin_nand_ins_add(NAND_MC_ADDR(page_addr & 0xff), dolphin);\r
1171         }\r
1172         \r
1173         sprd_dolphin_nand_ins_add(NAND_MC_MWDT, dolphin);\r
1174         if(mbuf && sbuf)\r
1175         {\r
1176                 sprd_dolphin_nand_ins_add(NAND_MC_SWDT, dolphin);\r
1177         }\r
1178         sprd_dolphin_nand_ins_add(NAND_MC_CMD(NAND_CMD_PAGEPROG), dolphin);\r
1179         sprd_dolphin_nand_ins_add(NFC_MC_WRB0_ID, dolphin); //wait rb\r
1180 \r
1181         sprd_dolphin_nand_ins_add(NFC_MC_DONE_ID, dolphin);\r
1182         //config registers \r
1183         cfg0 = NFC_AUTO_MODE | NFC_RW |  NFC_WPN | MAIN_SPAR_APT | ((dolphin->sct_pg - 1)<< SECTOR_NUM_OFFSET);\r
1184         if((!raw) && mbuf && sbuf)\r
1185         {\r
1186                 cfg0 |= ECC_EN;\r
1187         }\r
1188         if(chip->options & NAND_BUSWIDTH_16)\r
1189         {\r
1190                 cfg0 |= BUS_WIDTH;\r
1191         }\r
1192         cfg1 = ((dolphin->info_size) << SPAR_INFO_SIZE_OFFSET);\r
1193         cfg2 = (dolphin->ecc_mode << 12) | (dolphin->info_pos << SPAR_INFO_POS_OFFSET) | ((dolphin->sct_pg - 1) << SPAR_SECTOR_NUM_OFFSET) | dolphin->ecc_pos;\r
1194 \r
1195         if(mbuf && sbuf)\r
1196         {\r
1197                 cfg0 |= MAIN_USE | SPAR_USE;\r
1198                 cfg1 |= (dolphin->m_size - 1) | ((dolphin->s_size - 1) << SPAR_SIZE_OFFSET);\r
1199                 sprd_dolphin_reg_write(NFC_MAIN_ADDR_REG, dolphin->p_mbuf);\r
1200                 sprd_dolphin_reg_write(NFC_SPAR_ADDR_REG, dolphin->p_oob);\r
1201         }\r
1202         else\r
1203         {\r
1204                 cfg0 |= MAIN_USE;\r
1205                 if(mbuf)\r
1206                 {\r
1207                         cfg1 |= dolphin->m_size - 1;\r
1208                         sprd_dolphin_reg_write(NFC_MAIN_ADDR_REG, dolphin->p_mbuf);\r
1209                 }\r
1210                 else\r
1211                 {\r
1212                         cfg1 |= dolphin->s_size - 1;\r
1213                         sprd_dolphin_reg_write(NFC_MAIN_ADDR_REG, dolphin->p_oob);\r
1214                 }\r
1215         }\r
1216         sprd_dolphin_reg_write(NFC_CFG0_REG, cfg0);\r
1217         sprd_dolphin_reg_write(NFC_CFG1_REG, cfg1);\r
1218         sprd_dolphin_reg_write(NFC_CFG2_REG, cfg2);\r
1219         sprd_dolphin_nand_ins_exec(dolphin);\r
1220         sprd_dolphin_nand_wait_finish(dolphin);\r
1221         return 0;\r
1222 }\r
1223 #endif\r
1224 \r
1225 \r
1226 \r
1227 static int sprd_dolphin_nand_read_sp(struct mtd_info *mtd,uint8_t *mbuf, uint8_t *sbuf,uint32_t raw)\r
1228 {\r
1229         return 0;\r
1230 }\r
1231 static int sprd_dolphin_nand_write_sp(struct mtd_info *mtd,const uint8_t *mbuf, uint8_t *sbuf,uint32_t raw)\r
1232 {\r
1233         return 0;\r
1234 }\r
1235 static void sprd_dolphin_erase(struct mtd_info *mtd, int page_addr)\r
1236 {\r
1237         struct sprd_dolphin_nand_info *dolphin = mtd_to_dolphin(mtd);\r
1238         uint32_t cfg0 = 0;\r
1239         //DPRINT("sprd_dolphin_erase, %x\r\n", page_addr);\r
1240         sprd_dolphin_nand_ins_init(dolphin);\r
1241         sprd_dolphin_nand_ins_add(NAND_MC_CMD(NAND_CMD_ERASE1), dolphin);\r
1242         sprd_dolphin_nand_ins_add(NAND_MC_ADDR(page_addr & 0xff), dolphin);\r
1243         page_addr >>= 8;\r
1244         sprd_dolphin_nand_ins_add(NAND_MC_ADDR(page_addr & 0xff), dolphin);\r
1245         if((5 == dolphin->a_cycles) || ((4 == dolphin->a_cycles) && (512 == dolphin->write_size)))\r
1246         {\r
1247                 page_addr >>= 8;\r
1248                 sprd_dolphin_nand_ins_add(NAND_MC_ADDR(page_addr & 0xff), dolphin);\r
1249         }\r
1250         sprd_dolphin_nand_ins_add(NAND_MC_CMD(NAND_CMD_ERASE2), dolphin);\r
1251         sprd_dolphin_nand_ins_add(NFC_MC_WRB0_ID, dolphin); //wait rb\r
1252 \r
1253         sprd_dolphin_nand_ins_add(NFC_MC_DONE_ID, dolphin);\r
1254         cfg0 = NFC_WPN | NFC_ONLY_NAND_MODE;\r
1255         sprd_dolphin_reg_write(NFC_CFG0_REG, cfg0);\r
1256         sprd_dolphin_nand_ins_exec(dolphin);\r
1257         sprd_dolphin_nand_wait_finish(dolphin);\r
1258         //DPRINT("--sprd_dolphin_erase--\r\n");\r
1259 }\r
1260 static uint8_t sprd_dolphin_read_byte(struct mtd_info *mtd)\r
1261 {\r
1262         uint8_t ch = 0xff;\r
1263         struct sprd_dolphin_nand_info *dolphin = mtd_to_dolphin(mtd);\r
1264         if(dolphin->buf_head < dolphin->_buf_tail)\r
1265         {\r
1266                 ch = s_oob_data[dolphin->buf_head ++];\r
1267         }\r
1268         return ch;\r
1269 }\r
1270 static uint16_t sprd_dolphin_read_word(struct mtd_info *mtd)\r
1271 {\r
1272         uint16_t data = 0xffff;\r
1273         struct sprd_dolphin_nand_info *dolphin = mtd_to_dolphin(mtd);\r
1274         if(dolphin->buf_head < (dolphin->_buf_tail - 1))\r
1275         {\r
1276                 data = s_oob_data[dolphin->buf_head ++];\r
1277                 data |= ((uint16_t)s_oob_data[dolphin->buf_head ++]) << 8;\r
1278         }\r
1279         return data;\r
1280 }\r
1281 \r
1282 static int sprd_dolphin_waitfunc(struct mtd_info *mtd, struct nand_chip *chip)\r
1283 {\r
1284         return 0;\r
1285 }\r
1286 \r
1287 static int sprd_dolphin_ecc_calculate(struct mtd_info *mtd, const uint8_t *data,\r
1288                                 uint8_t *ecc_code)\r
1289 {\r
1290         return 0;\r
1291 }\r
1292 \r
1293 static int sprd_dolphin_ecc_correct(struct mtd_info *mtd, uint8_t *data,\r
1294                                 uint8_t *read_ecc, uint8_t *calc_ecc)\r
1295 {\r
1296         return 0;\r
1297 }\r
1298 \r
1299 static int sprd_dolphin_read_page(struct mtd_info *mtd, struct nand_chip *chip,\r
1300                         uint8_t *buf, int page)\r
1301 {\r
1302         struct sprd_dolphin_nand_info *dolphin = mtd_to_dolphin(mtd);\r
1303         dolphin->page = page;\r
1304         if(512 == mtd->writesize)\r
1305         {\r
1306                 sprd_dolphin_nand_read_sp(mtd, buf, chip->oob_poi, 0);\r
1307         }\r
1308         else\r
1309         {\r
1310                 sprd_dolphin_nand_read_lp(mtd, buf, chip->oob_poi, 0);\r
1311         }\r
1312         return 0;\r
1313 }\r
1314 static int sprd_dolphin_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,\r
1315                                 uint8_t *buf, int page)\r
1316 {\r
1317         struct sprd_dolphin_nand_info *dolphin = mtd_to_dolphin(mtd);\r
1318         dolphin->page = page;\r
1319         if(512 == mtd->writesize)\r
1320         {\r
1321                 sprd_dolphin_nand_read_sp(mtd, buf, chip->oob_poi, 1);\r
1322         }\r
1323         else\r
1324         {\r
1325                 sprd_dolphin_nand_read_lp(mtd, buf, chip->oob_poi, 1);\r
1326         }\r
1327         return 0;\r
1328 }\r
1329 static int sprd_dolphin_read_oob(struct mtd_info *mtd, struct nand_chip *chip,\r
1330                            int page, int sndcmd)\r
1331 {\r
1332         struct sprd_dolphin_nand_info *dolphin = mtd_to_dolphin(mtd);\r
1333         dolphin->page = page;\r
1334         if(512 == mtd->writesize)\r
1335         {\r
1336                 sprd_dolphin_nand_read_sp(mtd, 0, chip->oob_poi, 1);\r
1337         }\r
1338         else\r
1339         {\r
1340                 sprd_dolphin_nand_read_lp(mtd, 0, chip->oob_poi, 1);\r
1341         }\r
1342         return 0;\r
1343 }\r
1344 static void sprd_dolphin_write_page(struct mtd_info *mtd, struct nand_chip *chip,\r
1345                                 const uint8_t *buf)\r
1346 {\r
1347         if(512 == mtd->writesize)\r
1348         {\r
1349                 sprd_dolphin_nand_write_sp(mtd, buf, chip->oob_poi, 0); \r
1350         }\r
1351         else\r
1352         {\r
1353                 sprd_dolphin_nand_write_lp(mtd, buf, chip->oob_poi, 0); \r
1354         }\r
1355 \r
1356 }\r
1357 static void sprd_dolphin_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip,\r
1358                                         const uint8_t *buf)\r
1359 {\r
1360         if(512 == mtd->writesize)\r
1361         {\r
1362                 sprd_dolphin_nand_write_sp(mtd, buf, chip->oob_poi, 1); \r
1363         }\r
1364         else\r
1365         {\r
1366                 sprd_dolphin_nand_write_lp(mtd, buf, chip->oob_poi, 1); \r
1367         }\r
1368 }\r
1369 static int sprd_dolphin_write_oob(struct mtd_info *mtd, struct nand_chip *chip,\r
1370                                 int page)\r
1371 {\r
1372         struct sprd_dolphin_nand_info *dolphin = mtd_to_dolphin(mtd);   \r
1373         dolphin->page = page;\r
1374         if(512 == mtd->writesize)\r
1375         {\r
1376                 sprd_dolphin_nand_write_sp(mtd, 0, chip->oob_poi, 1);\r
1377         }\r
1378         else\r
1379         {\r
1380                 sprd_dolphin_nand_write_lp(mtd, 0, chip->oob_poi, 1);\r
1381         }\r
1382         return 0;\r
1383 }\r
1384 \r
1385 \r
1386 /**\r
1387  * nand_block_bad - [DEFAULT] Read bad block marker from the chip\r
1388  * @mtd:        MTD device structure\r
1389  * @ofs:        offset from device start\r
1390  * @getchip:    0, if the chip is already selected\r
1391  *\r
1392  * Check, if the block is bad.\r
1393  */\r
1394 static int sprd_dolphin_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)\r
1395 {\r
1396         int page, chipnr, res = 0;\r
1397         struct sprd_dolphin_nand_info *dolphin = mtd_to_dolphin(mtd);\r
1398         struct nand_chip *chip = mtd->priv;\r
1399         uint16_t bad;\r
1400         uint16_t *buf;\r
1401 \r
1402         page = (int)((long)ofs >> chip->page_shift) & chip->pagemask;\r
1403 \r
1404         if (getchip) {\r
1405                 chipnr = (int)((long)ofs >> chip->chip_shift);\r
1406                 /* Select the NAND device */\r
1407                 chip->select_chip(mtd, chipnr);\r
1408         }\r
1409 \r
1410         chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page);\r
1411         if(512 == dolphin->write_size) {\r
1412                 sprd_dolphin_nand_read_sp(mtd, 0, s_oob_data, 1);\r
1413         }\r
1414         else  {\r
1415                 sprd_dolphin_nand_read_lp(mtd, 0, s_oob_data, 1);\r
1416         }\r
1417         dolphin->buf_head = 0;\r
1418         dolphin->_buf_tail = mtd->oobsize;\r
1419         buf = (uint16_t *)(s_oob_data + chip->badblockpos);\r
1420 \r
1421         if (chip->options & NAND_BUSWIDTH_16) {\r
1422                 bad = *(buf);\r
1423                 if ((bad & 0xFF) != 0xff) {\r
1424                         res = 1;\r
1425                 }\r
1426         } else {\r
1427                 bad = *(buf) & 0xff;\r
1428                 if (bad != 0xff){\r
1429                         res = 1;\r
1430                 }\r
1431         }\r
1432         return res;\r
1433 }\r
1434 \r
1435 static void sprd_dolphin_nand_cmdfunc(struct mtd_info *mtd, unsigned int command,\r
1436                             int column, int page_addr)\r
1437 {\r
1438         struct sprd_dolphin_nand_info *dolphin = mtd_to_dolphin(mtd);\r
1439         /* Emulate NAND_CMD_READOOB */\r
1440         if (command == NAND_CMD_READOOB) {\r
1441                 column += mtd->writesize;\r
1442                 command = NAND_CMD_READ0;\r
1443         }\r
1444         /*\r
1445          * program and erase have their own busy handlers\r
1446          * status, sequential in, and deplete1 need no delay\r
1447          */\r
1448         switch (command) {\r
1449         case NAND_CMD_STATUS:\r
1450                 sprd_dolphin_nand_read_status(dolphin);\r
1451                 break;\r
1452         case NAND_CMD_READID:\r
1453                 sprd_dolphin_nand_read_id(dolphin, (uint32_t *)s_oob_data);\r
1454                 break;\r
1455         case NAND_CMD_RESET:\r
1456                 sprd_dolphin_nand_reset(dolphin);\r
1457                 break;\r
1458         case NAND_CMD_ERASE1:\r
1459                 sprd_dolphin_erase(mtd, page_addr);\r
1460                 break;\r
1461         case NAND_CMD_READ0:\r
1462         case NAND_CMD_SEQIN:\r
1463                 dolphin->column = column;\r
1464                 dolphin->page = page_addr;\r
1465         default:\r
1466                 break;\r
1467         }\r
1468 }\r
1469 static void sprd_dolphin_nand_hwecc_ctl(struct mtd_info *mtd, int mode)\r
1470 {\r
1471         return; //do nothing\r
1472 }\r
1473 \r
1474 \r
1475 \r
1476 static void dolphin_set_timing_config(struct sprd_dolphin_nand_info *dolphin , uint32_t nfc_clk_MHz) {\r
1477         int index, array;\r
1478         u8 id_buf[8];\r
1479         u32 reg_val, temp_val;\r
1480         struct sprd_dolphin_nand_param * param;\r
1481 \r
1482         /* read id */\r
1483         sprd_dolphin_nand_read_id(dolphin, (uint32_t *)id_buf);\r
1484 \r
1485         /* get timing para */\r
1486         array = ARRAY_SIZE(sprd_dolphin_nand_param_tb);\r
1487         for (index = 0; index < array; index ++) {\r
1488                 param = sprd_dolphin_nand_param_tb + index;\r
1489                 if ((param->id[0] == id_buf[0])\r
1490                         && (param->id[1] == id_buf[1])\r
1491                         && (param->id[2] == id_buf[2])\r
1492                         && (param->id[3] == id_buf[3])\r
1493                         && (param->id[4] == id_buf[4]))\r
1494                         break;\r
1495         }\r
1496 \r
1497         if (index < array) {\r
1498                 reg_val = 0;\r
1499 \r
1500                 /* get acs value : 0ns */\r
1501                 reg_val |= ((2 & 0x1F) << NFC_ACS_OFFSET);\r
1502 \r
1503                 /* get ace value + 6ns read delay time, and rwl added */\r
1504                 temp_val = (param->ace_ns + 6) * nfc_clk_MHz / 1000;\r
1505                 if (((param->ace_ns * nfc_clk_MHz) % 1000)  != 0) {\r
1506                         temp_val++;\r
1507                 }\r
1508                 reg_val |= ((temp_val & 0x1F) << NFC_ACE_OFFSET);\r
1509 \r
1510                 /* get rws value : 20 ns */\r
1511                 temp_val = 20 * nfc_clk_MHz / 1000;\r
1512                 if (((param->ace_ns * nfc_clk_MHz) % 1000)  != 0) {\r
1513                         temp_val++;\r
1514                 }\r
1515                 reg_val |= ((temp_val & 0x3F) << NFC_RWS_OFFSET);\r
1516 \r
1517                 /* get rws value : 0 ns */\r
1518                 reg_val |= ((2 & 0x1F) << NFC_RWE_OFFSET);\r
1519 \r
1520                 /* get rwh value */\r
1521                 temp_val = (param->rwh_ns + 6) * nfc_clk_MHz / 1000;\r
1522                 if (((param->ace_ns * nfc_clk_MHz) % 1000)  != 0) {\r
1523                         temp_val++;\r
1524                 }\r
1525                 reg_val |= ((temp_val & 0x1F) << NFC_RWH_OFFSET);\r
1526 \r
1527                 /* get rwl value, 6 is read delay time*/\r
1528                 temp_val = (param->rwl_ns + 6) * nfc_clk_MHz / 1000;\r
1529                 if (((param->ace_ns * nfc_clk_MHz) % 1000)  != 0) {\r
1530                         temp_val++;\r
1531                 }\r
1532                 reg_val |= (temp_val & 0x3F);\r
1533 \r
1534                 DPRINT("nand timing val: 0x%x\n\r", reg_val);\r
1535 \r
1536                 sprd_dolphin_reg_write(NFC_TIMING_REG, reg_val);\r
1537         }\r
1538 }\r
1539 \r
1540 \r
1541 #ifdef DOLPHIN_UBOOT\r
1542 #define DOLPHIN_AHB_BASE SPRD_AHB_PHYS\r
1543 #define DOLPHIN_PIN_BASE SPRD_PIN_PHYS\r
1544 #define DOLPHIN_AHB_RST  (DOLPHIN_AHB_BASE + 0x0004)\r
1545 #define DOLPHIN_NANC_CLK_CFG  (DOLPHIN_AHB_BASE + 0x0060)\r
1546 \r
1547 #define DOLPHIN_ADISLAVE_BASE           SPRD_ADISLAVE_PHYS\r
1548 #define DOLPHIN_ANA_CTL_GLB_BASE                (DOLPHIN_ADISLAVE_BASE + 0x8800)\r
1549 \r
1550 #define DOLPHIN_NFC_REG_BASE  SPRD_NFC_PHYS\r
1551 #define DOLPHIN_NFC_TIMING_REG  (DOLPHIN_NFC_REG_BASE + 0x14)\r
1552 #define DOLPHIN_NFC_TIMEOUT_REG  (DOLPHIN_NFC_REG_BASE + 0x34)\r
1553 #endif\r
1554 \r
1555 #ifdef DOLPHIN_KERNEL\r
1556 #define DOLPHIN_AHB_BASE SPRD_AHB_BASE\r
1557 #define DOLPHIN_PIN_BASE SPRD_PIN_BASE\r
1558 #define DOLPHIN_AHB_RST  (DOLPHIN_AHB_BASE + 0x0004)\r
1559 #define DOLPHIN_NANC_CLK_CFG  (DOLPHIN_AHB_BASE + 0x0060)\r
1560 \r
1561 #define DOLPHIN_ADISLAVE_BASE           SPRD_ADISLAVE_BASE\r
1562 #define DOLPHIN_ANA_CTL_GLB_BASE                (DOLPHIN_ADISLAVE_BASE + 0x8800)\r
1563 \r
1564 #define DOLPHIN_NFC_REG_BASE  SPRD_NFC_BASE\r
1565 #define DOLPHIN_NFC_TIMING_REG  (DOLPHIN_NFC_REG_BASE + 0x14)\r
1566 #define DOLPHIN_NFC_TIMEOUT_REG  (DOLPHIN_NFC_REG_BASE + 0x34)\r
1567 #endif\r
1568 \r
1569 \r
1570 static void sprd_dolphin_nand_hw_init(struct sprd_dolphin_nand_info *dolphin)\r
1571 {\r
1572         int i = 0;\r
1573         uint32_t val;\r
1574 \r
1575         //sprd_dolphin_reg_and(DOLPHIN_NANC_CLK_CFG, ~(BIT(1) | BIT(0)));\r
1576         //sprd_dolphin_reg_or(DOLPHIN_NANC_CLK_CFG, BIT(0));\r
1577 \r
1578         sprd_dolphin_reg_or(DOLPHIN_AHB_BASE,BIT(19) | BIT(18) | BIT(17) | BIT(6));\r
1579 \r
1580         sprd_dolphin_reg_or(DOLPHIN_AHB_RST,BIT(9));\r
1581         mdelay(1);\r
1582         sprd_dolphin_reg_and(DOLPHIN_AHB_RST, ~(BIT(9)));\r
1583 \r
1584         val = (3)  | (4 << NFC_RWH_OFFSET) | (3 << NFC_RWE_OFFSET) | (3 << NFC_RWS_OFFSET) | (3 << NFC_ACE_OFFSET) | (3 << NFC_ACS_OFFSET);\r
1585         sprd_dolphin_reg_write(DOLPHIN_NFC_TIMING_REG, val);\r
1586         sprd_dolphin_reg_write(DOLPHIN_NFC_TIMEOUT_REG, 0xffffffff);\r
1587         //sprd_dolphin_reg_write(DOLPHIN_NFC_REG_BASE + 0x118, 3);\r
1588 \r
1589 #if 0\r
1590         sprd_tiger_reg_or(REG_PIN_NFRB, BIT_7);   //set PIN_NFRB pull up\r
1591         for (i=REG_PIN_NFWPN; i<=REG_PIN_NFD15; i+=4)\r
1592         {\r
1593                 sprd_tiger_reg_or( i, BIT_9);\r
1594                 sprd_tiger_reg_and(i, ~(BIT_8|BIT_10|BIT_6));\r
1595         }\r
1596 #endif\r
1597 \r
1598 #if 0\r
1599         sprd_dolphin_reg_or(DOLPHIN_PIN_BASE + REG_PIN_NFRB, BIT(7));\r
1600         for (i = REG_PIN_NFWPN; i <= REG_PIN_NFD15; i += 4)\r
1601         {\r
1602                 sprd_dolphin_reg_or(DOLPHIN_PIN_BASE + i, BIT(9));\r
1603                 sprd_dolphin_reg_and(DOLPHIN_PIN_BASE + i, ~(BIT(10) | BIT(8) | BIT(6)));\r
1604                 sprd_dolphin_reg_and(DOLPHIN_PIN_BASE + i, ~(BIT(4) | BIT(5)));\r
1605         }\r
1606 \r
1607 #endif\r
1608 \r
1609 #if 0\r
1610         sprd_dolphin_reg_or(DOLPHIN_PIN_BASE + REG_PIN_NFWPN, BIT(7) | BIT(8) | BIT(9));\r
1611         sprd_dolphin_reg_and(DOLPHIN_PIN_BASE + REG_PIN_NFWPN, ~(BIT(4) | BIT(5)));\r
1612         sprd_dolphin_reg_or(DOLPHIN_PIN_BASE + REG_PIN_NFRB, BIT(7) | BIT(8) | BIT(9));\r
1613         sprd_dolphin_reg_and(DOLPHIN_PIN_BASE + REG_PIN_NFRB, ~(BIT(4) | BIT(5)));\r
1614         for(i = 0; i < 22; ++i)\r
1615         {\r
1616                 sprd_dolphin_reg_or(DOLPHIN_PIN_BASE + REG_PIN_NFCLE + (i << 2), BIT(7) | BIT(8) | BIT(9));\r
1617                 sprd_dolphin_reg_and(DOLPHIN_PIN_BASE + REG_PIN_NFCLE + (i << 2), ~(BIT(4) | BIT(5)));\r
1618         }\r
1619 #endif\r
1620 \r
1621 #if 0\r
1622         i = sprd_dolphin_reg_read(DOLPHIN_ANA_CTL_GLB_BASE+0x3c);\r
1623         i &= ~0x7F00;\r
1624         i |= 0x38 << 8;\r
1625         sprd_dolphin_reg_write(DOLPHIN_ANA_CTL_GLB_BASE + 0x3c, i);\r
1626 \r
1627         i = sprd_dolphin_reg_read(DOLPHIN_ANA_CTL_GLB_BASE+0x20);\r
1628         i &= ~0xFF;\r
1629         i |= 0x38 << 0;\r
1630         sprd_dolphin_reg_write(DOLPHIN_ANA_CTL_GLB_BASE + 0x20, i);\r
1631 #endif\r
1632         \r
1633         //close write protect\r
1634         sprd_dolphin_nand_wp_en(dolphin, 0);\r
1635 }\r
1636 \r
1637 \r
1638 int board_nand_init(struct nand_chip *chip)\r
1639 {\r
1640         //DPRINT("board_nand_init\r\n");\r
1641 \r
1642         sprd_dolphin_nand_hw_init(&g_dolphin);\r
1643 \r
1644         chip->select_chip = sprd_dolphin_select_chip;\r
1645         chip->cmdfunc = sprd_dolphin_nand_cmdfunc;\r
1646         chip->read_byte = sprd_dolphin_read_byte;\r
1647         chip->read_word = sprd_dolphin_read_word;\r
1648         chip->waitfunc = sprd_dolphin_waitfunc;\r
1649         chip->ecc.mode = NAND_ECC_HW;\r
1650         chip->ecc.calculate = sprd_dolphin_ecc_calculate;\r
1651         chip->ecc.hwctl = sprd_dolphin_nand_hwecc_ctl;\r
1652         \r
1653         chip->ecc.correct = sprd_dolphin_ecc_correct;\r
1654         chip->ecc.read_page = sprd_dolphin_read_page;\r
1655         chip->ecc.read_page_raw = sprd_dolphin_read_page_raw;\r
1656         chip->ecc.write_page = sprd_dolphin_write_page;\r
1657         chip->ecc.write_page_raw = sprd_dolphin_write_page_raw;\r
1658         chip->ecc.read_oob = sprd_dolphin_read_oob;\r
1659         chip->ecc.write_oob = sprd_dolphin_write_oob;\r
1660         chip->erase_cmd = sprd_dolphin_erase;\r
1661         \r
1662         chip->ecc.bytes = CONFIG_SYS_NAND_ECCBYTES;\r
1663         g_dolphin.ecc_mode = ecc_mode_convert(CONFIG_SYS_NAND_ECC_MODE);\r
1664         g_dolphin.nand = chip;\r
1665 \r
1666         dolphin_set_timing_config(&g_dolphin, 64);      /* 153 is current clock 153MHz */\r
1667 \r
1668         chip->eccbitmode = CONFIG_SYS_NAND_ECC_MODE;\r
1669         chip->ecc.size = CONFIG_SYS_NAND_ECCSIZE;\r
1670 \r
1671         chip->chip_delay = 20;\r
1672         chip->priv = &g_dolphin;\r
1673 \r
1674         //printf("v2   board eccbitmode %d\n", chip->eccbitmode);\r
1675 \r
1676         chip->options = NAND_BUSWIDTH_16;\r
1677 \r
1678         return 0;\r
1679 }\r
1680 \r
1681 #ifdef DOLPHIN_UBOOT\r
1682 #ifndef CONFIG_NAND_SPL\r
1683 void McuReadNandType(unsigned char *array)\r
1684 {\r
1685 \r
1686 }\r
1687 #endif\r
1688 \r
1689 static unsigned long nfc_read_status(void)\r
1690 {\r
1691         unsigned long status = 0;\r
1692 \r
1693         sprd_dolphin_nand_read_status(&g_dolphin);      \r
1694         status = s_oob_data[0];\r
1695 \r
1696         return status;\r
1697 }\r
1698 \r
1699 #ifndef CONFIG_NAND_SPL\r
1700 static int sprd_scan_one_block(int blk, int erasesize, int writesize)\r
1701 {\r
1702         int i, cmd;\r
1703         int status = 1, ii;\r
1704         u32 size = 0;\r
1705         int oobsize = mtdoobsize;\r
1706         int column, page_addr;\r
1707 \r
1708         page_addr = blk * (erasesize / writesize);\r
1709         for (ii = 0; ii < 2; ii ++) {\r
1710                 DPRINT("please debug here : %s %d\n", __FUNCTION__, __LINE__);\r
1711                 sprd_dolphin_nand_ins_init(&g_dolphin);\r
1712                 sprd_dolphin_nand_ins_add(NAND_MC_CMD(NAND_CMD_READ0), &g_dolphin);\r
1713                 sprd_dolphin_nand_ins_add(NAND_MC_CMD(NAND_CMD_READSTART), &g_dolphin);\r
1714                 if ((s_oob_data[0] != 0xff) || (s_oob_data[1] != 0xff))\r
1715                         break;\r
1716         } //for (ii = 0; ii < 2; ii ++)\r
1717 \r
1718         if ((s_oob_data[0] == 0xff) && (s_oob_data[1] == 0xff))\r
1719                 status = 0; //good block\r
1720         else\r
1721                 status = 1; //bad block\r
1722 \r
1723         return status;\r
1724 }\r
1725 \r
1726 static unsigned long nand_ctl_erase_block(int blk, int erasesize, int writesize)\r
1727 {\r
1728         int cmd, status;\r
1729         int page_addr;\r
1730 \r
1731         page_addr = blk * (erasesize / writesize);\r
1732         sprd_dolphin_erase(&g_dolphin, page_addr);\r
1733         status = nfc_read_status();\r
1734 \r
1735         return status;\r
1736 }\r
1737 #endif\r
1738 \r
1739 \r
1740 #ifndef CONFIG_NAND_SPL\r
1741 void nand_scan_patition(int blocks, int erasesize, int writesize)\r
1742 {\r
1743         int blk;\r
1744         int ret;\r
1745         int status;\r
1746 \r
1747         //read_chip_id();\r
1748         for (blk = 0; blk < blocks; blk ++) {\r
1749                 ret = sprd_scan_one_block(blk, erasesize, writesize);\r
1750                 if (ret != 0) {\r
1751                         DPRINT("\n%d is bad, scrub to erase it, ", blk);\r
1752                         ret = nand_ctl_erase_block(blk, erasesize, writesize);\r
1753                         DPRINT("0x%02x\n", ret);\r
1754                 } else {\r
1755                         ret = nand_ctl_erase_block(blk, erasesize, writesize);\r
1756                         DPRINT("erasing block : %d    %d % \r", blk, (blk * 100 ) / blocks);\r
1757                 }\r
1758         }\r
1759 }\r
1760 int nand_scan_block(int block, int erasesize, int writesize){\r
1761         int ret = 0;\r
1762         ret = nand_ctl_erase_block(block, erasesize, writesize);\r
1763         ret = ret&1;\r
1764 \r
1765         return ret;\r
1766 }\r
1767 #endif\r
1768 #endif  //DOLPHIN_UBOOT end\r
1769 \r
1770 \r
1771 \r
1772 #ifdef DOLPHIN_KERNEL\r
1773 extern int parse_mtd_partitions(struct mtd_info *master, const char **types,\r
1774                                 struct mtd_partition **pparts,\r
1775                                 struct mtd_part_parser_data *data);\r
1776 \r
1777 static struct mtd_info *sprd_mtd = NULL;\r
1778 #ifdef CONFIG_MTD_CMDLINE_PARTS\r
1779 const char *part_probes[] = { "cmdlinepart", NULL };\r
1780 #endif\r
1781 \r
1782 static int sprd_nand_dma_init(struct sprd_dolphin_nand_info *dolphin)\r
1783 {\r
1784         dma_addr_t phys_addr = 0;\r
1785         void *virt_ptr = 0;\r
1786         virt_ptr = dma_alloc_coherent(NULL, dolphin->write_size, &phys_addr, GFP_KERNEL);\r
1787         if (virt_ptr == NULL) {\r
1788                 DPRINT(KERN_ERR "NAND - Failed to allocate memory for DMA main buffer\n");\r
1789                 return -ENOMEM;\r
1790         }\r
1791         dolphin->v_mbuf = (u32)virt_ptr;\r
1792         dolphin->p_mbuf = (u32)phys_addr;\r
1793 \r
1794         virt_ptr = dma_alloc_coherent(NULL, dolphin->oob_size, &phys_addr, GFP_KERNEL);\r
1795         if (virt_ptr == NULL) {\r
1796                 DPRINT(KERN_ERR "NAND - Failed to allocate memory for DMA oob buffer\n");\r
1797                 dma_free_coherent(NULL, dolphin->write_size, (void *)dolphin->v_mbuf, (dma_addr_t)dolphin->p_mbuf);\r
1798                 return -ENOMEM;\r
1799         }\r
1800         dolphin->v_oob = (u32)virt_ptr;\r
1801         dolphin->p_oob = (u32)phys_addr;\r
1802         return 0;\r
1803 }\r
1804 static void sprd_nand_dma_deinit(struct sprd_dolphin_nand_info *dolphin)\r
1805 {\r
1806         dma_free_coherent(NULL, dolphin->write_size, (void *)dolphin->v_mbuf, (dma_addr_t)dolphin->p_mbuf);\r
1807         dma_free_coherent(NULL, dolphin->write_size, (void *)dolphin->v_oob, (dma_addr_t)dolphin->p_oob);\r
1808 }\r
1809 static int sprd_nand_probe(struct platform_device *pdev)\r
1810 {\r
1811         struct nand_chip *this;\r
1812         struct resource *regs = NULL;\r
1813         struct mtd_partition *partitions = NULL;\r
1814         int num_partitions = 0;\r
1815         int ret = 0;\r
1816 \r
1817         regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);\r
1818         if (!regs) {\r
1819                 dev_err(&pdev->dev,"resources unusable\n");\r
1820                 goto prob_err;\r
1821         }\r
1822 \r
1823         memset(&g_dolphin, 0 , sizeof(g_dolphin));\r
1824 \r
1825         platform_set_drvdata(pdev, &g_dolphin);\r
1826         g_dolphin.pdev = pdev;\r
1827 \r
1828         sprd_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL);\r
1829         this = (struct nand_chip *)(&sprd_mtd[1]);\r
1830         memset((char *)sprd_mtd, 0, sizeof(struct mtd_info));\r
1831         memset((char *)this, 0, sizeof(struct nand_chip));\r
1832 \r
1833         sprd_mtd->priv = this;\r
1834 \r
1835         this->options |= NAND_BUSWIDTH_16;\r
1836         this->options |= NAND_NO_READRDY;\r
1837 \r
1838         board_nand_init(this);\r
1839 \r
1840 \r
1841     if (sprd_dolphin_nand_reset(&g_dolphin) != 0)\r
1842     {\r
1843         ret = -ENXIO;\r
1844         printk("nand reset failed!!!!!!!!!!!!!\n");\r
1845         goto prob_err;\r
1846     }\r
1847     msleep(1);\r
1848 \r
1849     if (sprd_dolphin_nand_read_id(&g_dolphin, (uint32_t *)s_oob_data) != 0)\r
1850     {\r
1851         ret = -ENXIO;\r
1852         printk("nand read id failed, no nand device!!!!!!!!!!!!!\n");\r
1853         goto prob_err;\r
1854     }\r
1855     printk("nand read id ok, nand exists!!!!!!!!!!!!!\n");\r
1856 \r
1857         //nand_scan(sprd_mtd, 1);\r
1858         /* first scan to find the device and get the page size */\r
1859         if (nand_scan_ident(sprd_mtd, 1, NULL)) {\r
1860                 ret = -ENXIO;\r
1861                 goto prob_err;\r
1862         }\r
1863         sprd_dolphin_nand_read_id(&g_dolphin, (uint32_t *)s_oob_data);\r
1864         nand_hardware_config(sprd_mtd, this, s_oob_data);\r
1865         if(sprd_nand_dma_init(&g_dolphin) != 0) {\r
1866                 return -ENOMEM;\r
1867         }\r
1868         \r
1869         //this->IO_ADDR_R = g_dolphin.v_mbuf;\r
1870         //this->IO_ADDR_W = g_dolphin.v_mbuf;\r
1871 \r
1872         /* second phase scan */\r
1873         if (nand_scan_tail(sprd_mtd)) {\r
1874                 ret = -ENXIO;\r
1875                 goto prob_err;\r
1876         }\r
1877 \r
1878         sprd_mtd->name = "sprd-nand";\r
1879         num_partitions = parse_mtd_partitions(sprd_mtd, part_probes, &partitions, 0);\r
1880 \r
1881         if ((!partitions) || (num_partitions == 0)) {\r
1882                 DPRINT("No parititions defined, or unsupported device.\n");\r
1883                 goto release;\r
1884         }\r
1885 \r
1886 #ifdef CONFIG_MTD_CMDLINE_PARTS\r
1887         mtd_device_register(sprd_mtd, partitions, num_partitions);\r
1888 #endif\r
1889 \r
1890         return 0;\r
1891 release:\r
1892         nand_release(sprd_mtd);\r
1893         sprd_nand_dma_deinit(&g_dolphin);\r
1894 prob_err:\r
1895         sprd_dolphin_reg_and(DOLPHIN_AHB_BASE,~(BIT(17) | BIT(18) | BIT(19) | BIT(6)));\r
1896         kfree(sprd_mtd);\r
1897         return ret;\r
1898 }\r
1899 \r
1900 static int sprd_nand_remove(struct platform_device *pdev)\r
1901 {\r
1902         platform_set_drvdata(pdev, NULL);\r
1903         nand_release(sprd_mtd);\r
1904         sprd_nand_dma_deinit(&g_dolphin);\r
1905         kfree(sprd_mtd);\r
1906         return 0;\r
1907 }\r
1908 \r
1909 #ifdef CONFIG_PM\r
1910 static int sprd_nand_suspend(struct platform_device *dev, pm_message_t pm)\r
1911 {\r
1912         //nothing to do\r
1913         return 0;\r
1914 }\r
1915 \r
1916 static int sprd_nand_resume(struct platform_device *dev)\r
1917 {\r
1918         sprd_dolphin_reg_write(NFC_TIMING_REG, NFC_DEFAULT_TIMING);\r
1919         sprd_dolphin_reg_write(NFC_TIMEOUT_REG, 0x80400000);\r
1920         //close write protect\r
1921         sprd_dolphin_nand_wp_en(&g_dolphin, 0);\r
1922         return 0;\r
1923 }\r
1924 #else\r
1925 #define sprd_nand_suspend NULL\r
1926 #define sprd_nand_resume NULL\r
1927 #endif\r
1928 \r
1929 static struct platform_driver sprd_nand_driver = {\r
1930         .probe          = sprd_nand_probe,\r
1931         .remove         = sprd_nand_remove,\r
1932         .suspend        = sprd_nand_suspend,\r
1933         .resume         = sprd_nand_resume,\r
1934         .driver         = {\r
1935                 .name   = "sprd-nand",\r
1936                 .owner  = THIS_MODULE,\r
1937         },\r
1938 };\r
1939 \r
1940 static int __init sprd_nand_init(void)\r
1941 {\r
1942         return platform_driver_register(&sprd_nand_driver);\r
1943 }\r
1944 \r
1945 static void __exit sprd_nand_exit(void)\r
1946 {\r
1947         platform_driver_unregister(&sprd_nand_driver);\r
1948 }\r
1949 \r
1950 module_init(sprd_nand_init);\r
1951 module_exit(sprd_nand_exit);\r
1952 \r
1953 MODULE_LICENSE("GPL");\r
1954 MODULE_AUTHOR("giya.li@spreadtrum.com");\r
1955 MODULE_DESCRIPTION("SPRD dolphin MTD NAND driver");\r
1956 MODULE_ALIAS("platform:sprd-nand");\r
1957 \r
1958 #endif\r
1959 \r
1960 \r
1961 \r
1962 \r
1963 \r
1964 \r
1965 \r