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