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
19 #include <asm/errno.h>
\r
22 #include <asm/arch/sci_types.h>
\r
23 #include <asm/arch/pinmap.h>
\r
24 #include <asm/arch/bits.h>
\r
27 #include <linux/mtd/nand.h>
\r
29 #include <asm/arch-sc9630/sprd_nfc_reg_v2.h>
\r
30 //#include <asm/arch/sc8810_reg_base.h>
\r
31 #include <asm/arch/regs_ana.h>
\r
32 #include <asm/arch/analog_reg_v3.h>
\r
33 //#include <asm/arch/sc8810_reg_ahb.h>
\r
34 //#include <asm/arch/sc8810_reg_global.h>
\r
35 #include <asm/arch/gpio_drvapi.h>
\r
36 #include <asm/arch/regs_global.h>
\r
37 //#include <asm/arch/regs_cpc.h>
\r
38 //#include <asm/arch/pin_reg_v3.h>
\r
40 #define mdelay(ms) do{ int volatile i = 0; for(i; i < 0xFFFF; i++); } while(0)
\r
43 #ifdef CONFIG_NAND_SPL
\r
44 #define printf(arg...) do{}while(0)
\r
47 #define printf(arg...) do{}while(0)
\r
50 #define DPRINT(arg...) do{}while(0)
\r
52 /* 2 bit correct, sc8810 support 1, 2, 4, 8, 12,14, 24 */
\r
53 #define CONFIG_SYS_NAND_ECC_MODE 2
\r
54 //#define CONFIG_SYS_NAND_ECC_MODE 4
\r
55 /* Number of ECC bytes per OOB - S3C6400 calculates 4 bytes ECC in 1-bit mode */
\r
56 #define CONFIG_SYS_NAND_ECCBYTES 4
\r
57 //#define CONFIG_SYS_NAND_ECCBYTES 7
\r
58 /* Size of the block protected by one OOB (Spare Area in Samsung terminology) */
\r
59 #define CONFIG_SYS_NAND_ECCSIZE 512
\r
60 #define CONFIG_SYS_NAND_5_ADDR_CYCLE 5
\r
62 #define NFC_MC_ICMD_ID (0xCD)
\r
63 #define NFC_MC_ADDR_ID (0x0A)
\r
64 #define NFC_MC_WRB0_ID (0xB0)
\r
65 #define NFC_MC_WRB1_ID (0xB1)
\r
66 #define NFC_MC_MRDT_ID (0xD0)
\r
67 #define NFC_MC_MWDT_ID (0xD1)
\r
68 #define NFC_MC_SRDT_ID (0xD2)
\r
69 #define NFC_MC_SWDT_ID (0xD3)
\r
70 #define NFC_MC_IDST_ID (0xDD)
\r
71 #define NFC_MC_CSEN_ID (0xCE)
\r
72 #define NFC_MC_NOP_ID (0xF0)
\r
73 #define NFC_MC_DONE_ID (0xFF)
\r
74 #define NFC_MAX_CHIP 1
\r
75 #define NFC_TIMEOUT_VAL 0x1000000
\r
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 "sc9630_nand.h"
\r
113 #include <mach/pinmap.h>
\r
115 #define DPRINT(arg...) do{}while(0)
\r
116 #endif //DOLPHIN_KERNEL
\r
119 struct sprd_dolphin_nand_param {
\r
123 uint8_t sct_pg; //sector per page
\r
124 uint8_t oob_size; /* oob size per sector*/
\r
125 uint8_t ecc_pos; /* oob size per sector*/
\r
126 uint8_t info_pos; /* oob size per sector*/
\r
127 uint8_t info_size; /* oob size per sector*/
\r
128 uint8_t eccbit; /* ecc level per eccsize */
\r
129 uint16_t eccsize; /*bytes per sector for ecc calcuate once time */
\r
130 uint8_t ace_ns; /* ALE, CLE end of delay timing, unit: ns */
\r
131 uint8_t rwl_ns; /* WE, RE, IO, pulse timing, unit: ns */
\r
132 uint8_t rwh_ns; /* WE, RE, IO, high hold timing, unit: ns */
\r
135 struct sprd_dolphin_nand_info {
\r
136 struct mtd_info *mtd;
\r
137 struct nand_chip *nand;
\r
139 #ifdef DOLPHIN_UBOOT
\r
140 struct device *pdev;
\r
143 #ifdef DOLPHIN_KERNEL
\r
144 struct platform_device *pdev;
\r
147 struct sprd_dolphin_nand_param *param;
\r
148 uint32_t chip; //chip index
\r
149 uint32_t v_mbuf; //virtual main buffer address
\r
150 uint32_t p_mbuf; //phy main buffer address
\r
151 uint32_t v_oob; // virtual oob buffer address
\r
152 uint32_t p_oob; //phy oob buffer address
\r
153 uint32_t page; //page address
\r
154 uint16_t column; //column address
\r
156 uint16_t m_size; //main part size per sector
\r
157 uint16_t s_size; //oob size per sector
\r
158 uint8_t a_cycles;//address cycles, 3, 4, 5
\r
159 uint8_t sct_pg; //sector per page
\r
162 uint8_t ecc_mode;//0-1bit, 1-2bit, 2-4bit, 3-8bit,4-12bit,5-16bit,6-24bit
\r
163 uint8_t ecc_pos; // ecc postion
\r
164 uint8_t wp_en; //write protect enable
\r
165 uint16_t write_size;
\r
166 uint16_t page_per_bl;//page per block
\r
168 uint16_t _buf_tail;
\r
169 uint8_t ins_num;//instruction number
\r
170 uint32_t ins[NAND_MC_BUFFER_SIZE >> 1];
\r
174 #define mtd_to_dolphin(m) (&g_dolphin)
\r
176 //gloable variable
\r
177 static struct nand_ecclayout sprd_dolphin_nand_oob_default = {
\r
184 struct sprd_dolphin_nand_info g_dolphin = {0};
\r
185 //save the data read by read_byte and read_word api interface functon
\r
186 static __attribute__((aligned(4))) uint8_t s_oob_data[NAND_MAX_OOBSIZE];
\r
187 //static __attribute__((aligned(4))) uint8_t s_oob_data[8];
\r
188 //static __attribute__((aligned(4))) uint8_t s_id_status[8];
\r
190 static void sprd_dolphin_nand_read_id(struct sprd_dolphin_nand_info *dolphin, uint32_t *buf);
\r
191 static void sprd_dolphin_nand_reset(struct sprd_dolphin_nand_info *dolphin);
\r
192 static int sprd_dolphin_nand_wait_finish(struct sprd_dolphin_nand_info *dolphin);
\r
194 static uint32_t sprd_dolphin_reg_read(uint32_t addr)
\r
196 return readl(addr);
\r
198 static void sprd_dolphin_reg_write(uint32_t addr, uint32_t val)
\r
202 static void sprd_dolphin_reg_or(uint32_t addr, uint32_t val)
\r
204 sprd_dolphin_reg_write(addr, sprd_dolphin_reg_read(addr) | val);
\r
206 static void sprd_dolphin_reg_and(uint32_t addr, uint32_t mask)
\r
208 sprd_dolphin_reg_write(addr, sprd_dolphin_reg_read(addr) & mask);
\r
210 static void sprd_dolphin_nand_int_clr(uint32_t bit_clear)
\r
212 sprd_dolphin_reg_write(NFC_INT_REG, bit_clear);
\r
214 unsigned int ecc_mode_convert(uint32_t mode)
\r
253 /*spare info must be align to ecc pos, info_pos + info_size = ecc_pos,
\r
254 *the hardware must be config info_size and info_pos when ecc enable,and the ecc_info size can't be zero,
\r
255 *to simplify the nand_param_tb, the info is align with ecc and ecc at the last postion in one sector
\r
257 static struct sprd_dolphin_nand_param sprd_dolphin_nand_param_tb[] = {
\r
258 {{0xec, 0xbc, 0x00,0x55, 0x54}, 1, 5, 4, 16, 12, 11, 1, 2, 512, 5, 21, 10},
\r
259 {{0xec, 0xbc, 0x00,0x6A, 0x56}, 1, 5, 8, 16, 12, 11, 1, 2, 512, 10, 25, 15},
\r
260 //{{0xec, 0xbc, 0x00,0x6A, 0x56}, 1, 5, 8, 16, 12, 11, 1, 2, 512, 5, 21, 10},
\r
261 //{{0xec, 0xbc, 0x00,0x6A, 0x56}, 1, 5, 8, 8, 4, 3, 1, 2, 512, 5, 21, 10},
\r
262 {{0xad, 0xbc, 0x90,0x55, 0x54}, 1, 5, 4, 16, 12, 11, 1, 2, 512, 10, 25, 15},
\r
263 {{0x2c, 0xbc, 0x90,0x66, 0x54}, 1, 5, 8, 16, 12, 11, 1, 2, 512, 10, 25, 15},
\r
268 #ifdef CONFIG_NAND_SPL
\r
269 struct sprd_dolphin_boot_header_info {
\r
270 uint32_t check_sum;
\r
271 uint32_t sct_size; //
\r
272 uint32_t acycle; // 3, 4, 5
\r
273 uint32_t bus_width; //0 ,1
\r
274 uint32_t spare_size; //spare part sise for one sector
\r
275 uint32_t ecc_mode; //0--1bit, 1--2bit,2--4bit,3--8bit,4--12bit, 5--16bit, 6--24bit
\r
276 uint32_t ecc_pos; // ecc postion at spare part
\r
277 uint32_t sct_per_page; //sector per page
\r
279 uint32_t info_size;
\r
280 uint32_t magic_num; //0xaa55a5a5
\r
281 uint32_t ecc_value[27];
\r
283 void boad_nand_param_init(struct sprd_dolphin_nand_info *dolphin, struct nand_chip *chip, uint8 *id)
\r
286 uint32_t writesize;
\r
288 uint32_t erasesize;
\r
291 /* The 4th id byte is the important one */
\r
293 writesize = 1024 << (extid & 0x3);
\r
296 oobsize = (8 << (extid & 0x01)) * (writesize >> 9);
\r
298 /* Calc blocksize. Blocksize is multiples of 64KiB */
\r
299 erasesize = (64 * 1024) << (extid & 0x03);
\r
301 /* Get buswidth information */
\r
302 busw = (extid & 0x01) ? NAND_BUSWIDTH_16 : 0;
\r
303 dolphin->write_size = writesize;
\r
304 dolphin->m_size =CONFIG_SYS_NAND_ECCSIZE;
\r
305 dolphin->sct_pg = writesize / CONFIG_SYS_NAND_ECCSIZE;
\r
306 dolphin->s_size = oobsize / dolphin->sct_pg;
\r
307 dolphin->ecc_mode = ecc_mode_convert(CONFIG_SYS_NAND_ECC_MODE);
\r
308 dolphin->ecc_pos = dolphin->s_size - ((14 * CONFIG_SYS_NAND_ECC_MODE + 7) / 8);
\r
309 dolphin->info_pos = dolphin->ecc_pos - 1;
\r
310 dolphin->info_size = 1;
\r
311 dolphin->page_per_bl = erasesize / dolphin->write_size;
\r
312 dolphin->a_cycles = CONFIG_SYS_NAND_5_ADDR_CYCLE;
\r
313 if(NAND_BUSWIDTH_16 == busw)
\r
315 chip->options |= NAND_BUSWIDTH_16;
\r
319 chip->options &= ~NAND_BUSWIDTH_16;
\r
324 * because the dolphin firmware use the nand identify process
\r
325 * and the data at the header of nand_spl is the nand param used at nand read and write,
\r
326 * so in nand_spl, don't need read the id or use the onfi spec to calculate the nand param,
\r
327 * just use the param at the nand_spl header instead of
\r
329 void nand_hardware_config(struct mtd_info *mtd,struct nand_chip *chip)
\r
331 struct sprd_dolphin_nand_info *dolphin = mtd_to_dolphin(mtd);
\r
332 struct sprd_dolphin_boot_header_info *header;
\r
335 struct sprd_dolphin_nand_param * param;
\r
337 sprd_dolphin_nand_reset(dolphin);
\r
338 sprd_dolphin_nand_read_id(dolphin, (uint32_t *)s_oob_data);
\r
339 boad_nand_param_init(dolphin, dolphin->nand, s_oob_data);
\r
341 array = ARRAY_SIZE(sprd_dolphin_nand_param_tb);
\r
343 for (index = 0; index < array; index ++) {
\r
344 param = sprd_dolphin_nand_param_tb + index;
\r
345 if ((param->id[0] == id[0])
\r
346 && (param->id[1] == id[1])
\r
347 && (param->id[2] == id[2])
\r
348 && (param->id[3] == id[3])
\r
349 && (param->id[4] == id[4]))
\r
352 if (index < array) {
\r
353 dolphin->ecc_mode = ecc_mode_convert(param->eccbit);
\r
354 dolphin->m_size = param->eccsize;
\r
355 dolphin->s_size = param->oob_size;
\r
356 dolphin->a_cycles = param->a_cycles;
\r
357 dolphin->sct_pg = param->sct_pg;
\r
358 dolphin->info_pos = param->info_pos;
\r
359 dolphin->info_size = param->info_size;
\r
360 dolphin->write_size = dolphin->m_size * dolphin->sct_pg;
\r
361 dolphin->ecc_pos = param->ecc_pos;
\r
362 if(param->bus_width)
\r
364 chip->options |= NAND_BUSWIDTH_16;
\r
368 chip->options &= ~NAND_BUSWIDTH_16;
\r
370 mtd->writesize = dolphin->write_size;
\r
371 mtd->oobsize = dolphin->s_size * dolphin->sct_pg;
\r
372 dolphin->nand=chip;
\r
374 mtd->writesize = dolphin->write_size;
\r
375 mtd->oobsize = dolphin->s_size * dolphin->sct_pg;
\r
376 mtd->erasesize = dolphin->page_per_bl * dolphin->write_size;
\r
380 static void sprd_dolphin_nand_ecc_layout_gen(struct sprd_dolphin_nand_info *dolphin, struct sprd_dolphin_nand_param *param, struct nand_ecclayout *layout)
\r
385 uint32_t used_len ; //one sector ecc data size(byte)
\r
386 uint32_t eccbytes = 0; //one page ecc data size(byte)
\r
387 uint32_t oobfree_len = 0;
\r
388 used_len = (14 * param->eccbit + 7) / 8 + param->info_size;
\r
389 if(param->sct_pg > ARRAY_SIZE(layout->oobfree))
\r
393 for(sct = 0; sct < param->sct_pg; sct++)
\r
395 //offset = (oob_size * sct) + ecc_pos;
\r
396 //for(i = 0; i < ecc_len; i++)
\r
397 offset = (param->oob_size * sct) + param->info_pos;
\r
398 for(i = 0; i < used_len; i++)
\r
400 layout->eccpos[eccbytes++] = offset + i;
\r
402 layout->oobfree[sct].offset = param->oob_size * sct + param->info_pos;
\r
403 layout->oobfree[sct].length = param->info_size ;
\r
404 oobfree_len += param->info_size;
\r
407 layout->oobavail = oobfree_len;
\r
408 layout->eccbytes = used_len * param->sct_pg;
\r
411 void nand_hardware_config(struct mtd_info *mtd, struct nand_chip *chip, u8 id[5])
\r
415 struct sprd_dolphin_nand_param * param;
\r
416 struct sprd_dolphin_nand_info *dolphin = mtd_to_dolphin(mtd);
\r
418 array = ARRAY_SIZE(sprd_dolphin_nand_param_tb);
\r
419 for (index = 0; index < array; index ++) {
\r
420 param = sprd_dolphin_nand_param_tb + index;
\r
421 if ((param->id[0] == id[0])
\r
422 && (param->id[1] == id[1])
\r
423 && (param->id[2] == id[2])
\r
424 && (param->id[3] == id[3])
\r
425 && (param->id[4] == id[4]))
\r
428 if (index < array) {
\r
429 //save the param config
\r
430 dolphin->ecc_mode = ecc_mode_convert(param->eccbit);
\r
431 dolphin->m_size = param->eccsize;
\r
432 dolphin->s_size = param->oob_size;
\r
433 dolphin->a_cycles = param->a_cycles;
\r
434 dolphin->sct_pg = param->sct_pg;
\r
435 dolphin->info_pos = param->info_pos;
\r
436 dolphin->info_size = param->info_size;
\r
437 dolphin->write_size = dolphin->m_size * dolphin->sct_pg;
\r
438 dolphin->ecc_pos = param->ecc_pos;
\r
439 chip->eccbitmode = param->eccbit;
\r
440 chip->ecc.bytes = (param->eccbit*14+7)/8;
\r
441 //dolphin->bus_width = param->bus_width;
\r
442 if(param->bus_width)
\r
444 chip->options |= NAND_BUSWIDTH_16;
\r
448 chip->options &= ~NAND_BUSWIDTH_16;
\r
450 dolphin->param = param;
\r
451 //update the mtd and nand default param after nand scan
\r
452 mtd->writesize = dolphin->write_size;
\r
453 mtd->oobsize = dolphin->s_size * dolphin->sct_pg;
\r
454 dolphin->oob_size = mtd->oobsize;
\r
455 /* Calculate the address shift from the page size */
\r
456 chip->page_shift = ffs(mtd->writesize) - 1;
\r
457 /* Convert chipsize to number of pages per chip -1. */
\r
458 chip->pagemask = (chip->chipsize >> chip->page_shift) - 1;
\r
459 sprd_dolphin_nand_ecc_layout_gen(dolphin, param, &sprd_dolphin_nand_oob_default);
\r
460 chip->ecc.layout = &sprd_dolphin_nand_oob_default;
\r
461 dolphin->mtd = mtd;
\r
465 struct sprd_dolphin_nand_param param1;
\r
467 //save the param config
\r
468 steps = mtd->writesize / CONFIG_SYS_NAND_ECCSIZE;
\r
469 dolphin->ecc_mode = ecc_mode_convert(CONFIG_SYS_NAND_ECC_MODE);
\r
470 dolphin->m_size = CONFIG_SYS_NAND_ECCSIZE;
\r
471 dolphin->s_size = mtd->oobsize / steps;
\r
472 dolphin->a_cycles = mtd->writesize / CONFIG_SYS_NAND_ECCSIZE;
\r
473 dolphin->sct_pg = steps;
\r
474 dolphin->info_pos = dolphin->s_size - CONFIG_SYS_NAND_ECCBYTES - 1;
\r
475 dolphin->info_size = 1;
\r
476 dolphin->write_size = mtd->writesize;
\r
477 dolphin->oob_size = mtd->oobsize;
\r
478 dolphin->ecc_pos = dolphin->s_size - CONFIG_SYS_NAND_ECCBYTES;
\r
479 param1.sct_pg = dolphin->sct_pg;
\r
480 param1.info_pos = dolphin->info_pos;
\r
481 param1.info_size = dolphin->info_size;
\r
482 param1.oob_size = dolphin->s_size;
\r
483 param1.eccbit = CONFIG_SYS_NAND_ECC_MODE;
\r
484 param1.eccsize = dolphin->s_size;
\r
486 chip->eccbitmode = CONFIG_SYS_NAND_ECC_MODE;
\r
487 chip->ecc.bytes = (CONFIG_SYS_NAND_ECC_MODE * 14 + 7) / 8;
\r
488 //printf("hardware default eccbitmode %d\n", chip->eccbitmode);
\r
490 if(chip->chipsize > (128 << 20)) {
\r
491 dolphin->a_cycles = 5;
\r
494 dolphin->a_cycles = 4;
\r
497 sprd_dolphin_nand_ecc_layout_gen(dolphin, ¶m1, &sprd_dolphin_nand_oob_default);
\r
498 chip->ecc.layout = &sprd_dolphin_nand_oob_default;
\r
499 dolphin->mtd = mtd;
\r
501 dolphin->mtd = mtd;
\r
503 #endif //end CONFIG_NAND_SPL
\r
507 #ifdef DOLPHIN_UBOOT
\r
508 #ifndef CONFIG_NAND_SPL
\r
514 uint8_t dir; //if dir is 0, read dadta from NFC buffer, if 1, write data to NFC buffer
\r
517 } sprd_dolphin_nand_data_param;
\r
519 static unsigned int sprd_dolphin_data_trans(sprd_dolphin_nand_data_param *param)
\r
524 cfg0 = NFC_ONLY_MST_MODE | MAIN_SPAR_APT | NFC_WPN;
\r
529 if(param->m_sct != 0)
\r
531 cfg0 |= (param->m_sct - 1) << SECTOR_NUM_OFFSET;
\r
533 cfg1 |= (param->m_size - 1);
\r
534 sprd_dolphin_reg_write(NFC_MAIN_ADDR_REG, (uint32_t)param->m_buf);
\r
536 if(param->s_sct != 0)
\r
539 cfg1 |= (param->s_size - 1) << SPAR_SIZE_OFFSET;
\r
540 cfg2 |= (param->s_sct - 1) << SPAR_SECTOR_NUM_OFFSET;
\r
541 sprd_dolphin_reg_write(NFC_SPAR_ADDR_REG, (uint32_t)param->s_buf);
\r
543 sprd_dolphin_reg_write(NFC_CFG0_REG, cfg0);
\r
544 sprd_dolphin_reg_write(NFC_CFG1_REG, cfg1);
\r
545 sprd_dolphin_reg_write(NFC_CFG2_REG, cfg2);
\r
546 sprd_dolphin_nand_int_clr(INT_STSMCH_CLR | INT_WP_CLR | INT_TO_CLR | INT_DONE_CLR);//clear all interrupt
\r
547 sprd_dolphin_reg_write(NFC_START_REG, NFC_START);
\r
548 sprd_dolphin_nand_wait_finish(&g_dolphin);
\r
551 void sprd_ecc_ctrl(struct sprd_ecc_param *param, uint32_t dir)
\r
556 cfg0 = NFC_ONLY_ECC_MODE | MAIN_SPAR_APT;
\r
561 cfg1 |=(param->sinfo_size - 1) << SPAR_INFO_SIZE_OFFSET;
\r
562 cfg1 |=(param->sp_size - 1) << SPAR_SIZE_OFFSET;
\r
563 cfg1 |= (param->m_size - 1);
\r
565 cfg2 |= (param->sinfo_pos)<< SPAR_INFO_POS_OFFSET;
\r
566 cfg2 |= ecc_mode_convert(param->mode) << ECC_MODE_OFFSET;
\r
567 cfg2 |= param->ecc_pos;
\r
568 sprd_dolphin_reg_write(NFC_CFG0_REG, cfg0);
\r
569 sprd_dolphin_reg_write(NFC_CFG1_REG, cfg1);
\r
570 sprd_dolphin_reg_write(NFC_CFG2_REG, cfg2);
\r
571 sprd_dolphin_nand_int_clr(INT_STSMCH_CLR | INT_WP_CLR | INT_TO_CLR | INT_DONE_CLR);//clear all interrupt
\r
572 sprd_dolphin_reg_write(NFC_START_REG, NFC_START);
\r
573 sprd_dolphin_nand_wait_finish(&g_dolphin);
\r
576 unsigned int sprd_ecc_encode(struct sprd_ecc_param *param)
\r
578 struct sprd_dolphin_nand_info *dolphin;
\r
579 sprd_dolphin_nand_data_param d_param;
\r
581 dolphin = &g_dolphin;
\r
582 memset(&d_param, 0, sizeof(d_param));
\r
584 d_param.m_buf = param->p_mbuf;
\r
585 d_param.s_buf = param->p_sbuf;
\r
586 d_param.m_sct = param->ecc_num;
\r
587 d_param.s_sct = param->ecc_num;
\r
589 d_param.m_size = param->m_size;
\r
590 d_param.s_size = param->sp_size;
\r
592 Dcache_CleanRegion((unsigned int)d_param.m_buf, d_param.m_sct*d_param.m_size);
\r
593 Dcache_CleanRegion((unsigned int)d_param.s_buf, d_param.s_sct*d_param.s_size);
\r
595 sprd_dolphin_data_trans(&d_param);
\r
596 sprd_ecc_ctrl(param, 1);
\r
600 Dcache_InvalRegion((unsigned int)d_param.m_buf , d_param.m_sct*d_param.m_size);
\r
601 Dcache_InvalRegion((unsigned int)d_param.s_buf , d_param.s_sct*d_param.s_size);
\r
603 sprd_dolphin_data_trans(&d_param); //read the ecc value from nfc buffer
\r
606 #endif //CONFIG_NAND_SPL end
\r
607 #endif //DOLPHIN_UBOOT END
\r
611 //add one macro instruction to nand controller
\r
612 /*static */void sprd_dolphin_nand_ins_init(struct sprd_dolphin_nand_info *dolphin)
\r
614 dolphin->ins_num = 0;
\r
616 /*static */void sprd_dolphin_nand_ins_add(uint16_t ins, struct sprd_dolphin_nand_info *dolphin)
\r
618 uint16_t *buf = (uint16_t *)dolphin->ins;
\r
619 if(dolphin->ins_num >= NAND_MC_BUFFER_SIZE)
\r
623 *(buf + dolphin->ins_num) = ins;
\r
624 dolphin->ins_num++;
\r
627 static void sprd_dolphin_nand_ins_exec(struct sprd_dolphin_nand_info *dolphin)
\r
632 for(i = 0; i < ((dolphin->ins_num + 1) >> 1); i++)
\r
634 sprd_dolphin_reg_write(NFC_INST0_REG + (i << 2), dolphin->ins[i]);
\r
636 cfg0 = sprd_dolphin_reg_read(NFC_CFG0_REG);
\r
653 sprd_dolphin_nand_int_clr(INT_STSMCH_CLR | INT_WP_CLR | INT_TO_CLR | INT_DONE_CLR);//clear all interrupt
\r
654 sprd_dolphin_reg_write(NFC_CFG0_REG, cfg0);
\r
655 sprd_dolphin_reg_write(NFC_START_REG, NFC_START);
\r
657 static int sprd_dolphin_nand_wait_finish(struct sprd_dolphin_nand_info *dolphin)
\r
659 unsigned int value;
\r
660 unsigned int counter = 0;
\r
661 while((counter < NFC_TIMEOUT_VAL/*time out*/))
\r
663 value = sprd_dolphin_reg_read(NFC_INT_REG);
\r
664 if(value & INT_DONE_RAW)
\r
670 sprd_dolphin_reg_write(NFC_INT_REG, 0xf00); //clear all interrupt status
\r
671 if(counter > NFC_TIMEOUT_VAL)
\r
678 static void sprd_dolphin_nand_wp_en(struct sprd_dolphin_nand_info *dolphin, int en)
\r
682 dolphin->wp_en = 1;
\r
686 dolphin->wp_en = 0;
\r
689 static void sprd_dolphin_select_chip(struct mtd_info *mtd, int chip)
\r
691 struct sprd_dolphin_nand_info *dolphin = mtd_to_dolphin(mtd);
\r
692 if(chip < 0) { //for release caller
\r
695 //DPRINT("sprd_dolphin_select_chip, %x\r\n", chip);
\r
696 dolphin->chip = chip;
\r
697 #ifdef CONFIG_NAND_SPL
\r
698 nand_hardware_config(mtd,dolphin->nand);
\r
701 static void sprd_dolphin_nand_read_status(struct sprd_dolphin_nand_info *dolphin)
\r
704 //DPRINT("sprd_dolphin_nand_read_status\r\n");
\r
705 sprd_dolphin_nand_ins_init(dolphin);
\r
706 sprd_dolphin_nand_ins_add(NAND_MC_CMD(NAND_CMD_STATUS), dolphin);
\r
707 sprd_dolphin_nand_ins_add(NAND_MC_NOP(10), dolphin);
\r
708 sprd_dolphin_nand_ins_add(NAND_MC_IDST(1), dolphin);
\r
709 sprd_dolphin_nand_ins_add(NFC_MC_DONE_ID, dolphin);
\r
710 sprd_dolphin_reg_write(NFC_CFG0_REG, NFC_ONLY_NAND_MODE);
\r
711 sprd_dolphin_nand_ins_exec(dolphin);
\r
712 sprd_dolphin_nand_wait_finish(dolphin);
\r
713 buf = (uint32_t *)s_oob_data;
\r
714 *buf = sprd_dolphin_reg_read(NFC_STATUS0_REG);
\r
715 dolphin->buf_head = 0;
\r
716 dolphin->_buf_tail = 1;
\r
717 //DPRINT("--sprd_dolphin_nand_read_status--\r\n");
\r
719 static void sprd_dolphin_nand_read_id(struct sprd_dolphin_nand_info *dolphin, uint32_t *buf)
\r
721 //DPRINT("sprd_dolphin_nand_read_id\r\n");
\r
722 sprd_dolphin_nand_ins_init(dolphin);
\r
723 sprd_dolphin_nand_ins_add(NAND_MC_CMD(NAND_CMD_READID), dolphin);
\r
724 sprd_dolphin_nand_ins_add(NAND_MC_ADDR(0), dolphin);
\r
725 sprd_dolphin_nand_ins_add(NAND_MC_NOP(10), dolphin);
\r
726 sprd_dolphin_nand_ins_add(NAND_MC_IDST(8), dolphin);
\r
727 sprd_dolphin_nand_ins_add(NFC_MC_DONE_ID, dolphin);
\r
729 sprd_dolphin_reg_write(NFC_CFG0_REG, NFC_ONLY_NAND_MODE);
\r
730 sprd_dolphin_nand_ins_exec(dolphin);
\r
731 sprd_dolphin_nand_wait_finish(dolphin);
\r
732 *buf = sprd_dolphin_reg_read(NFC_STATUS0_REG);
\r
733 *(buf + 1) = sprd_dolphin_reg_read(NFC_STATUS1_REG);
\r
734 dolphin->buf_head = 0;
\r
735 dolphin->_buf_tail = 8;
\r
736 //DPRINT("--sprd_dolphin_nand_read_id--\r\n");
\r
738 static void sprd_dolphin_nand_reset(struct sprd_dolphin_nand_info *dolphin)
\r
740 //DPRINT("sprd_dolphin_nand_reset\r\n");
\r
741 sprd_dolphin_nand_ins_init(dolphin);
\r
742 sprd_dolphin_nand_ins_add(NAND_MC_CMD(NAND_CMD_RESET), dolphin);
\r
743 sprd_dolphin_nand_ins_add(NFC_MC_WRB0_ID, dolphin); //wait rb
\r
744 sprd_dolphin_nand_ins_add(NFC_MC_DONE_ID, dolphin);
\r
746 sprd_dolphin_reg_write(NFC_CFG0_REG, NFC_ONLY_NAND_MODE);
\r
747 sprd_dolphin_nand_ins_exec(dolphin);
\r
748 sprd_dolphin_nand_wait_finish(dolphin);
\r
749 //DPRINT("--sprd_dolphin_nand_reset--\r\n");
\r
751 static u32 sprd_dolphin_get_decode_sts(u32 index)
\r
756 reg_addr = NFC_STATUS0_REG + (index & 0xfffffffc);
\r
757 shift = (index & 0x3) << 3;
\r
758 err = sprd_dolphin_reg_read(reg_addr);
\r
760 if((err & ECC_ALL_FF))
\r
762 err &= ERR_ERR_NUM0_MASK;
\r
772 #ifdef DOLPHIN_UBOOT
\r
774 static int sprd_dolphin_nand_read_lp(struct mtd_info *mtd,uint8_t *mbuf, uint8_t *sbuf,uint32_t raw)
\r
776 struct sprd_dolphin_nand_info *dolphin = mtd_to_dolphin(mtd);
\r
777 struct nand_chip *chip = dolphin->nand;
\r
779 uint32_t page_addr;
\r
785 page_addr = dolphin->page;
\r
788 column = mtd->writesize;
\r
794 if(chip->options & NAND_BUSWIDTH_16)
\r
798 //DPRINT("sprd_dolphin_nand_read_lp,page_addr = %x,column = %x\r\n",page_addr, column);
\r
799 sprd_dolphin_nand_ins_init(dolphin);
\r
800 sprd_dolphin_nand_ins_add(NAND_MC_CMD(NAND_CMD_READ0), dolphin);
\r
801 sprd_dolphin_nand_ins_add(NAND_MC_ADDR(column & 0xff), dolphin);
\r
803 sprd_dolphin_nand_ins_add(NAND_MC_ADDR(column & 0xff), dolphin);
\r
805 sprd_dolphin_nand_ins_add(NAND_MC_ADDR(page_addr & 0xff), dolphin);
\r
807 sprd_dolphin_nand_ins_add(NAND_MC_ADDR(page_addr & 0xff), dolphin);
\r
809 if (5 == dolphin->a_cycles)// five address cycles
\r
812 sprd_dolphin_nand_ins_add(NAND_MC_ADDR(page_addr & 0xff), dolphin);
\r
814 sprd_dolphin_nand_ins_add(NAND_MC_CMD(NAND_CMD_READSTART), dolphin);
\r
816 sprd_dolphin_nand_ins_add(NFC_MC_WRB0_ID, dolphin); //wait rb
\r
819 sprd_dolphin_nand_ins_add(NAND_MC_SRDT, dolphin);
\r
820 //switch to main part
\r
821 sprd_dolphin_nand_ins_add(NAND_MC_CMD(NAND_CMD_RNDOUT), dolphin);
\r
822 sprd_dolphin_nand_ins_add(NAND_MC_ADDR(0), dolphin);
\r
823 sprd_dolphin_nand_ins_add(NAND_MC_ADDR(0), dolphin);
\r
824 sprd_dolphin_nand_ins_add(NAND_MC_CMD(NAND_CMD_RNDOUTSTART), dolphin);
\r
825 sprd_dolphin_nand_ins_add(NAND_MC_MRDT, dolphin);
\r
829 sprd_dolphin_nand_ins_add(NAND_MC_MRDT, dolphin);
\r
831 sprd_dolphin_nand_ins_add(NFC_MC_DONE_ID, dolphin);
\r
832 //config registers
\r
833 cfg0 = NFC_AUTO_MODE | MAIN_SPAR_APT | ((dolphin->sct_pg - 1)<< SECTOR_NUM_OFFSET);
\r
834 if((!raw) && mbuf && sbuf)
\r
836 cfg0 |= ECC_EN | DETECT_ALL_FF;
\r
838 if(chip->options & NAND_BUSWIDTH_16)
\r
842 cfg1 = (dolphin->info_size) << SPAR_INFO_SIZE_OFFSET;
\r
843 cfg2 = (dolphin->ecc_mode << 12) | (dolphin->info_pos << SPAR_INFO_POS_OFFSET) | ((dolphin->sct_pg - 1) << SPAR_SECTOR_NUM_OFFSET) | dolphin->ecc_pos;
\r
845 #ifndef CONFIG_NAND_SPL
\r
848 Dcache_CleanRegion((unsigned int)mbuf, dolphin->m_size*dolphin->sct_pg);
\r
849 Dcache_InvalRegion((unsigned int)mbuf, dolphin->m_size*dolphin->sct_pg);
\r
854 Dcache_CleanRegion((unsigned int)sbuf, dolphin->s_size*dolphin->sct_pg);
\r
855 Dcache_InvalRegion((unsigned int)sbuf, dolphin->s_size*dolphin->sct_pg);
\r
861 cfg1 |= (dolphin->m_size - 1) | ((dolphin->s_size - 1)<< SPAR_SIZE_OFFSET);
\r
862 sprd_dolphin_reg_write(NFC_MAIN_ADDR_REG, (uint32_t)mbuf);
\r
863 sprd_dolphin_reg_write(NFC_SPAR_ADDR_REG, (uint32_t)sbuf);
\r
864 cfg0 |= MAIN_USE | SPAR_USE;
\r
870 cfg1 |= (dolphin->m_size - 1);
\r
871 sprd_dolphin_reg_write(NFC_MAIN_ADDR_REG, (uint32_t)mbuf);
\r
875 cfg1 |= (dolphin->s_size - 1);
\r
876 sprd_dolphin_reg_write(NFC_MAIN_ADDR_REG, (uint32_t)sbuf);
\r
880 sprd_dolphin_reg_write(NFC_CFG0_REG, cfg0);
\r
881 sprd_dolphin_reg_write(NFC_CFG1_REG, cfg1);
\r
882 sprd_dolphin_reg_write(NFC_CFG2_REG, cfg2);
\r
884 sprd_dolphin_nand_ins_exec(dolphin);
\r
885 sprd_dolphin_nand_wait_finish(dolphin);
\r
887 for(i = 0; i < dolphin->sct_pg; i++) {
\r
888 err = sprd_dolphin_get_decode_sts(i);
\r
889 if(err == ERR_ERR_NUM0_MASK) {
\r
890 mtd->ecc_stats.failed++;
\r
893 mtd->ecc_stats.corrected += err;
\r
902 static int sprd_dolphin_nand_write_lp(struct mtd_info *mtd,const uint8_t *mbuf, uint8_t *sbuf,uint32_t raw)
\r
904 struct sprd_dolphin_nand_info *dolphin = mtd_to_dolphin(mtd);
\r
905 struct nand_chip *chip = dolphin->nand;
\r
907 uint32_t page_addr;
\r
911 page_addr = dolphin->page;
\r
916 column = mtd->writesize;
\r
918 if(chip->options & NAND_BUSWIDTH_16)
\r
923 sprd_dolphin_nand_ins_init(dolphin);
\r
924 sprd_dolphin_nand_ins_add(NAND_MC_CMD(NAND_CMD_SEQIN), dolphin);
\r
925 sprd_dolphin_nand_ins_add(NAND_MC_ADDR(column & 0xff), dolphin);
\r
927 sprd_dolphin_nand_ins_add(NAND_MC_ADDR(column & 0xff), dolphin);
\r
928 sprd_dolphin_nand_ins_add(NAND_MC_ADDR(page_addr & 0xff), dolphin);
\r
930 sprd_dolphin_nand_ins_add(NAND_MC_ADDR(page_addr & 0xff), dolphin);
\r
932 if (5 == dolphin->a_cycles)// five address cycles
\r
935 sprd_dolphin_nand_ins_add(NAND_MC_ADDR(page_addr & 0xff), dolphin);
\r
938 sprd_dolphin_nand_ins_add(NAND_MC_MWDT, dolphin);
\r
941 sprd_dolphin_nand_ins_add(NAND_MC_SWDT, dolphin);
\r
943 sprd_dolphin_nand_ins_add(NAND_MC_CMD(NAND_CMD_PAGEPROG), dolphin);
\r
944 sprd_dolphin_nand_ins_add(NFC_MC_WRB0_ID, dolphin); //wait rb
\r
946 sprd_dolphin_nand_ins_add(NFC_MC_DONE_ID, dolphin);
\r
947 //config registers
\r
948 cfg0 = NFC_AUTO_MODE | NFC_RW | NFC_WPN | MAIN_SPAR_APT | ((dolphin->sct_pg - 1)<< SECTOR_NUM_OFFSET);
\r
949 if((!raw) && mbuf && sbuf)
\r
953 if(chip->options & NAND_BUSWIDTH_16)
\r
957 cfg1 = ((dolphin->info_size) << SPAR_INFO_SIZE_OFFSET);
\r
958 cfg2 = (dolphin->ecc_mode << 12) | (dolphin->info_pos << SPAR_INFO_POS_OFFSET) | ((dolphin->sct_pg - 1) << SPAR_SECTOR_NUM_OFFSET) | dolphin->ecc_pos;
\r
960 #ifndef CONFIG_NAND_SPL
\r
963 Dcache_CleanRegion((unsigned int)mbuf, dolphin->m_size*dolphin->sct_pg);
\r
964 Dcache_InvalRegion((unsigned int)mbuf, dolphin->m_size*dolphin->sct_pg);
\r
969 Dcache_CleanRegion((unsigned int)sbuf, dolphin->s_size*dolphin->sct_pg);
\r
970 Dcache_InvalRegion((unsigned int)sbuf, dolphin->s_size*dolphin->sct_pg);
\r
976 cfg0 |= MAIN_USE | SPAR_USE;
\r
977 cfg1 |= (dolphin->m_size - 1) | ((dolphin->s_size - 1) << SPAR_SIZE_OFFSET);
\r
978 sprd_dolphin_reg_write(NFC_MAIN_ADDR_REG, (uint32_t)mbuf);
\r
979 sprd_dolphin_reg_write(NFC_SPAR_ADDR_REG, (uint32_t)sbuf);
\r
986 cfg1 |= dolphin->m_size - 1;
\r
987 sprd_dolphin_reg_write(NFC_MAIN_ADDR_REG, (uint32_t)mbuf);
\r
991 cfg1 |= dolphin->s_size - 1;
\r
992 sprd_dolphin_reg_write(NFC_MAIN_ADDR_REG, (uint32_t)sbuf);
\r
995 sprd_dolphin_reg_write(NFC_CFG0_REG, cfg0);
\r
996 sprd_dolphin_reg_write(NFC_CFG1_REG, cfg1);
\r
997 sprd_dolphin_reg_write(NFC_CFG2_REG, cfg2);
\r
998 sprd_dolphin_nand_ins_exec(dolphin);
\r
999 sprd_dolphin_nand_wait_finish(dolphin);
\r
1006 #ifdef DOLPHIN_KERNEL
\r
1008 static int sprd_dolphin_nand_read_lp(struct mtd_info *mtd,uint8_t *mbuf, uint8_t *sbuf,uint32_t raw)
\r
1010 struct sprd_dolphin_nand_info *dolphin = mtd_to_dolphin(mtd);
\r
1011 struct nand_chip *chip = dolphin->nand;
\r
1013 uint32_t page_addr;
\r
1019 page_addr = dolphin->page;
\r
1022 column = mtd->writesize;
\r
1028 if(chip->options & NAND_BUSWIDTH_16)
\r
1032 //DPRINT("sprd_dolphin_nand_read_lp,page_addr = %x,column = %x\r\n",page_addr, column);
\r
1033 sprd_dolphin_nand_ins_init(dolphin);
\r
1034 sprd_dolphin_nand_ins_add(NAND_MC_CMD(NAND_CMD_READ0), dolphin);
\r
1035 sprd_dolphin_nand_ins_add(NAND_MC_ADDR(column & 0xff), dolphin);
\r
1037 sprd_dolphin_nand_ins_add(NAND_MC_ADDR(column & 0xff), dolphin);
\r
1039 sprd_dolphin_nand_ins_add(NAND_MC_ADDR(page_addr & 0xff), dolphin);
\r
1041 sprd_dolphin_nand_ins_add(NAND_MC_ADDR(page_addr & 0xff), dolphin);
\r
1043 if (5 == dolphin->a_cycles)// five address cycles
\r
1046 sprd_dolphin_nand_ins_add(NAND_MC_ADDR(page_addr & 0xff), dolphin);
\r
1048 sprd_dolphin_nand_ins_add(NAND_MC_CMD(NAND_CMD_READSTART), dolphin);
\r
1050 sprd_dolphin_nand_ins_add(NFC_MC_WRB0_ID, dolphin); //wait rb
\r
1053 sprd_dolphin_nand_ins_add(NAND_MC_SRDT, dolphin);
\r
1054 //switch to main part
\r
1055 sprd_dolphin_nand_ins_add(NAND_MC_CMD(NAND_CMD_RNDOUT), dolphin);
\r
1056 sprd_dolphin_nand_ins_add(NAND_MC_ADDR(0), dolphin);
\r
1057 sprd_dolphin_nand_ins_add(NAND_MC_ADDR(0), dolphin);
\r
1058 sprd_dolphin_nand_ins_add(NAND_MC_CMD(NAND_CMD_RNDOUTSTART), dolphin);
\r
1059 sprd_dolphin_nand_ins_add(NAND_MC_MRDT, dolphin);
\r
1063 sprd_dolphin_nand_ins_add(NAND_MC_MRDT, dolphin);
\r
1065 sprd_dolphin_nand_ins_add(NFC_MC_DONE_ID, dolphin);
\r
1066 //config registers
\r
1067 cfg0 = NFC_AUTO_MODE | MAIN_SPAR_APT | ((dolphin->sct_pg - 1)<< SECTOR_NUM_OFFSET);
\r
1068 if((!raw) && mbuf && sbuf)
\r
1070 cfg0 |= ECC_EN | DETECT_ALL_FF;
\r
1072 if(chip->options & NAND_BUSWIDTH_16)
\r
1074 cfg0 |= BUS_WIDTH;
\r
1076 cfg1 = (dolphin->info_size) << SPAR_INFO_SIZE_OFFSET;
\r
1077 cfg2 = (dolphin->ecc_mode << 12) | (dolphin->info_pos << SPAR_INFO_POS_OFFSET) | ((dolphin->sct_pg - 1) << SPAR_SECTOR_NUM_OFFSET) | dolphin->ecc_pos;
\r
1081 cfg1 |= (dolphin->m_size - 1) | ((dolphin->s_size - 1)<< SPAR_SIZE_OFFSET);
\r
1082 sprd_dolphin_reg_write(NFC_MAIN_ADDR_REG, dolphin->p_mbuf);
\r
1083 sprd_dolphin_reg_write(NFC_SPAR_ADDR_REG, dolphin->p_oob);
\r
1084 cfg0 |= MAIN_USE | SPAR_USE;
\r
1090 cfg1 |= (dolphin->m_size - 1);
\r
1091 sprd_dolphin_reg_write(NFC_MAIN_ADDR_REG, dolphin->p_mbuf);
\r
1095 cfg1 |= (dolphin->s_size - 1);
\r
1096 sprd_dolphin_reg_write(NFC_MAIN_ADDR_REG, dolphin->p_oob);
\r
1100 sprd_dolphin_reg_write(NFC_CFG0_REG, cfg0);
\r
1101 sprd_dolphin_reg_write(NFC_CFG1_REG, cfg1);
\r
1102 sprd_dolphin_reg_write(NFC_CFG2_REG, cfg2);
\r
1104 sprd_dolphin_nand_ins_exec(dolphin);
\r
1105 sprd_dolphin_nand_wait_finish(dolphin);
\r
1107 for(i = 0; i < dolphin->sct_pg; i++) {
\r
1108 err = sprd_dolphin_get_decode_sts(i);
\r
1109 if(err == ERR_ERR_NUM0_MASK) {
\r
1110 mtd->ecc_stats.failed++;
\r
1113 mtd->ecc_stats.corrected += err;
\r
1119 memcpy(mbuf, (const void *)dolphin->v_mbuf, dolphin->write_size);
\r
1122 memcpy(sbuf, (const void *)dolphin->v_oob, dolphin->oob_size);
\r
1130 static int sprd_dolphin_nand_write_lp(struct mtd_info *mtd,const uint8_t *mbuf, uint8_t *sbuf,uint32_t raw)
\r
1132 struct sprd_dolphin_nand_info *dolphin = mtd_to_dolphin(mtd);
\r
1133 struct nand_chip *chip = dolphin->nand;
\r
1135 uint32_t page_addr;
\r
1139 page_addr = dolphin->page;
\r
1144 column = mtd->writesize;
\r
1146 if(chip->options & NAND_BUSWIDTH_16)
\r
1152 memcpy((void *)dolphin->v_mbuf, (const void *)mbuf, dolphin->write_size);
\r
1155 memcpy((void *)dolphin->v_oob, (const void *)sbuf, dolphin->oob_size);
\r
1158 sprd_dolphin_nand_ins_init(dolphin);
\r
1159 sprd_dolphin_nand_ins_add(NAND_MC_CMD(NAND_CMD_SEQIN), dolphin);
\r
1160 sprd_dolphin_nand_ins_add(NAND_MC_ADDR(column & 0xff), dolphin);
\r
1162 sprd_dolphin_nand_ins_add(NAND_MC_ADDR(column & 0xff), dolphin);
\r
1163 sprd_dolphin_nand_ins_add(NAND_MC_ADDR(page_addr & 0xff), dolphin);
\r
1165 sprd_dolphin_nand_ins_add(NAND_MC_ADDR(page_addr & 0xff), dolphin);
\r
1167 if (5 == dolphin->a_cycles)// five address cycles
\r
1170 sprd_dolphin_nand_ins_add(NAND_MC_ADDR(page_addr & 0xff), dolphin);
\r
1173 sprd_dolphin_nand_ins_add(NAND_MC_MWDT, dolphin);
\r
1176 sprd_dolphin_nand_ins_add(NAND_MC_SWDT, dolphin);
\r
1178 sprd_dolphin_nand_ins_add(NAND_MC_CMD(NAND_CMD_PAGEPROG), dolphin);
\r
1179 sprd_dolphin_nand_ins_add(NFC_MC_WRB0_ID, dolphin); //wait rb
\r
1181 sprd_dolphin_nand_ins_add(NFC_MC_DONE_ID, dolphin);
\r
1182 //config registers
\r
1183 cfg0 = NFC_AUTO_MODE | NFC_RW | NFC_WPN | MAIN_SPAR_APT | ((dolphin->sct_pg - 1)<< SECTOR_NUM_OFFSET);
\r
1184 if((!raw) && mbuf && sbuf)
\r
1188 if(chip->options & NAND_BUSWIDTH_16)
\r
1190 cfg0 |= BUS_WIDTH;
\r
1192 cfg1 = ((dolphin->info_size) << SPAR_INFO_SIZE_OFFSET);
\r
1193 cfg2 = (dolphin->ecc_mode << 12) | (dolphin->info_pos << SPAR_INFO_POS_OFFSET) | ((dolphin->sct_pg - 1) << SPAR_SECTOR_NUM_OFFSET) | dolphin->ecc_pos;
\r
1197 cfg0 |= MAIN_USE | SPAR_USE;
\r
1198 cfg1 |= (dolphin->m_size - 1) | ((dolphin->s_size - 1) << SPAR_SIZE_OFFSET);
\r
1199 sprd_dolphin_reg_write(NFC_MAIN_ADDR_REG, dolphin->p_mbuf);
\r
1200 sprd_dolphin_reg_write(NFC_SPAR_ADDR_REG, dolphin->p_oob);
\r
1207 cfg1 |= dolphin->m_size - 1;
\r
1208 sprd_dolphin_reg_write(NFC_MAIN_ADDR_REG, dolphin->p_mbuf);
\r
1212 cfg1 |= dolphin->s_size - 1;
\r
1213 sprd_dolphin_reg_write(NFC_MAIN_ADDR_REG, dolphin->p_oob);
\r
1216 sprd_dolphin_reg_write(NFC_CFG0_REG, cfg0);
\r
1217 sprd_dolphin_reg_write(NFC_CFG1_REG, cfg1);
\r
1218 sprd_dolphin_reg_write(NFC_CFG2_REG, cfg2);
\r
1219 sprd_dolphin_nand_ins_exec(dolphin);
\r
1220 sprd_dolphin_nand_wait_finish(dolphin);
\r
1227 static int sprd_dolphin_nand_read_sp(struct mtd_info *mtd,uint8_t *mbuf, uint8_t *sbuf,uint32_t raw)
\r
1231 static int sprd_dolphin_nand_write_sp(struct mtd_info *mtd,const uint8_t *mbuf, uint8_t *sbuf,uint32_t raw)
\r
1235 static void sprd_dolphin_erase(struct mtd_info *mtd, int page_addr)
\r
1237 struct sprd_dolphin_nand_info *dolphin = mtd_to_dolphin(mtd);
\r
1238 uint32_t cfg0 = 0;
\r
1239 //DPRINT("sprd_dolphin_erase, %x\r\n", page_addr);
\r
1240 sprd_dolphin_nand_ins_init(dolphin);
\r
1241 sprd_dolphin_nand_ins_add(NAND_MC_CMD(NAND_CMD_ERASE1), dolphin);
\r
1242 sprd_dolphin_nand_ins_add(NAND_MC_ADDR(page_addr & 0xff), dolphin);
\r
1244 sprd_dolphin_nand_ins_add(NAND_MC_ADDR(page_addr & 0xff), dolphin);
\r
1245 if((5 == dolphin->a_cycles) || ((4 == dolphin->a_cycles) && (512 == dolphin->write_size)))
\r
1248 sprd_dolphin_nand_ins_add(NAND_MC_ADDR(page_addr & 0xff), dolphin);
\r
1250 sprd_dolphin_nand_ins_add(NAND_MC_CMD(NAND_CMD_ERASE2), dolphin);
\r
1251 sprd_dolphin_nand_ins_add(NFC_MC_WRB0_ID, dolphin); //wait rb
\r
1253 sprd_dolphin_nand_ins_add(NFC_MC_DONE_ID, dolphin);
\r
1254 cfg0 = NFC_WPN | NFC_ONLY_NAND_MODE;
\r
1255 sprd_dolphin_reg_write(NFC_CFG0_REG, cfg0);
\r
1256 sprd_dolphin_nand_ins_exec(dolphin);
\r
1257 sprd_dolphin_nand_wait_finish(dolphin);
\r
1258 //DPRINT("--sprd_dolphin_erase--\r\n");
\r
1260 static uint8_t sprd_dolphin_read_byte(struct mtd_info *mtd)
\r
1262 uint8_t ch = 0xff;
\r
1263 struct sprd_dolphin_nand_info *dolphin = mtd_to_dolphin(mtd);
\r
1264 if(dolphin->buf_head < dolphin->_buf_tail)
\r
1266 ch = s_oob_data[dolphin->buf_head ++];
\r
1270 static uint16_t sprd_dolphin_read_word(struct mtd_info *mtd)
\r
1272 uint16_t data = 0xffff;
\r
1273 struct sprd_dolphin_nand_info *dolphin = mtd_to_dolphin(mtd);
\r
1274 if(dolphin->buf_head < (dolphin->_buf_tail - 1))
\r
1276 data = s_oob_data[dolphin->buf_head ++];
\r
1277 data |= ((uint16_t)s_oob_data[dolphin->buf_head ++]) << 8;
\r
1282 static int sprd_dolphin_waitfunc(struct mtd_info *mtd, struct nand_chip *chip)
\r
1287 static int sprd_dolphin_ecc_calculate(struct mtd_info *mtd, const uint8_t *data,
\r
1288 uint8_t *ecc_code)
\r
1293 static int sprd_dolphin_ecc_correct(struct mtd_info *mtd, uint8_t *data,
\r
1294 uint8_t *read_ecc, uint8_t *calc_ecc)
\r
1299 static int sprd_dolphin_read_page(struct mtd_info *mtd, struct nand_chip *chip,
\r
1300 uint8_t *buf, int page)
\r
1302 struct sprd_dolphin_nand_info *dolphin = mtd_to_dolphin(mtd);
\r
1303 dolphin->page = page;
\r
1304 if(512 == mtd->writesize)
\r
1306 sprd_dolphin_nand_read_sp(mtd, buf, chip->oob_poi, 0);
\r
1310 sprd_dolphin_nand_read_lp(mtd, buf, chip->oob_poi, 0);
\r
1314 static int sprd_dolphin_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
\r
1315 uint8_t *buf, int page)
\r
1317 struct sprd_dolphin_nand_info *dolphin = mtd_to_dolphin(mtd);
\r
1318 dolphin->page = page;
\r
1319 if(512 == mtd->writesize)
\r
1321 sprd_dolphin_nand_read_sp(mtd, buf, chip->oob_poi, 1);
\r
1325 sprd_dolphin_nand_read_lp(mtd, buf, chip->oob_poi, 1);
\r
1329 static int sprd_dolphin_read_oob(struct mtd_info *mtd, struct nand_chip *chip,
\r
1330 int page, int sndcmd)
\r
1332 struct sprd_dolphin_nand_info *dolphin = mtd_to_dolphin(mtd);
\r
1333 dolphin->page = page;
\r
1334 if(512 == mtd->writesize)
\r
1336 sprd_dolphin_nand_read_sp(mtd, 0, chip->oob_poi, 1);
\r
1340 sprd_dolphin_nand_read_lp(mtd, 0, chip->oob_poi, 1);
\r
1344 static void sprd_dolphin_write_page(struct mtd_info *mtd, struct nand_chip *chip,
\r
1345 const uint8_t *buf)
\r
1347 if(512 == mtd->writesize)
\r
1349 sprd_dolphin_nand_write_sp(mtd, buf, chip->oob_poi, 0);
\r
1353 sprd_dolphin_nand_write_lp(mtd, buf, chip->oob_poi, 0);
\r
1357 static void sprd_dolphin_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
\r
1358 const uint8_t *buf)
\r
1360 if(512 == mtd->writesize)
\r
1362 sprd_dolphin_nand_write_sp(mtd, buf, chip->oob_poi, 1);
\r
1366 sprd_dolphin_nand_write_lp(mtd, buf, chip->oob_poi, 1);
\r
1369 static int sprd_dolphin_write_oob(struct mtd_info *mtd, struct nand_chip *chip,
\r
1372 struct sprd_dolphin_nand_info *dolphin = mtd_to_dolphin(mtd);
\r
1373 dolphin->page = page;
\r
1374 if(512 == mtd->writesize)
\r
1376 sprd_dolphin_nand_write_sp(mtd, 0, chip->oob_poi, 1);
\r
1380 sprd_dolphin_nand_write_lp(mtd, 0, chip->oob_poi, 1);
\r
1387 * nand_block_bad - [DEFAULT] Read bad block marker from the chip
\r
1388 * @mtd: MTD device structure
\r
1389 * @ofs: offset from device start
\r
1390 * @getchip: 0, if the chip is already selected
\r
1392 * Check, if the block is bad.
\r
1394 static int sprd_dolphin_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)
\r
1396 int page, chipnr, res = 0;
\r
1397 struct sprd_dolphin_nand_info *dolphin = mtd_to_dolphin(mtd);
\r
1398 struct nand_chip *chip = mtd->priv;
\r
1402 page = (int)((long)ofs >> chip->page_shift) & chip->pagemask;
\r
1405 chipnr = (int)((long)ofs >> chip->chip_shift);
\r
1406 /* Select the NAND device */
\r
1407 chip->select_chip(mtd, chipnr);
\r
1410 chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page);
\r
1411 if(512 == dolphin->write_size) {
\r
1412 sprd_dolphin_nand_read_sp(mtd, 0, s_oob_data, 1);
\r
1415 sprd_dolphin_nand_read_lp(mtd, 0, s_oob_data, 1);
\r
1417 dolphin->buf_head = 0;
\r
1418 dolphin->_buf_tail = mtd->oobsize;
\r
1419 buf = (uint16_t *)(s_oob_data + chip->badblockpos);
\r
1421 if (chip->options & NAND_BUSWIDTH_16) {
\r
1423 if ((bad & 0xFF) != 0xff) {
\r
1427 bad = *(buf) & 0xff;
\r
1435 static void sprd_dolphin_nand_cmdfunc(struct mtd_info *mtd, unsigned int command,
\r
1436 int column, int page_addr)
\r
1438 struct sprd_dolphin_nand_info *dolphin = mtd_to_dolphin(mtd);
\r
1439 /* Emulate NAND_CMD_READOOB */
\r
1440 if (command == NAND_CMD_READOOB) {
\r
1441 column += mtd->writesize;
\r
1442 command = NAND_CMD_READ0;
\r
1445 * program and erase have their own busy handlers
\r
1446 * status, sequential in, and deplete1 need no delay
\r
1448 switch (command) {
\r
1449 case NAND_CMD_STATUS:
\r
1450 sprd_dolphin_nand_read_status(dolphin);
\r
1452 case NAND_CMD_READID:
\r
1453 sprd_dolphin_nand_read_id(dolphin, (uint32_t *)s_oob_data);
\r
1455 case NAND_CMD_RESET:
\r
1456 sprd_dolphin_nand_reset(dolphin);
\r
1458 case NAND_CMD_ERASE1:
\r
1459 sprd_dolphin_erase(mtd, page_addr);
\r
1461 case NAND_CMD_READ0:
\r
1462 case NAND_CMD_SEQIN:
\r
1463 dolphin->column = column;
\r
1464 dolphin->page = page_addr;
\r
1469 static void sprd_dolphin_nand_hwecc_ctl(struct mtd_info *mtd, int mode)
\r
1471 return; //do nothing
\r
1476 static void dolphin_set_timing_config(struct sprd_dolphin_nand_info *dolphin , uint32_t nfc_clk_MHz) {
\r
1479 u32 reg_val, temp_val;
\r
1480 struct sprd_dolphin_nand_param * param;
\r
1483 sprd_dolphin_nand_read_id(dolphin, (uint32_t *)id_buf);
\r
1485 /* get timing para */
\r
1486 array = ARRAY_SIZE(sprd_dolphin_nand_param_tb);
\r
1487 for (index = 0; index < array; index ++) {
\r
1488 param = sprd_dolphin_nand_param_tb + index;
\r
1489 if ((param->id[0] == id_buf[0])
\r
1490 && (param->id[1] == id_buf[1])
\r
1491 && (param->id[2] == id_buf[2])
\r
1492 && (param->id[3] == id_buf[3])
\r
1493 && (param->id[4] == id_buf[4]))
\r
1497 if (index < array) {
\r
1500 /* get acs value : 0ns */
\r
1501 reg_val |= ((2 & 0x1F) << NFC_ACS_OFFSET);
\r
1503 /* get ace value + 6ns read delay time, and rwl added */
\r
1504 temp_val = (param->ace_ns + 6) * nfc_clk_MHz / 1000;
\r
1505 if (((param->ace_ns * nfc_clk_MHz) % 1000) != 0) {
\r
1508 reg_val |= ((temp_val & 0x1F) << NFC_ACE_OFFSET);
\r
1510 /* get rws value : 20 ns */
\r
1511 temp_val = 20 * nfc_clk_MHz / 1000;
\r
1512 if (((param->ace_ns * nfc_clk_MHz) % 1000) != 0) {
\r
1515 reg_val |= ((temp_val & 0x3F) << NFC_RWS_OFFSET);
\r
1517 /* get rws value : 0 ns */
\r
1518 reg_val |= ((2 & 0x1F) << NFC_RWE_OFFSET);
\r
1520 /* get rwh value */
\r
1521 temp_val = (param->rwh_ns + 6) * nfc_clk_MHz / 1000;
\r
1522 if (((param->ace_ns * nfc_clk_MHz) % 1000) != 0) {
\r
1525 reg_val |= ((temp_val & 0x1F) << NFC_RWH_OFFSET);
\r
1527 /* get rwl value, 6 is read delay time*/
\r
1528 temp_val = (param->rwl_ns + 6) * nfc_clk_MHz / 1000;
\r
1529 if (((param->ace_ns * nfc_clk_MHz) % 1000) != 0) {
\r
1532 reg_val |= (temp_val & 0x3F);
\r
1534 DPRINT("nand timing val: 0x%x\n\r", reg_val);
\r
1536 sprd_dolphin_reg_write(NFC_TIMING_REG, reg_val);
\r
1541 #ifdef DOLPHIN_UBOOT
\r
1542 #define DOLPHIN_AHB_BASE SPRD_AHB_PHYS
\r
1543 #define DOLPHIN_PIN_BASE SPRD_PIN_PHYS
\r
1544 #define DOLPHIN_AHB_RST (DOLPHIN_AHB_BASE + 0x0004)
\r
1545 #define DOLPHIN_NANC_CLK_CFG (DOLPHIN_AHB_BASE + 0x0060)
\r
1547 #define DOLPHIN_ADISLAVE_BASE SPRD_ADISLAVE_PHYS
\r
1548 #define DOLPHIN_ANA_CTL_GLB_BASE (DOLPHIN_ADISLAVE_BASE + 0x8800)
\r
1550 #define DOLPHIN_NFC_REG_BASE SPRD_NFC_PHYS
\r
1551 #define DOLPHIN_NFC_TIMING_REG (DOLPHIN_NFC_REG_BASE + 0x14)
\r
1552 #define DOLPHIN_NFC_TIMEOUT_REG (DOLPHIN_NFC_REG_BASE + 0x34)
\r
1555 #ifdef DOLPHIN_KERNEL
\r
1556 #define DOLPHIN_AHB_BASE SPRD_AHB_BASE
\r
1557 #define DOLPHIN_PIN_BASE SPRD_PIN_BASE
\r
1558 #define DOLPHIN_AHB_RST (DOLPHIN_AHB_BASE + 0x0004)
\r
1559 #define DOLPHIN_NANC_CLK_CFG (DOLPHIN_AHB_BASE + 0x0060)
\r
1561 #define DOLPHIN_ADISLAVE_BASE SPRD_ADISLAVE_BASE
\r
1562 #define DOLPHIN_ANA_CTL_GLB_BASE (DOLPHIN_ADISLAVE_BASE + 0x8800)
\r
1564 #define DOLPHIN_NFC_REG_BASE SPRD_NFC_BASE
\r
1565 #define DOLPHIN_NFC_TIMING_REG (DOLPHIN_NFC_REG_BASE + 0x14)
\r
1566 #define DOLPHIN_NFC_TIMEOUT_REG (DOLPHIN_NFC_REG_BASE + 0x34)
\r
1570 static void sprd_dolphin_nand_hw_init(struct sprd_dolphin_nand_info *dolphin)
\r
1575 //sprd_dolphin_reg_and(DOLPHIN_NANC_CLK_CFG, ~(BIT(1) | BIT(0)));
\r
1576 //sprd_dolphin_reg_or(DOLPHIN_NANC_CLK_CFG, BIT(0));
\r
1578 sprd_dolphin_reg_or(DOLPHIN_AHB_BASE,BIT(19) | BIT(18) | BIT(17) | BIT(6));
\r
1580 sprd_dolphin_reg_or(DOLPHIN_AHB_RST,BIT(9));
\r
1582 sprd_dolphin_reg_and(DOLPHIN_AHB_RST, ~(BIT(9)));
\r
1584 val = (3) | (4 << NFC_RWH_OFFSET) | (3 << NFC_RWE_OFFSET) | (3 << NFC_RWS_OFFSET) | (3 << NFC_ACE_OFFSET) | (3 << NFC_ACS_OFFSET);
\r
1585 sprd_dolphin_reg_write(DOLPHIN_NFC_TIMING_REG, val);
\r
1586 sprd_dolphin_reg_write(DOLPHIN_NFC_TIMEOUT_REG, 0xffffffff);
\r
1587 //sprd_dolphin_reg_write(DOLPHIN_NFC_REG_BASE + 0x118, 3);
\r
1590 sprd_tiger_reg_or(REG_PIN_NFRB, BIT_7); //set PIN_NFRB pull up
\r
1591 for (i=REG_PIN_NFWPN; i<=REG_PIN_NFD15; i+=4)
\r
1593 sprd_tiger_reg_or( i, BIT_9);
\r
1594 sprd_tiger_reg_and(i, ~(BIT_8|BIT_10|BIT_6));
\r
1599 sprd_dolphin_reg_or(DOLPHIN_PIN_BASE + REG_PIN_NFRB, BIT(7));
\r
1600 for (i = REG_PIN_NFWPN; i <= REG_PIN_NFD15; i += 4)
\r
1602 sprd_dolphin_reg_or(DOLPHIN_PIN_BASE + i, BIT(9));
\r
1603 sprd_dolphin_reg_and(DOLPHIN_PIN_BASE + i, ~(BIT(10) | BIT(8) | BIT(6)));
\r
1604 sprd_dolphin_reg_and(DOLPHIN_PIN_BASE + i, ~(BIT(4) | BIT(5)));
\r
1610 sprd_dolphin_reg_or(DOLPHIN_PIN_BASE + REG_PIN_NFWPN, BIT(7) | BIT(8) | BIT(9));
\r
1611 sprd_dolphin_reg_and(DOLPHIN_PIN_BASE + REG_PIN_NFWPN, ~(BIT(4) | BIT(5)));
\r
1612 sprd_dolphin_reg_or(DOLPHIN_PIN_BASE + REG_PIN_NFRB, BIT(7) | BIT(8) | BIT(9));
\r
1613 sprd_dolphin_reg_and(DOLPHIN_PIN_BASE + REG_PIN_NFRB, ~(BIT(4) | BIT(5)));
\r
1614 for(i = 0; i < 22; ++i)
\r
1616 sprd_dolphin_reg_or(DOLPHIN_PIN_BASE + REG_PIN_NFCLE + (i << 2), BIT(7) | BIT(8) | BIT(9));
\r
1617 sprd_dolphin_reg_and(DOLPHIN_PIN_BASE + REG_PIN_NFCLE + (i << 2), ~(BIT(4) | BIT(5)));
\r
1622 i = sprd_dolphin_reg_read(DOLPHIN_ANA_CTL_GLB_BASE+0x3c);
\r
1625 sprd_dolphin_reg_write(DOLPHIN_ANA_CTL_GLB_BASE + 0x3c, i);
\r
1627 i = sprd_dolphin_reg_read(DOLPHIN_ANA_CTL_GLB_BASE+0x20);
\r
1630 sprd_dolphin_reg_write(DOLPHIN_ANA_CTL_GLB_BASE + 0x20, i);
\r
1633 //close write protect
\r
1634 sprd_dolphin_nand_wp_en(dolphin, 0);
\r
1638 int board_nand_init(struct nand_chip *chip)
\r
1640 //DPRINT("board_nand_init\r\n");
\r
1642 sprd_dolphin_nand_hw_init(&g_dolphin);
\r
1644 chip->select_chip = sprd_dolphin_select_chip;
\r
1645 chip->cmdfunc = sprd_dolphin_nand_cmdfunc;
\r
1646 chip->read_byte = sprd_dolphin_read_byte;
\r
1647 chip->read_word = sprd_dolphin_read_word;
\r
1648 chip->waitfunc = sprd_dolphin_waitfunc;
\r
1649 chip->ecc.mode = NAND_ECC_HW;
\r
1650 chip->ecc.calculate = sprd_dolphin_ecc_calculate;
\r
1651 chip->ecc.hwctl = sprd_dolphin_nand_hwecc_ctl;
\r
1653 chip->ecc.correct = sprd_dolphin_ecc_correct;
\r
1654 chip->ecc.read_page = sprd_dolphin_read_page;
\r
1655 chip->ecc.read_page_raw = sprd_dolphin_read_page_raw;
\r
1656 chip->ecc.write_page = sprd_dolphin_write_page;
\r
1657 chip->ecc.write_page_raw = sprd_dolphin_write_page_raw;
\r
1658 chip->ecc.read_oob = sprd_dolphin_read_oob;
\r
1659 chip->ecc.write_oob = sprd_dolphin_write_oob;
\r
1660 chip->erase_cmd = sprd_dolphin_erase;
\r
1662 chip->ecc.bytes = CONFIG_SYS_NAND_ECCBYTES;
\r
1663 g_dolphin.ecc_mode = ecc_mode_convert(CONFIG_SYS_NAND_ECC_MODE);
\r
1664 g_dolphin.nand = chip;
\r
1666 dolphin_set_timing_config(&g_dolphin, 64); /* 153 is current clock 153MHz */
\r
1668 chip->eccbitmode = CONFIG_SYS_NAND_ECC_MODE;
\r
1669 chip->ecc.size = CONFIG_SYS_NAND_ECCSIZE;
\r
1671 chip->chip_delay = 20;
\r
1672 chip->priv = &g_dolphin;
\r
1674 //printf("v2 board eccbitmode %d\n", chip->eccbitmode);
\r
1676 chip->options = NAND_BUSWIDTH_16;
\r
1681 #ifdef DOLPHIN_UBOOT
\r
1682 #ifndef CONFIG_NAND_SPL
\r
1683 void McuReadNandType(unsigned char *array)
\r
1689 static unsigned long nfc_read_status(void)
\r
1691 unsigned long status = 0;
\r
1693 sprd_dolphin_nand_read_status(&g_dolphin);
\r
1694 status = s_oob_data[0];
\r
1699 #ifndef CONFIG_NAND_SPL
\r
1700 static int sprd_scan_one_block(int blk, int erasesize, int writesize)
\r
1703 int status = 1, ii;
\r
1705 int oobsize = mtdoobsize;
\r
1706 int column, page_addr;
\r
1708 page_addr = blk * (erasesize / writesize);
\r
1709 for (ii = 0; ii < 2; ii ++) {
\r
1710 DPRINT("please debug here : %s %d\n", __FUNCTION__, __LINE__);
\r
1711 sprd_dolphin_nand_ins_init(&g_dolphin);
\r
1712 sprd_dolphin_nand_ins_add(NAND_MC_CMD(NAND_CMD_READ0), &g_dolphin);
\r
1713 sprd_dolphin_nand_ins_add(NAND_MC_CMD(NAND_CMD_READSTART), &g_dolphin);
\r
1714 if ((s_oob_data[0] != 0xff) || (s_oob_data[1] != 0xff))
\r
1716 } //for (ii = 0; ii < 2; ii ++)
\r
1718 if ((s_oob_data[0] == 0xff) && (s_oob_data[1] == 0xff))
\r
1719 status = 0; //good block
\r
1721 status = 1; //bad block
\r
1726 static unsigned long nand_ctl_erase_block(int blk, int erasesize, int writesize)
\r
1731 page_addr = blk * (erasesize / writesize);
\r
1732 sprd_dolphin_erase(&g_dolphin, page_addr);
\r
1733 status = nfc_read_status();
\r
1740 #ifndef CONFIG_NAND_SPL
\r
1741 void nand_scan_patition(int blocks, int erasesize, int writesize)
\r
1748 for (blk = 0; blk < blocks; blk ++) {
\r
1749 ret = sprd_scan_one_block(blk, erasesize, writesize);
\r
1751 DPRINT("\n%d is bad, scrub to erase it, ", blk);
\r
1752 ret = nand_ctl_erase_block(blk, erasesize, writesize);
\r
1753 DPRINT("0x%02x\n", ret);
\r
1755 ret = nand_ctl_erase_block(blk, erasesize, writesize);
\r
1756 DPRINT("erasing block : %d %d % \r", blk, (blk * 100 ) / blocks);
\r
1760 int nand_scan_block(int block, int erasesize, int writesize){
\r
1762 ret = nand_ctl_erase_block(block, erasesize, writesize);
\r
1768 #endif //DOLPHIN_UBOOT end
\r
1772 #ifdef DOLPHIN_KERNEL
\r
1773 extern int parse_mtd_partitions(struct mtd_info *master, const char **types,
\r
1774 struct mtd_partition **pparts,
\r
1775 struct mtd_part_parser_data *data);
\r
1777 static struct mtd_info *sprd_mtd = NULL;
\r
1778 #ifdef CONFIG_MTD_CMDLINE_PARTS
\r
1779 const char *part_probes[] = { "cmdlinepart", NULL };
\r
1782 static int sprd_nand_dma_init(struct sprd_dolphin_nand_info *dolphin)
\r
1784 dma_addr_t phys_addr = 0;
\r
1785 void *virt_ptr = 0;
\r
1786 virt_ptr = dma_alloc_coherent(NULL, dolphin->write_size, &phys_addr, GFP_KERNEL);
\r
1787 if (virt_ptr == NULL) {
\r
1788 DPRINT(KERN_ERR "NAND - Failed to allocate memory for DMA main buffer\n");
\r
1791 dolphin->v_mbuf = (u32)virt_ptr;
\r
1792 dolphin->p_mbuf = (u32)phys_addr;
\r
1794 virt_ptr = dma_alloc_coherent(NULL, dolphin->oob_size, &phys_addr, GFP_KERNEL);
\r
1795 if (virt_ptr == NULL) {
\r
1796 DPRINT(KERN_ERR "NAND - Failed to allocate memory for DMA oob buffer\n");
\r
1797 dma_free_coherent(NULL, dolphin->write_size, (void *)dolphin->v_mbuf, (dma_addr_t)dolphin->p_mbuf);
\r
1800 dolphin->v_oob = (u32)virt_ptr;
\r
1801 dolphin->p_oob = (u32)phys_addr;
\r
1804 static void sprd_nand_dma_deinit(struct sprd_dolphin_nand_info *dolphin)
\r
1806 dma_free_coherent(NULL, dolphin->write_size, (void *)dolphin->v_mbuf, (dma_addr_t)dolphin->p_mbuf);
\r
1807 dma_free_coherent(NULL, dolphin->write_size, (void *)dolphin->v_oob, (dma_addr_t)dolphin->p_oob);
\r
1809 static int sprd_nand_probe(struct platform_device *pdev)
\r
1811 struct nand_chip *this;
\r
1812 struct resource *regs = NULL;
\r
1813 struct mtd_partition *partitions = NULL;
\r
1814 int num_partitions = 0;
\r
1817 regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
\r
1819 dev_err(&pdev->dev,"resources unusable\n");
\r
1823 memset(&g_dolphin, 0 , sizeof(g_dolphin));
\r
1825 platform_set_drvdata(pdev, &g_dolphin);
\r
1826 g_dolphin.pdev = pdev;
\r
1828 sprd_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL);
\r
1829 this = (struct nand_chip *)(&sprd_mtd[1]);
\r
1830 memset((char *)sprd_mtd, 0, sizeof(struct mtd_info));
\r
1831 memset((char *)this, 0, sizeof(struct nand_chip));
\r
1833 sprd_mtd->priv = this;
\r
1835 this->options |= NAND_BUSWIDTH_16;
\r
1836 this->options |= NAND_NO_READRDY;
\r
1838 board_nand_init(this);
\r
1841 if (sprd_dolphin_nand_reset(&g_dolphin) != 0)
\r
1844 printk("nand reset failed!!!!!!!!!!!!!\n");
\r
1849 if (sprd_dolphin_nand_read_id(&g_dolphin, (uint32_t *)s_oob_data) != 0)
\r
1852 printk("nand read id failed, no nand device!!!!!!!!!!!!!\n");
\r
1855 printk("nand read id ok, nand exists!!!!!!!!!!!!!\n");
\r
1857 //nand_scan(sprd_mtd, 1);
\r
1858 /* first scan to find the device and get the page size */
\r
1859 if (nand_scan_ident(sprd_mtd, 1, NULL)) {
\r
1863 sprd_dolphin_nand_read_id(&g_dolphin, (uint32_t *)s_oob_data);
\r
1864 nand_hardware_config(sprd_mtd, this, s_oob_data);
\r
1865 if(sprd_nand_dma_init(&g_dolphin) != 0) {
\r
1869 //this->IO_ADDR_R = g_dolphin.v_mbuf;
\r
1870 //this->IO_ADDR_W = g_dolphin.v_mbuf;
\r
1872 /* second phase scan */
\r
1873 if (nand_scan_tail(sprd_mtd)) {
\r
1878 sprd_mtd->name = "sprd-nand";
\r
1879 num_partitions = parse_mtd_partitions(sprd_mtd, part_probes, &partitions, 0);
\r
1881 if ((!partitions) || (num_partitions == 0)) {
\r
1882 DPRINT("No parititions defined, or unsupported device.\n");
\r
1886 #ifdef CONFIG_MTD_CMDLINE_PARTS
\r
1887 mtd_device_register(sprd_mtd, partitions, num_partitions);
\r
1892 nand_release(sprd_mtd);
\r
1893 sprd_nand_dma_deinit(&g_dolphin);
\r
1895 sprd_dolphin_reg_and(DOLPHIN_AHB_BASE,~(BIT(17) | BIT(18) | BIT(19) | BIT(6)));
\r
1900 static int sprd_nand_remove(struct platform_device *pdev)
\r
1902 platform_set_drvdata(pdev, NULL);
\r
1903 nand_release(sprd_mtd);
\r
1904 sprd_nand_dma_deinit(&g_dolphin);
\r
1910 static int sprd_nand_suspend(struct platform_device *dev, pm_message_t pm)
\r
1916 static int sprd_nand_resume(struct platform_device *dev)
\r
1918 sprd_dolphin_reg_write(NFC_TIMING_REG, NFC_DEFAULT_TIMING);
\r
1919 sprd_dolphin_reg_write(NFC_TIMEOUT_REG, 0x80400000);
\r
1920 //close write protect
\r
1921 sprd_dolphin_nand_wp_en(&g_dolphin, 0);
\r
1925 #define sprd_nand_suspend NULL
\r
1926 #define sprd_nand_resume NULL
\r
1929 static struct platform_driver sprd_nand_driver = {
\r
1930 .probe = sprd_nand_probe,
\r
1931 .remove = sprd_nand_remove,
\r
1932 .suspend = sprd_nand_suspend,
\r
1933 .resume = sprd_nand_resume,
\r
1935 .name = "sprd-nand",
\r
1936 .owner = THIS_MODULE,
\r
1940 static int __init sprd_nand_init(void)
\r
1942 return platform_driver_register(&sprd_nand_driver);
\r
1945 static void __exit sprd_nand_exit(void)
\r
1947 platform_driver_unregister(&sprd_nand_driver);
\r
1950 module_init(sprd_nand_init);
\r
1951 module_exit(sprd_nand_exit);
\r
1953 MODULE_LICENSE("GPL");
\r
1954 MODULE_AUTHOR("giya.li@spreadtrum.com");
\r
1955 MODULE_DESCRIPTION("SPRD dolphin MTD NAND driver");
\r
1956 MODULE_ALIAS("platform:sprd-nand");
\r