2 * Copyright (C) 2012 Spreadtrum Communications Inc.
\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
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
14 #define DOLPHIN_UBOOT
\r
16 #ifdef DOLPHIN_UBOOT
\r
20 #include <asm/errno.h>
\r
23 #include <asm/arch/sci_types.h>
\r
24 #include <asm/arch/pinmap.h>
\r
25 #include <asm/arch/bits.h>
\r
28 #include <linux/mtd/nand.h>
\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
41 #ifdef CONFIG_NAND_SPL
\r
45 int cnt = 200 * (x); \
\r
46 for (i=0; i<cnt; i++);\
\r
50 #define mdelay(_ms) udelay((_ms)*1000)
\r
54 #if defined(CONFIG_NAND_SPL) || !defined(NAND_DBG)
\r
55 #define DPRINT(arg...) do{}while(0)
\r
57 #define DPRINT printf
\r
59 #define ASSERT(cond) { assert(cond); }
\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
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
88 #define NAND_MC_BUFFER_SIZE (24)
\r
90 static int mtderasesize = 0;
\r
91 static int mtdwritesize = 0;
\r
92 static int mtdoobsize = 0;
\r
94 #endif //DOLPHIN_UBOOT end
\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
114 #include "sc8830_nand.h"
\r
115 #define DPRINT printk
\r
117 #endif //DOLPHIN_KERNEL
\r
121 #define SPRD_ASSERT(cond) { if (!(cond)) while(1); }
\r
122 #define STATIC_FUNC static
\r
124 #include "sprd_nand_param.h"
\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
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
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
149 #define IRQ_TIMEOUT 100//unit:ms,IRQ timeout value
\r
150 #define DRIVER_NAME "sc8830_nand"
\r
153 enum NAND_ERR_CORRECT_S {
\r
154 NAND_FATAL_ERROR=0,
\r
155 NAND_ERR_NEED_RETRY,
\r
160 enum NAND_HANDLE_STATUS_S {
\r
161 NAND_HANDLE_DONE=0,
\r
162 NAND_HANDLE_TIMEOUT,
\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
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
174 //#define NAND_IRQ_EN
\r
176 #include <linux/completion.h>
\r
177 #include <mach/irqs.h>
\r
179 static struct completion nfc_op_completion;
\r
180 STATIC_FUNC void nfc_wait_op_done(void);
\r
184 struct sprd_dolphin_nand_info {
\r
185 struct mtd_info *mtd;
\r
186 struct nand_chip *nand;
\r
188 #ifdef DOLPHIN_UBOOT
\r
189 struct device *pdev;
\r
192 #ifdef DOLPHIN_KERNEL
\r
193 struct platform_device *pdev;
\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
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
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
217 uint16_t _buf_tail;
\r
218 uint8_t ins_num;//instruction number
\r
219 uint32_t ins[NAND_MC_BUFFER_SIZE >> 1];
\r
223 #define mtd_to_dolphin(m) (&g_dolphin)
\r
225 //gloable variable
\r
226 static struct nand_ecclayout sprd_dolphin_nand_oob_default = {
\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
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
243 STATIC_FUNC uint32_t sprd_dolphin_reg_read(uint32_t addr)
\r
245 return readl(addr);
\r
247 STATIC_FUNC void sprd_dolphin_reg_write(uint32_t addr, uint32_t val)
\r
251 STATIC_FUNC void sprd_dolphin_reg_or(uint32_t addr, uint32_t val)
\r
253 sprd_dolphin_reg_write(addr, sprd_dolphin_reg_read(addr) | val);
\r
255 STATIC_FUNC void sprd_dolphin_reg_and(uint32_t addr, uint32_t mask)
\r
257 sprd_dolphin_reg_write(addr, sprd_dolphin_reg_read(addr) & mask);
\r
259 STATIC_FUNC void sprd_dolphin_nand_int_clr(uint32_t bit_clear)
\r
261 sprd_dolphin_reg_write(NFC_INT_REG, bit_clear);
\r
264 STATIC_FUNC void nfc_clear_interrupt(void)
\r
266 uint32_t value = 0;
\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
271 //value = NFC_CMD_CLR;
\r
272 //sprd_dolphin_reg_or(NFC_START_REG, value); /* clear all interrupt status */
\r
275 STATIC_FUNC void nfc_enable_interrupt(void)
\r
277 uint32_t value = 0;
\r
279 value = (INT_TO_EN | INT_DONE_EN);
\r
280 sprd_dolphin_reg_or(NFC_INT_REG, value); /* clear all interrupt status */
\r
283 STATIC_FUNC void nfc_disable_interrupt(void)
\r
285 uint32_t value = 0;
\r
287 value = ~(INT_TO_EN | INT_DONE_EN);
\r
288 sprd_dolphin_reg_and(NFC_INT_REG, value); /* clear all interrupt status */
\r
291 unsigned int ecc_mode_convert(uint32_t mode)
\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
335 /* get acs value : 0ns */
\r
336 reg_val |= ((2 & 0x1F) << NFC_ACS_OFFSET);
\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
343 reg_val |= ((temp_val & 0x1F) << NFC_ACE_OFFSET);
\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
350 reg_val |= ((temp_val & 0x3F) << NFC_RWS_OFFSET);
\r
352 /* get rws value : 0 ns */
\r
353 reg_val |= ((2 & 0x1F) << NFC_RWE_OFFSET);
\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
360 reg_val |= ((temp_val & 0x1F) << NFC_RWH_OFFSET);
\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
367 reg_val |= (temp_val & 0x3F);
\r
369 DPRINT("%s nand timing val: 0x%x\n\r", __func__, reg_val);
\r
371 sprd_dolphin_reg_write(NFC_TIMING_REG, reg_val);
\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
386 uint32_t info_size;
\r
387 uint32_t magic_num; //0xaa55a5a5
\r
388 uint32_t ecc_value[27];
\r
390 void boad_nand_param_init(struct sprd_dolphin_nand_info *dolphin, struct nand_chip *chip, uint8 *id)
\r
393 uint32_t writesize;
\r
395 uint32_t erasesize;
\r
398 /* The 4th id byte is the important one */
\r
400 writesize = 1024 << (extid & 0x3);
\r
403 oobsize = (8 << (extid & 0x01)) * (writesize >> 9);
\r
405 /* Calc blocksize. Blocksize is multiples of 64KiB */
\r
406 erasesize = (64 * 1024) << (extid & 0x03);
\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
422 chip->options |= NAND_BUSWIDTH_16;
\r
426 chip->options &= ~NAND_BUSWIDTH_16;
\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
436 void nand_hardware_config(struct mtd_info *mtd, struct nand_chip *chip)
\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
444 sprd_dolphin_nand_reset(dolphin);
\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
450 param = SprdGetNandParam(id);
\r
452 if (param != NULL) {
\r
453 dolphin->param = param;
\r
454 oob = ¶m->sOOB;
\r
455 timing = ¶m->sTiming;
\r
457 dolphin_set_timing_config(timing, SPRD_NAND_CLOCK);
\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
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
475 chip->ecc.bytes = (oob->nEccBits * 14 + 7) / 8;
\r
476 #ifdef DOLPHIN_UBOOT
\r
477 chip->eccbitmode = oob->nEccBits;
\r
479 if(param->nBusWidth)
\r
481 chip->options |= NAND_BUSWIDTH_16;
\r
485 chip->options &= ~NAND_BUSWIDTH_16;
\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
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
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
506 used_len = (14 * oob->nEccBits + 7) / 8 + oob->nInfoSize;
\r
507 if (sector_num > ARRAY_SIZE(layout->oobfree)) {
\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
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
524 layout->oobavail = oobfree_len;
\r
525 layout->eccbytes = used_len * sector_num;
\r
528 void nand_hardware_config(struct mtd_info *mtd, struct nand_chip *chip, uint8_t id[5])
\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
535 param = SprdGetNandParam(id);
\r
537 if (param != NULL) {
\r
538 dolphin->param = param;
\r
539 oob = ¶m->sOOB;
\r
540 timing = ¶m->sTiming;
\r
542 dolphin_set_timing_config(timing, SPRD_NAND_CLOCK);
\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
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
560 chip->ecc.bytes = (oob->nEccBits * 14 + 7) / 8;
\r
561 #ifdef DOLPHIN_UBOOT
\r
562 chip->eccbitmode = oob->nEccBits;
\r
564 if(param->nBusWidth)
\r
566 chip->options |= NAND_BUSWIDTH_16;
\r
570 chip->options &= ~NAND_BUSWIDTH_16;
\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
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
586 struct sprd_nand_oob oob_tmp;
\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
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
610 chip->ecc.layout = &sprd_dolphin_nand_oob_default;
\r
611 #ifdef DOLPHIN_UBOOT
\r
612 chip->eccbitmode = CONFIG_SYS_NAND_ECC_MODE;
\r
614 if(chip->chipsize > (128 << 20)) {
\r
615 dolphin->a_cycles = 5;
\r
618 dolphin->a_cycles = 4;
\r
623 #endif //end CONFIG_NAND_SPL
\r
627 #ifdef DOLPHIN_UBOOT
\r
628 #ifndef CONFIG_NAND_SPL
\r
634 uint8_t dir; //if dir is 0, read dadta from NFC buffer, if 1, write data to NFC buffer
\r
637 } sprd_dolphin_nand_data_param;
\r
639 STATIC_FUNC unsigned int sprd_dolphin_data_trans(sprd_dolphin_nand_data_param *param)
\r
644 cfg0 = NFC_ONLY_MST_MODE | MAIN_SPAR_APT | NFC_WPN;
\r
649 if(param->m_sct != 0)
\r
651 cfg0 |= (param->m_sct - 1) << SECTOR_NUM_OFFSET;
\r
653 cfg1 |= (param->m_size - 1);
\r
654 sprd_dolphin_reg_write(NFC_MAIN_ADDR_REG, (uint32_t)param->m_buf);
\r
656 if(param->s_sct != 0)
\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
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
671 void sprd_ecc_ctrl(struct sprd_ecc_param *param, uint32_t dir)
\r
676 cfg0 = NFC_ONLY_ECC_MODE | MAIN_SPAR_APT;
\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
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
696 unsigned int sprd_ecc_encode(struct sprd_ecc_param *param)
\r
698 struct sprd_dolphin_nand_info *dolphin;
\r
699 sprd_dolphin_nand_data_param d_param;
\r
701 dolphin = &g_dolphin;
\r
702 memset(&d_param, 0, sizeof(d_param));
\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
709 d_param.m_size = param->m_size;
\r
710 d_param.s_size = param->sp_size;
\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
715 sprd_dolphin_data_trans(&d_param);
\r
716 sprd_ecc_ctrl(param, 1);
\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
723 sprd_dolphin_data_trans(&d_param); //read the ecc value from nfc buffer
\r
726 #endif //CONFIG_NAND_SPL end
\r
727 #endif //DOLPHIN_UBOOT END
\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
734 dolphin->ins_num = 0;
\r
736 STATIC_FUNC void sprd_dolphin_nand_ins_add(uint16_t ins, struct sprd_dolphin_nand_info *dolphin)
\r
738 uint16_t *buf = (uint16_t *)dolphin->ins;
\r
739 if(dolphin->ins_num >= NAND_MC_BUFFER_SIZE)
\r
743 *(buf + dolphin->ins_num) = ins;
\r
744 dolphin->ins_num++;
\r
747 STATIC_FUNC void sprd_dolphin_nand_ins_exec(struct sprd_dolphin_nand_info *dolphin)
\r
752 for(i = 0; i < ((dolphin->ins_num + 1) >> 1); i++)
\r
754 sprd_dolphin_reg_write(NFC_INST0_REG + (i << 2), dolphin->ins[i]);
\r
756 cfg0 = sprd_dolphin_reg_read(NFC_CFG0_REG);
\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
778 STATIC_FUNC int sprd_dolphin_nand_wait_finish(struct sprd_dolphin_nand_info *dolphin)
\r
780 unsigned int value;
\r
781 unsigned int counter = 0;
\r
782 while((counter < NFC_TIMEOUT_VAL/*time out*/))
\r
784 value = sprd_dolphin_reg_read(NFC_INT_REG);
\r
785 if(value & INT_DONE_RAW)
\r
791 sprd_dolphin_reg_write(NFC_INT_REG, 0xf00); //clear all interrupt status
\r
792 if(counter >= NFC_TIMEOUT_VAL)
\r
800 STATIC_FUNC void sprd_dolphin_nand_wp_en(struct sprd_dolphin_nand_info *dolphin, int en)
\r
804 dolphin->wp_en = 1;
\r
808 dolphin->wp_en = 0;
\r
811 STATIC_FUNC void sprd_dolphin_select_chip(struct mtd_info *mtd, int chip)
\r
813 struct sprd_dolphin_nand_info *dolphin = mtd_to_dolphin(mtd);
\r
814 if(chip < 0) { //for release caller
\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
824 STATIC_FUNC void sprd_dolphin_nand_read_status(struct sprd_dolphin_nand_info *dolphin)
\r
827 //DPRINT("%s enter\n", __func__);
\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
842 //DPRINT("%s leave\n", __func__);
\r
844 STATIC_FUNC int sprd_dolphin_nand_read_id(struct sprd_dolphin_nand_info *dolphin, uint32_t *buf)
\r
846 //DPRINT("%s enter\n", __func__);
\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
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
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
866 //DPRINT("%s leave\n", __func__);
\r
870 STATIC_FUNC int sprd_dolphin_nand_reset(struct sprd_dolphin_nand_info *dolphin)
\r
872 //DPRINT("%s enter\n", __func__);
\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
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
886 //DPRINT("%s leave\n", __func__);
\r
890 STATIC_FUNC u32 sprd_dolphin_get_decode_sts(u32 index)
\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
899 if((err & ECC_ALL_FF))
\r
901 err &= ERR_ERR_NUM0_MASK;
\r
911 #ifdef DOLPHIN_UBOOT
\r
913 STATIC_FUNC int sprd_dolphin_nand_read_lp(struct mtd_info *mtd,uint8_t *mbuf, uint8_t *sbuf,uint32_t raw)
\r
915 struct sprd_dolphin_nand_info *dolphin = mtd_to_dolphin(mtd);
\r
916 struct nand_chip *chip = dolphin->nand;
\r
918 uint32_t page_addr;
\r
924 int size = 0 ,sct_size;
\r
926 uint8_t ecc_bit=0 ;
\r
928 page_addr = dolphin->page;
\r
931 column = mtd->writesize;
\r
937 if(chip->options & NAND_BUSWIDTH_16)
\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
946 sprd_dolphin_nand_ins_add(NAND_MC_ADDR(column & 0xff), dolphin);
\r
948 sprd_dolphin_nand_ins_add(NAND_MC_ADDR(page_addr & 0xff), dolphin);
\r
950 sprd_dolphin_nand_ins_add(NAND_MC_ADDR(page_addr & 0xff), dolphin);
\r
952 if (5 == dolphin->a_cycles)// five address cycles
\r
955 sprd_dolphin_nand_ins_add(NAND_MC_ADDR(page_addr & 0xff), dolphin);
\r
957 sprd_dolphin_nand_ins_add(NAND_MC_CMD(NAND_CMD_READSTART), dolphin);
\r
959 sprd_dolphin_nand_ins_add(NFC_MC_WRB0_ID, dolphin); //wait rb
\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
972 sprd_dolphin_nand_ins_add(NAND_MC_MRDT, dolphin);
\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
979 cfg0 |= ECC_EN | DETECT_ALL_FF;
\r
981 if(chip->options & NAND_BUSWIDTH_16)
\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
988 #ifndef CONFIG_NAND_SPL
\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
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
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
1013 cfg1 |= (dolphin->m_size - 1);
\r
1014 sprd_dolphin_reg_write(NFC_MAIN_ADDR_REG, (uint32_t)mbuf);
\r
1018 cfg1 |= (dolphin->s_size - 1);
\r
1019 sprd_dolphin_reg_write(NFC_MAIN_ADDR_REG, (uint32_t)sbuf);
\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
1027 sprd_dolphin_nand_ins_exec(dolphin);
\r
1028 sprd_dolphin_nand_wait_finish(dolphin);
\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
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
1043 if(ecc_bit > chip->eccbitmode){
\r
1045 DPRINT("%s spare area ecc check err\n",__func__);
\r
1051 mtd->ecc_stats.failed++;
\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
1067 if(ecc_bit > chip->eccbitmode){
\r
1069 DPRINT("%s main+spare area ecc check err\n",__func__);
\r
1075 mtd->ecc_stats.failed++;
\r
1078 mbuf[size] = 0xff;
\r
1083 mtd->ecc_stats.corrected += err;
\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
1094 struct sprd_dolphin_nand_info *dolphin = mtd_to_dolphin(mtd);
\r
1095 struct nand_chip *chip = dolphin->nand;
\r
1097 uint32_t page_addr;
\r
1101 page_addr = dolphin->page;
\r
1106 column = mtd->writesize;
\r
1108 if(chip->options & NAND_BUSWIDTH_16)
\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
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
1120 sprd_dolphin_nand_ins_add(NAND_MC_ADDR(page_addr & 0xff), dolphin);
\r
1122 if (5 == dolphin->a_cycles)// five address cycles
\r
1125 sprd_dolphin_nand_ins_add(NAND_MC_ADDR(page_addr & 0xff), dolphin);
\r
1128 sprd_dolphin_nand_ins_add(NAND_MC_MWDT, dolphin);
\r
1131 sprd_dolphin_nand_ins_add(NAND_MC_SWDT, dolphin);
\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
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
1143 if(chip->options & NAND_BUSWIDTH_16)
\r
1145 cfg0 |= BUS_WIDTH;
\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
1150 #ifndef CONFIG_NAND_SPL
\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
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
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
1176 cfg1 |= dolphin->m_size - 1;
\r
1177 sprd_dolphin_reg_write(NFC_MAIN_ADDR_REG, (uint32_t)mbuf);
\r
1181 cfg1 |= dolphin->s_size - 1;
\r
1182 sprd_dolphin_reg_write(NFC_MAIN_ADDR_REG, (uint32_t)sbuf);
\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
1196 #ifdef DOLPHIN_KERNEL
\r
1198 #ifdef NAND_IRQ_EN
\r
1199 STATIC_FUNC void sprd_dolphin_nand_ins_exec_irq(struct sprd_dolphin_nand_info *dolphin)
\r
1203 uint32_t value = 0;
\r
1205 //DPRINT("%s enter\n", __func__);
\r
1207 for(i = 0; i < ((dolphin->ins_num + 1) >> 1); i++)
\r
1209 sprd_dolphin_reg_write(NFC_INST0_REG + (i << 2), dolphin->ins[i]);
\r
1211 cfg0 = sprd_dolphin_reg_read(NFC_CFG0_REG);
\r
1212 if(dolphin->wp_en)
\r
1228 sprd_dolphin_reg_write(NFC_CFG0_REG, cfg0);
\r
1230 nfc_clear_interrupt();
\r
1231 nfc_enable_interrupt();
\r
1233 sprd_dolphin_reg_write(NFC_START_REG, NFC_START);
\r
1235 //DPRINT("%s leave\n", __func__);
\r
1238 STATIC_FUNC int sprd_dolphin_nand_wait_finish_irq(struct sprd_dolphin_nand_info *dolphin)
\r
1240 unsigned int value;
\r
1241 unsigned int counter = 0;
\r
1243 //DPRINT("%s enter\n", __func__);
\r
1245 nfc_wait_op_done();
\r
1246 if(handle_status==NAND_HANDLE_DONE)
\r
1248 ret_irq_en=NAND_NO_ERROR;
\r
1250 else if(handle_status==NAND_HANDLE_TIMEOUT)
\r
1252 ret_irq_en=NAND_ERR_NEED_RETRY;
\r
1254 else if(handle_status==NAND_HANDLE_ERR)
\r
1256 ret_irq_en=NAND_ERR_NEED_RETRY;
\r
1259 //DPRINT("%s leave\n", __func__);
\r
1264 STATIC_FUNC void nfc_wait_op_done(void)
\r
1266 if (!wait_for_completion_timeout(&nfc_op_completion, msecs_to_jiffies(IRQ_TIMEOUT)))
\r
1268 handle_status=NAND_HANDLE_ERR;
\r
1269 DPRINT(KERN_ERR "%s, wait irq timeout\n", __func__);
\r
1273 STATIC_FUNC irqreturn_t nfc_irq_handler(int irq, void *dev_id)
\r
1275 unsigned int value;
\r
1277 //DPRINT("%s enter\n", __func__); /*diable irq*/
\r
1278 nfc_disable_interrupt();
\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
1286 DPRINT(KERN_ALERT "%s, timeout occur NFC_INT_REG:0x%x\n", __func__, value);
\r
1287 handle_status=NAND_HANDLE_TIMEOUT;
\r
1289 else if(value & INT_DONE_STS)
\r
1291 handle_status=NAND_HANDLE_DONE;
\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
1298 //value = NFC_CMD_CLR;
\r
1299 //sprd_dolphin_reg_or(NFC_START_REG, value); /* clear all interrupt status */
\r
1301 nfc_clear_interrupt();
\r
1303 complete(&nfc_op_completion);
\r
1305 //DPRINT("%s leave\n", __func__);
\r
1307 return IRQ_HANDLED;
\r
1313 STATIC_FUNC int sprd_dolphin_nand_read_lp(struct mtd_info *mtd,uint8_t *mbuf, uint8_t *sbuf,uint32_t raw)
\r
1315 struct sprd_dolphin_nand_info *dolphin = mtd_to_dolphin(mtd);
\r
1316 struct nand_chip *chip = dolphin->nand;
\r
1318 uint32_t page_addr;
\r
1324 int size = 0 ,sct_size;
\r
1327 uint8_t ecc_bit=0 ;
\r
1328 page_addr = dolphin->page;
\r
1330 //DPRINT("%s enter\n", __func__);
\r
1333 column = mtd->writesize;
\r
1339 if(chip->options & NAND_BUSWIDTH_16)
\r
1343 //DPRINT("sprd_dolphin_nand_read_lp,page_addr = %x,column = %x\r\n",page_addr, column);
\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
1349 sprd_dolphin_nand_ins_add(NAND_MC_ADDR(column & 0xff), dolphin);
\r
1351 sprd_dolphin_nand_ins_add(NAND_MC_ADDR(page_addr & 0xff), dolphin);
\r
1353 sprd_dolphin_nand_ins_add(NAND_MC_ADDR(page_addr & 0xff), dolphin);
\r
1355 if (5 == dolphin->a_cycles)// five address cycles
\r
1358 sprd_dolphin_nand_ins_add(NAND_MC_ADDR(page_addr & 0xff), dolphin);
\r
1360 sprd_dolphin_nand_ins_add(NAND_MC_CMD(NAND_CMD_READSTART), dolphin);
\r
1362 sprd_dolphin_nand_ins_add(NFC_MC_WRB0_ID, dolphin); //wait rb
\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
1375 sprd_dolphin_nand_ins_add(NAND_MC_MRDT, dolphin);
\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
1382 cfg0 |= ECC_EN | DETECT_ALL_FF;
\r
1384 if(chip->options & NAND_BUSWIDTH_16)
\r
1386 cfg0 |= BUS_WIDTH;
\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
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
1402 cfg1 |= (dolphin->m_size - 1);
\r
1403 sprd_dolphin_reg_write(NFC_MAIN_ADDR_REG, dolphin->p_mbuf);
\r
1407 cfg1 |= (dolphin->s_size - 1);
\r
1408 sprd_dolphin_reg_write(NFC_MAIN_ADDR_REG, dolphin->p_oob);
\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
1417 #ifdef NAND_IRQ_EN
\r
1418 sprd_dolphin_nand_ins_exec_irq(dolphin);
\r
1419 sprd_dolphin_nand_wait_finish_irq(dolphin);
\r
1421 sprd_dolphin_nand_ins_exec(dolphin);
\r
1422 sprd_dolphin_nand_wait_finish(dolphin);
\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
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
1440 if(ecc_bit> chip->ecc.strength){
\r
1442 DPRINT("%s spare area ecc check error!\n",__func__);
\r
1448 mtd->ecc_stats.failed++;
\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
1463 if(ecc_bit > chip->ecc.strength){
\r
1465 DPRINT("%s main+spare area ecc check error!\n",__func__);
\r
1472 mtd->ecc_stats.failed++;
\r
1475 mbuf[size] = 0xff;
\r
1480 mtd->ecc_stats.corrected += err;
\r
1486 memcpy(mbuf, (const void *)dolphin->v_mbuf, dolphin->write_size);
\r
1489 memcpy(sbuf, (const void *)dolphin->v_oob, dolphin->oob_size);
\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
1499 struct sprd_dolphin_nand_info *dolphin = mtd_to_dolphin(mtd);
\r
1500 struct nand_chip *chip = dolphin->nand;
\r
1502 uint32_t page_addr;
\r
1506 page_addr = dolphin->page;
\r
1508 //DPRINT("%s, page addr is %lx\n", __func__, page_addr);
\r
1514 column = mtd->writesize;
\r
1516 if(chip->options & NAND_BUSWIDTH_16)
\r
1522 memcpy((void *)dolphin->v_mbuf, (const void *)mbuf, dolphin->write_size);
\r
1525 memcpy((void *)dolphin->v_oob, (const void *)sbuf, dolphin->oob_size);
\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
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
1535 sprd_dolphin_nand_ins_add(NAND_MC_ADDR(page_addr & 0xff), dolphin);
\r
1537 if (5 == dolphin->a_cycles)// five address cycles
\r
1540 sprd_dolphin_nand_ins_add(NAND_MC_ADDR(page_addr & 0xff), dolphin);
\r
1543 sprd_dolphin_nand_ins_add(NAND_MC_MWDT, dolphin);
\r
1546 sprd_dolphin_nand_ins_add(NAND_MC_SWDT, dolphin);
\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
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
1558 if(chip->options & NAND_BUSWIDTH_16)
\r
1560 cfg0 |= BUS_WIDTH;
\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
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
1577 cfg1 |= dolphin->m_size - 1;
\r
1578 sprd_dolphin_reg_write(NFC_MAIN_ADDR_REG, dolphin->p_mbuf);
\r
1582 cfg1 |= dolphin->s_size - 1;
\r
1583 sprd_dolphin_reg_write(NFC_MAIN_ADDR_REG, dolphin->p_oob);
\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
1591 #ifdef NAND_IRQ_EN
\r
1592 sprd_dolphin_nand_ins_exec_irq(dolphin);
\r
1593 sprd_dolphin_nand_wait_finish_irq(dolphin);
\r
1595 sprd_dolphin_nand_ins_exec(dolphin);
\r
1596 sprd_dolphin_nand_wait_finish(dolphin);
\r
1605 STATIC_FUNC int sprd_dolphin_nand_read_sp(struct mtd_info *mtd,uint8_t *mbuf, uint8_t *sbuf,uint32_t raw)
\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
1613 STATIC_FUNC void sprd_dolphin_erase(struct mtd_info *mtd, int page_addr)
\r
1615 struct sprd_dolphin_nand_info *dolphin = mtd_to_dolphin(mtd);
\r
1616 uint32_t cfg0 = 0;
\r
1618 //DPRINT("%s, page addr is %x\r\n", __func__ , page_addr);
\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
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
1628 sprd_dolphin_nand_ins_add(NAND_MC_ADDR(page_addr & 0xff), dolphin);
\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
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
1638 #ifdef NAND_IRQ_EN
\r
1639 sprd_dolphin_nand_ins_exec_irq(dolphin);
\r
1640 sprd_dolphin_nand_wait_finish_irq(dolphin);
\r
1642 sprd_dolphin_nand_ins_exec(dolphin);
\r
1643 sprd_dolphin_nand_wait_finish(dolphin);
\r
1646 //DPRINT("%s leave\n", __func__);
\r
1648 STATIC_FUNC uint8_t sprd_dolphin_read_byte(struct mtd_info *mtd)
\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
1654 ch = s_oob_data[dolphin->buf_head ++];
\r
1658 STATIC_FUNC uint16_t sprd_dolphin_read_word(struct mtd_info *mtd)
\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
1664 data = s_oob_data[dolphin->buf_head ++];
\r
1665 data |= ((uint16_t)s_oob_data[dolphin->buf_head ++]) << 8;
\r
1670 STATIC_FUNC int sprd_dolphin_waitfunc(struct mtd_info *mtd, struct nand_chip *chip)
\r
1675 STATIC_FUNC int sprd_dolphin_ecc_calculate(struct mtd_info *mtd, const uint8_t *data,
\r
1676 uint8_t *ecc_code)
\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
1687 static int sprd_dolphin_read_page(struct mtd_info *mtd, struct nand_chip *chip,
\r
1688 uint8_t *buf, int page)
\r
1690 struct sprd_dolphin_nand_info *dolphin = mtd_to_dolphin(mtd);
\r
1691 dolphin->page = page;
\r
1692 if(512 == mtd->writesize)
\r
1694 sprd_dolphin_nand_read_sp(mtd, buf, chip->oob_poi, 0);
\r
1698 sprd_dolphin_nand_read_lp(mtd, buf, chip->oob_poi, 0);
\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
1705 struct sprd_dolphin_nand_info *dolphin = mtd_to_dolphin(mtd);
\r
1706 dolphin->page = page;
\r
1707 if(512 == mtd->writesize)
\r
1709 sprd_dolphin_nand_read_sp(mtd, buf, chip->oob_poi, 1);
\r
1713 sprd_dolphin_nand_read_lp(mtd, buf, chip->oob_poi, 1);
\r
1717 STATIC_FUNC int sprd_dolphin_read_oob(struct mtd_info *mtd, struct nand_chip *chip,
\r
1718 int page, int sndcmd)
\r
1720 struct sprd_dolphin_nand_info *dolphin = mtd_to_dolphin(mtd);
\r
1721 dolphin->page = page;
\r
1722 if(512 == mtd->writesize)
\r
1724 sprd_dolphin_nand_read_sp(mtd, 0, chip->oob_poi, 1);
\r
1728 sprd_dolphin_nand_read_lp(mtd, 0, chip->oob_poi, 1);
\r
1732 STATIC_FUNC void sprd_dolphin_write_page(struct mtd_info *mtd, struct nand_chip *chip,
\r
1733 const uint8_t *buf)
\r
1735 if(512 == mtd->writesize)
\r
1737 sprd_dolphin_nand_write_sp(mtd, buf, chip->oob_poi, 0);
\r
1741 sprd_dolphin_nand_write_lp(mtd, buf, chip->oob_poi, 0);
\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
1748 if(512 == mtd->writesize)
\r
1750 sprd_dolphin_nand_write_sp(mtd, buf, chip->oob_poi, 1);
\r
1754 sprd_dolphin_nand_write_lp(mtd, buf, chip->oob_poi, 1);
\r
1757 STATIC_FUNC int sprd_dolphin_write_oob(struct mtd_info *mtd, struct nand_chip *chip,
\r
1760 struct sprd_dolphin_nand_info *dolphin = mtd_to_dolphin(mtd);
\r
1761 dolphin->page = page;
\r
1762 if(512 == mtd->writesize)
\r
1764 sprd_dolphin_nand_write_sp(mtd, 0, chip->oob_poi, 1);
\r
1768 sprd_dolphin_nand_write_lp(mtd, 0, chip->oob_poi, 1);
\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
1780 * Check, if the block is bad.
\r
1782 STATIC_FUNC int sprd_dolphin_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)
\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
1790 page = (int)((long)ofs >> chip->page_shift) & chip->pagemask;
\r
1793 chipnr = (int)((long)ofs >> chip->chip_shift);
\r
1794 /* Select the NAND device */
\r
1795 chip->select_chip(mtd, chipnr);
\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
1803 sprd_dolphin_nand_read_lp(mtd, 0, s_oob_data, 1);
\r
1805 dolphin->buf_head = 0;
\r
1806 dolphin->_buf_tail = mtd->oobsize;
\r
1807 buf = (uint16_t *)(s_oob_data + chip->badblockpos);
\r
1809 if (chip->options & NAND_BUSWIDTH_16) {
\r
1811 if ((bad & 0xFF) != 0xff) {
\r
1815 bad = *(buf) & 0xff;
\r
1823 STATIC_FUNC void sprd_dolphin_nand_cmdfunc(struct mtd_info *mtd, unsigned int command,
\r
1824 int column, int page_addr)
\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
1833 * program and erase have their own busy handlers
\r
1834 * status, sequential in, and deplete1 need no delay
\r
1836 switch (command) {
\r
1837 case NAND_CMD_STATUS:
\r
1838 sprd_dolphin_nand_read_status(dolphin);
\r
1840 case NAND_CMD_READID:
\r
1841 sprd_dolphin_nand_read_id(dolphin, (uint32_t *)s_oob_data);
\r
1843 case NAND_CMD_RESET:
\r
1844 sprd_dolphin_nand_reset(dolphin);
\r
1846 case NAND_CMD_ERASE1:
\r
1847 sprd_dolphin_erase(mtd, page_addr);
\r
1849 case NAND_CMD_READ0:
\r
1850 case NAND_CMD_SEQIN:
\r
1851 dolphin->column = column;
\r
1852 dolphin->page = page_addr;
\r
1857 STATIC_FUNC void sprd_dolphin_nand_hwecc_ctl(struct mtd_info *mtd, int mode)
\r
1859 return; //do nothing
\r
1863 STATIC_FUNC void sprd_dolphin_nand_hw_init(struct sprd_dolphin_nand_info *dolphin)
\r
1868 sprd_dolphin_reg_or(REG_AP_AHB_AHB_EB, BIT_NAND_ENABLE);
\r
1870 sprd_dolphin_reg_or(REG_AP_AHB_AHB_RST,BIT_NAND_RESET);
\r
1872 sprd_dolphin_reg_and(REG_AP_AHB_AHB_RST, ~(BIT_NAND_RESET));
\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
1878 //close write protect
\r
1879 sprd_dolphin_nand_wp_en(dolphin, 0);
\r
1883 int board_nand_init(struct nand_chip *chip)
\r
1885 DPRINT("board_nand_init\r\n");
\r
1887 sprd_dolphin_nand_hw_init(&g_dolphin);
\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
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
1910 #ifdef DOLPHIN_KERNEL
\r
1911 chip->ecc.strength = CONFIG_SYS_NAND_ECC_MODE;
\r
1914 #ifdef DOLPHIN_UBOOT
\r
1915 chip->eccbitmode = CONFIG_SYS_NAND_ECC_MODE;
\r
1918 //dolphin_set_timing_config(&g_dolphin, SPRD_NAND_CLOCK); /* 153 is current clock 153MHz */
\r
1920 chip->ecc.size = CONFIG_SYS_NAND_ECCSIZE;
\r
1922 chip->chip_delay = 20;
\r
1923 chip->priv = &g_dolphin;
\r
1925 //DPRINT("v2 board eccbitmode %d\n", chip->eccbitmode);
\r
1927 chip->options = NAND_BUSWIDTH_16;
\r
1932 #ifdef DOLPHIN_UBOOT
\r
1933 #ifndef CONFIG_NAND_SPL
\r
1934 void McuReadNandType(unsigned char *array)
\r
1940 static unsigned long nfc_read_status(void)
\r
1942 unsigned long status = 0;
\r
1944 sprd_dolphin_nand_read_status(&g_dolphin);
\r
1945 status = s_oob_data[0];
\r
1950 #ifndef CONFIG_NAND_SPL
\r
1951 static int sprd_scan_one_block(int blk, int erasesize, int writesize)
\r
1954 int status = 1, ii;
\r
1956 int oobsize = mtdoobsize;
\r
1957 int column, page_addr;
\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
1967 } //for (ii = 0; ii < 2; ii ++)
\r
1969 if ((s_oob_data[0] == 0xff) && (s_oob_data[1] == 0xff))
\r
1970 status = 0; //good block
\r
1972 status = 1; //bad block
\r
1977 static unsigned long nand_ctl_erase_block(int blk, int erasesize, int writesize)
\r
1982 page_addr = blk * (erasesize / writesize);
\r
1983 sprd_dolphin_erase(&g_dolphin, page_addr);
\r
1984 status = nfc_read_status();
\r
1991 #ifndef CONFIG_NAND_SPL
\r
1992 void nand_scan_patition(int blocks, int erasesize, int writesize)
\r
1999 for (blk = 0; blk < blocks; blk ++) {
\r
2000 ret = sprd_scan_one_block(blk, erasesize, writesize);
\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
2006 ret = nand_ctl_erase_block(blk, erasesize, writesize);
\r
2007 DPRINT("erasing block : %d %d % \r", blk, (blk * 100 ) / blocks);
\r
2011 int nand_scan_block(int block, int erasesize, int writesize){
\r
2013 ret = nand_ctl_erase_block(block, erasesize, writesize);
\r
2019 #endif //DOLPHIN_UBOOT end
\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
2028 static struct mtd_info *sprd_mtd = NULL;
\r
2029 #ifdef CONFIG_MTD_CMDLINE_PARTS
\r
2030 const char *part_probes[] = { "cmdlinepart", NULL };
\r
2033 STATIC_FUNC int sprd_nand_dma_init(struct sprd_dolphin_nand_info *dolphin)
\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
2042 dolphin->v_mbuf = (u32)virt_ptr;
\r
2043 dolphin->p_mbuf = (u32)phys_addr;
\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
2051 dolphin->v_oob = (u32)virt_ptr;
\r
2052 dolphin->p_oob = (u32)phys_addr;
\r
2055 STATIC_FUNC void sprd_nand_dma_deinit(struct sprd_dolphin_nand_info *dolphin)
\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
2060 STATIC_FUNC int sprd_nand_probe(struct platform_device *pdev)
\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
2069 #ifdef NAND_IRQ_EN
\r
2071 init_completion(&nfc_op_completion);
\r
2072 err = request_irq(IRQ_NFC_INT, nfc_irq_handler, 0, DRIVER_NAME, NULL);
\r
2074 DPRINT(KERN_ERR "request_irq error\n");
\r
2077 DPRINT(KERN_ALERT "request_irq ok\n");
\r
2081 regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
\r
2083 dev_err(&pdev->dev,"resources unusable\n");
\r
2087 memset(&g_dolphin, 0 , sizeof(g_dolphin));
\r
2089 platform_set_drvdata(pdev, &g_dolphin);
\r
2090 g_dolphin.pdev = pdev;
\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
2097 sprd_mtd->priv = this;
\r
2099 this->options |= NAND_BUSWIDTH_16;
\r
2100 //this->options |= NAND_NO_READRDY;
\r
2102 board_nand_init(this);
\r
2105 if (sprd_dolphin_nand_reset(&g_dolphin) != 0)
\r
2108 DPRINT(KERN_ERR "nand reset failed!!!!!!!!!!!!!\n");
\r
2113 if (sprd_dolphin_nand_read_id(&g_dolphin, (uint32_t *)s_oob_data) != 0)
\r
2116 DPRINT(KERN_ERR "nand read id failed, no nand device!!!!!!!!!!!!!\n");
\r
2118 DPRINT(KERN_ALERT "nand read id ok, nand exists!!!!!!!!!!!!!\n");
\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
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
2132 //this->IO_ADDR_R = g_dolphin.v_mbuf;
\r
2133 //this->IO_ADDR_W = g_dolphin.v_mbuf;
\r
2135 /* second phase scan */
\r
2136 if (nand_scan_tail(sprd_mtd)) {
\r
2141 sprd_mtd->name = "sprd-nand";
\r
2142 num_partitions = parse_mtd_partitions(sprd_mtd, part_probes, &partitions, 0);
\r
2144 if ((!partitions) || (num_partitions == 0)) {
\r
2145 DPRINT(KERN_ALERT "No parititions defined, or unsupported device.\n");
\r
2149 #ifdef CONFIG_MTD_CMDLINE_PARTS
\r
2150 mtd_device_register(sprd_mtd, partitions, num_partitions);
\r
2155 nand_release(sprd_mtd);
\r
2156 sprd_nand_dma_deinit(&g_dolphin);
\r
2158 sprd_dolphin_reg_and(DOLPHIN_AHB_BASE,~(BIT(6)));
\r
2163 STATIC_FUNC int sprd_nand_remove(struct platform_device *pdev)
\r
2165 platform_set_drvdata(pdev, NULL);
\r
2166 nand_release(sprd_mtd);
\r
2167 sprd_nand_dma_deinit(&g_dolphin);
\r
2173 STATIC_FUNC int sprd_nand_suspend(struct platform_device *dev, pm_message_t pm)
\r
2179 STATIC_FUNC int sprd_nand_resume(struct platform_device *dev)
\r
2181 sprd_dolphin_nand_hw_init(&g_dolphin);
\r
2185 #define sprd_nand_suspend NULL
\r
2186 #define sprd_nand_resume NULL
\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
2195 .name = "sprd-nand",
\r
2196 .owner = THIS_MODULE,
\r
2200 STATIC_FUNC int __init sprd_nand_init(void)
\r
2202 return platform_driver_register(&sprd_nand_driver);
\r
2205 STATIC_FUNC void __exit sprd_nand_exit(void)
\r
2207 platform_driver_unregister(&sprd_nand_driver);
\r
2210 module_init(sprd_nand_init);
\r
2211 module_exit(sprd_nand_exit);
\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