1 /* linux/drivers/mtd/nand/tiger_nand.c
\r
3 * Copyright (c) 2012 Spreadtrun.
\r
5 * Spreadtrun NAND driver
\r
7 * This program is free software; you can redistribute it and/or modify
\r
8 * it under the terms of the GNU General Public License as published by
\r
9 * the Free Software Foundation; either version 2 of the License, or
\r
10 * (at your option) any later version.
\r
12 * This program is distributed in the hope that it will be useful,
\r
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
15 * GNU General Public License for more details.
\r
17 * You should have received a copy of the GNU General Public License
\r
18 * along with this program; if not, write to the Free Software
\r
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
\r
23 #include <asm/arch/bits.h>
\r
24 //#include <asm/arch/chip_drv_config_extern.h>
\r
25 #include <asm/arch/sprd_nfc_reg_v2.h>
\r
26 #include <asm/arch/regs_cpc.h>
\r
29 #include <linux/mtd/nand.h>
\r
30 #include <asm/arch/pin_reg_v3.h>
\r
32 #ifdef CONFIG_NAND_SPL
\r
33 #define printf(arg...) do{}while(0)
\r
36 #define printf(arg...) do{}while(0)
\r
39 /* 2 bit correct, sc8810 support 1, 2, 4, 8, 12,14, 24 */
\r
40 #define CONFIG_SYS_NAND_ECC_MODE 2
\r
41 /* Number of ECC bytes per OOB - S3C6400 calculates 4 bytes ECC in 1-bit mode */
\r
42 #define CONFIG_SYS_NAND_ECCBYTES 4
\r
43 /* Size of the block protected by one OOB (Spare Area in Samsung terminology) */
\r
44 #define CONFIG_SYS_NAND_ECCSIZE 512
\r
46 #define CONFIG_SYS_NAND_5_ADDR_CYCLE 5
\r
49 #define NFC_MC_ICMD_ID (0xCD)
\r
50 #define NFC_MC_ADDR_ID (0x0A)
\r
51 #define NFC_MC_WRB0_ID (0xB0)
\r
52 #define NFC_MC_WRB1_ID (0xB1)
\r
53 #define NFC_MC_MRDT_ID (0xD0)
\r
54 #define NFC_MC_MWDT_ID (0xD1)
\r
55 #define NFC_MC_SRDT_ID (0xD2)
\r
56 #define NFC_MC_SWDT_ID (0xD3)
\r
57 #define NFC_MC_IDST_ID (0xDD)
\r
58 #define NFC_MC_CSEN_ID (0xCE)
\r
59 #define NFC_MC_NOP_ID (0xF0)
\r
60 #define NFC_MC_DONE_ID (0xFF)
\r
61 #define NFC_MAX_CHIP 1
\r
62 #define NFC_TIMEOUT_VAL 0x1000000
\r
64 #define NAND_MC_CMD(x) (uint16_t)(((x & 0xff) << 8) | NFC_MC_ICMD_ID)
\r
65 #define NAND_MC_ADDR(x) (uint16_t)(((x & 0xff) << 8) | (NFC_MC_ADDR_ID << 4))
\r
66 #define NAND_MC_WRB0(x) (uint16_t)(NFC_MC_WRB0_ID)
\r
67 #define NAND_MC_MRDT (uint16_t)(NFC_MC_MRDT_ID)
\r
68 #define NAND_MC_MWDT (uint16_t)(NFC_MC_MWDT_ID)
\r
69 #define NAND_MC_SRDT (uint16_t)(NFC_MC_SRDT_ID)
\r
70 #define NAND_MC_SWDT (uint16_t)(NFC_MC_SWDT_ID)
\r
71 #define NAND_MC_IDST(x) (uint16_t)((NFC_MC_IDST_ID) | ((x -1) << 8))
\r
72 #define NAND_MC_NOP(x) (uint16_t)(((x & 0xff) << 8) | NFC_MC_NOP_ID)
\r
74 #define NAND_MC_BUFFER_SIZE (24)
\r
76 static int mtderasesize = 0;
\r
77 static int mtdwritesize = 0;
\r
78 static int mtdoobsize = 0;
\r
80 #define mtd_to_tiger(m) (&g_tiger)
\r
81 struct sprd_tiger_nand_param {
\r
85 uint8_t sct_pg; //sector per page
\r
86 uint8_t oob_size; /* oob size per sector*/
\r
87 uint8_t ecc_pos; /* oob size per sector*/
\r
88 uint8_t info_pos; /* oob size per sector*/
\r
89 uint8_t info_size; /* oob size per sector*/
\r
90 uint8_t eccbit; /* ecc level per eccsize */
\r
91 uint16_t eccsize; /*bytes per sector for ecc calcuate once time */
\r
92 uint8_t ace_ns; /* ALE, CLE end of delay timing, unit: ns */
\r
93 uint8_t rwl_ns; /* WE, RE, IO, pulse timing, unit: ns */
\r
94 uint8_t rwh_ns; /* WE, RE, IO, high hold timing, unit: ns */
\r
96 struct sprd_tiger_nand_info {
\r
97 struct mtd_info *mtd;
\r
98 struct nand_chip *nand;
\r
99 struct device *pdev;
\r
100 struct sprd_tiger_nand_param *param;
\r
101 uint32_t chip; //chip index
\r
102 uint32_t page; //page address
\r
103 uint16_t column; //column address
\r
105 uint16_t m_size; //main part size per sector
\r
106 uint16_t s_size; //oob size per sector
\r
107 uint8_t a_cycles;//address cycles, 3, 4, 5
\r
108 uint8_t sct_pg; //sector per page
\r
111 uint8_t ecc_mode;//0-1bit, 1-2bit, 2-4bit, 3-8bit,4-12bit,5-16bit,6-24bit
\r
112 uint8_t ecc_pos; // ecc postion
\r
113 uint8_t wp_en; //write protect enable
\r
114 uint16_t write_size;
\r
115 uint16_t page_per_bl;//page per block
\r
117 uint16_t _buf_tail;
\r
118 uint8_t ins_num;//instruction number
\r
119 uint32_t ins[NAND_MC_BUFFER_SIZE >> 1];
\r
121 static void sprd_tiger_nand_read_id(struct sprd_tiger_nand_info *tiger, uint32 *buf);
\r
122 static void sprd_tiger_nand_reset(struct sprd_tiger_nand_info *tiger);
\r
123 static int sprd_tiger_nand_wait_finish(struct sprd_tiger_nand_info *tiger);
\r
124 //gloable variable
\r
125 static struct nand_ecclayout sprd_tiger_nand_oob_default = {
\r
132 struct sprd_tiger_nand_info g_tiger = {0};
\r
133 //save the data read by read_byte and read_word api interface functon
\r
134 static __attribute__((aligned(4))) uint8_t s_oob_data[NAND_MAX_OOBSIZE];
\r
135 static uint32_t sprd_tiger_reg_read(uint32_t addr)
\r
137 return readl(addr);
\r
139 static void sprd_tiger_reg_write(uint32_t addr, uint32_t val)
\r
143 static void sprd_tiger_reg_or(uint32_t addr, uint32_t val)
\r
145 sprd_tiger_reg_write(addr, sprd_tiger_reg_read(addr) | val);
\r
147 static void sprd_tiger_reg_and(uint32_t addr, uint32_t mask)
\r
149 sprd_tiger_reg_write(addr, sprd_tiger_reg_read(addr) & mask);
\r
151 static void sprd_tiger_nand_int_clr(uint32_t bit_clear)
\r
153 sprd_tiger_reg_write(NFC_INT_REG, bit_clear);
\r
155 unsigned int ecc_mode_convert(uint32_t mode)
\r
187 /*spare info must be align to ecc pos, info_pos + info_size = ecc_pos,
\r
188 *the hardware must be config info_size and info_pos when ecc enable,and the ecc_info size can't be zero,
\r
189 *to simplify the nand_param_tb, the info is align with ecc and ecc at the last postion in one sector
\r
191 static struct sprd_tiger_nand_param sprd_tiger_nand_param_tb[] = {
\r
192 {{0xec, 0xbc, 0x00,0x55, 0x54}, 1, 5, 4, 16, 12, 11, 1, 2, 512, 5, 21, 10},
\r
193 {{0xec, 0xbc, 0x00,0x6A, 0x56}, 1, 5, 8, 16, 9, 8, 1, 4, 512, 5, 21, 10},
\r
194 {{0xad, 0xbc, 0x90,0x55, 0x54}, 1, 5, 4, 16, 12, 11, 1, 2, 512, 10, 25, 15},
\r
197 #ifndef CONFIG_NAND_SPL
\r
198 static void tiger_set_timing_config(struct sprd_tiger_nand_info * tiger, uint32_t nfc_clk_MHz){
\r
201 uint32_t reg_val, temp_val;
\r
202 struct sprd_tiger_nand_param * param;
\r
205 sprd_tiger_nand_read_id(tiger, (uint32 *)id_buf);
\r
207 /* get timing para */
\r
208 array = ARRAY_SIZE(sprd_tiger_nand_param_tb);
\r
209 for (index = 0; index < array; index ++) {
\r
210 param = sprd_tiger_nand_param_tb + index;
\r
211 if ((param->id[0] == id_buf[0])
\r
212 && (param->id[1] == id_buf[1])
\r
213 && (param->id[2] == id_buf[2])
\r
214 && (param->id[3] == id_buf[3])
\r
215 && (param->id[4] == id_buf[4]))
\r
219 if (index < array) {
\r
222 /* get acs value : 0 ns */
\r
223 reg_val |= ((2 & 0x1F) << NFC_ACS_OFFSET);
\r
225 /* get ace value + 6ns read delay time, and rwl added */
\r
226 temp_val = (param->ace_ns + 6)* nfc_clk_MHz / 1000;
\r
227 if (((param->ace_ns * nfc_clk_MHz) % 1000) != 0) {
\r
230 reg_val |= ((temp_val & 0x1F) << NFC_ACE_OFFSET);
\r
232 /* get rws value : 20 ns */
\r
233 temp_val = 20 * nfc_clk_MHz / 1000;
\r
234 if (((param->ace_ns * nfc_clk_MHz) % 1000) != 0) {
\r
237 reg_val |= ((temp_val & 0x3F) << NFC_RWS_OFFSET);
\r
239 /* get rws value : 0 ns */
\r
240 reg_val |= ((2 & 0x1F) << NFC_RWE_OFFSET);
\r
242 /* get rwh value */
\r
243 temp_val = (param->rwh_ns + 6) * nfc_clk_MHz / 1000;
\r
244 if (((param->ace_ns * nfc_clk_MHz) % 1000) != 0) {
\r
247 reg_val |= ((temp_val & 0x1F) << NFC_RWH_OFFSET);
\r
249 /* get rwl value, 6 is read delay time*/
\r
250 temp_val = (param->rwl_ns + 6) * nfc_clk_MHz / 1000;
\r
251 if (((param->ace_ns * nfc_clk_MHz) % 1000) != 0) {
\r
254 reg_val |= (temp_val & 0x3F);
\r
256 printf("nand timing val: 0x%x\n\r", reg_val);
\r
258 sprd_tiger_reg_write(NFC_TIMING_REG, reg_val);
\r
263 #ifdef CONFIG_NAND_SPL
\r
264 struct sprd_tiger_boot_header_info {
\r
265 uint32_t check_sum;
\r
266 uint32_t sct_size; //
\r
267 uint32_t acycle; // 3, 4, 5
\r
268 uint32_t bus_width; //0 ,1
\r
269 uint32_t spare_size; //spare part sise for one sector
\r
270 uint32_t ecc_mode; //0--1bit, 1--2bit,2--4bit,3--8bit,4--12bit, 5--16bit, 6--24bit
\r
271 uint32_t ecc_pos; // ecc postion at spare part
\r
272 uint32_t sct_per_page; //sector per page
\r
274 uint32_t info_size;
\r
275 uint32_t magic_num; //0xaa55a5a5
\r
276 uint32_t ecc_value[11];
\r
278 void boad_nand_param_init(struct sprd_tiger_nand_info *tiger, struct nand_chip *chip, uint8 *id)
\r
281 uint32_t writesize;
\r
283 uint32_t erasesize;
\r
286 /* The 4th id byte is the important one */
\r
288 writesize = 1024 << (extid & 0x3);
\r
291 oobsize = (8 << (extid & 0x01)) * (writesize >> 9);
\r
293 /* Calc blocksize. Blocksize is multiples of 64KiB */
\r
294 erasesize = (64 * 1024) << (extid & 0x03);
\r
296 /* Get buswidth information */
\r
297 busw = (extid & 0x01) ? NAND_BUSWIDTH_16 : 0;
\r
298 tiger->write_size = writesize;
\r
299 tiger->m_size =CONFIG_SYS_NAND_ECCSIZE;
\r
300 tiger->sct_pg = writesize / CONFIG_SYS_NAND_ECCSIZE;
\r
301 tiger->s_size = oobsize / tiger->sct_pg;
\r
302 tiger->ecc_mode = ecc_mode_convert(CONFIG_SYS_NAND_ECC_MODE);
\r
303 tiger->ecc_pos = tiger->s_size - ((14 * CONFIG_SYS_NAND_ECC_MODE + 7) / 8);
\r
304 tiger->info_pos = tiger->ecc_pos - 1;
\r
305 tiger->info_size = 1;
\r
306 tiger->page_per_bl = erasesize / tiger->write_size;
\r
307 tiger->a_cycles = CONFIG_SYS_NAND_5_ADDR_CYCLE;
\r
308 if(NAND_BUSWIDTH_16 == busw)
\r
310 chip->options |= NAND_BUSWIDTH_16;
\r
314 chip->options &= ~NAND_BUSWIDTH_16;
\r
318 * because the tiger firmware use the nand identify process
\r
319 * and the data at the header of nand_spl is the nand param used at nand read and write,
\r
320 * so in nand_spl, don't need read the id or use the onfi spec to calculate the nand param,
\r
321 * just use the param at the nand_spl header instead of
\r
323 void nand_hardware_config(struct mtd_info *mtd,struct nand_chip *chip)
\r
325 struct sprd_tiger_nand_info *tiger = mtd_to_tiger(mtd);
\r
326 struct sprd_tiger_boot_header_info *header;
\r
329 struct sprd_tiger_nand_param * param;
\r
331 sprd_tiger_nand_reset(tiger);
\r
332 sprd_tiger_nand_read_id(tiger, (uint32 *)s_oob_data);
\r
333 boad_nand_param_init(tiger, tiger->nand, s_oob_data);
\r
336 array = ARRAY_SIZE(sprd_tiger_nand_param_tb);
\r
337 for (index = 0; index < array; index ++) {
\r
338 param = sprd_tiger_nand_param_tb + index;
\r
339 if ((param->id[0] == id[0])
\r
340 && (param->id[1] == id[1])
\r
341 && (param->id[2] == id[2])
\r
342 && (param->id[3] == id[3])
\r
343 && (param->id[4] == id[4]))
\r
346 if (index < array) {
\r
347 tiger->ecc_mode = ecc_mode_convert(param->eccbit);
\r
348 tiger->m_size = param->eccsize;
\r
349 tiger->s_size = param->oob_size;
\r
350 tiger->a_cycles = param->a_cycles;
\r
351 tiger->sct_pg = param->sct_pg;
\r
352 tiger->info_pos = param->info_pos;
\r
353 tiger->info_size = param->info_size;
\r
354 tiger->write_size = tiger->m_size * tiger->sct_pg;
\r
355 tiger->ecc_pos = param->ecc_pos;
\r
356 if(param->bus_width)
\r
358 chip->options |= NAND_BUSWIDTH_16;
\r
362 chip->options &= ~NAND_BUSWIDTH_16;
\r
364 mtd->writesize = tiger->write_size;
\r
365 mtd->oobsize = tiger->s_size * tiger->sct_pg;
\r
368 mtd->writesize = tiger->write_size;
\r
369 mtd->oobsize = tiger->s_size * tiger->sct_pg;
\r
370 mtd->erasesize = tiger->page_per_bl * tiger->write_size;
\r
372 header = (struct sprd_tiger_boot_header_info *)0x400000000;
\r
373 tiger->ecc_mode = header->ecc_mode;
\r
374 tiger->m_size = header->sct_size;
\r
375 tiger->s_size = header->spare_size;
\r
376 tiger->a_cycles = header->acycle;
\r
377 tiger->sct_pg = header->sct_per_page;
\r
378 tiger->info_pos = header->info_pos;
\r
379 tiger->info_size = header->info_size;
\r
380 tiger->write_size = tiger->m_size * tiger->sct_pg;
\r
381 if(header->bus_width)
\r
383 chip->options |= NAND_BUSWIDTH_16;
\r
387 chip->options &= ~NAND_BUSWIDTH_16;
\r
389 mtd->writesize = tiger->write_size;
\r
390 mtd->oobsize = tiger->s_size * tiger->sct_pg;
\r
394 static void sprd_tiger_nand_ecc_layout_gen(struct sprd_tiger_nand_info *tiger, struct sprd_tiger_nand_param *param, struct nand_ecclayout *layout)
\r
399 uint32_t used_len ; //one sector ecc data size(byte)
\r
400 uint32_t eccbytes = 0; //one page ecc data size(byte)
\r
401 uint32_t oobfree_len = 0;
\r
402 used_len = (14 * param->eccbit + 7) / 8 + param->info_size;
\r
403 if(param->sct_pg > ARRAY_SIZE(layout->oobfree))
\r
407 for(sct = 0; sct < param->sct_pg; sct++)
\r
409 //offset = (oob_size * sct) + ecc_pos;
\r
410 //for(i = 0; i < ecc_len; i++)
\r
411 offset = (param->oob_size * sct) + param->info_pos;
\r
412 for(i = 0; i < used_len; i++)
\r
414 layout->eccpos[eccbytes++] = offset + i;
\r
416 layout->oobfree[sct].offset = param->oob_size * sct;
\r
417 layout->oobfree[sct].length = param->oob_size - used_len ;
\r
418 oobfree_len += param->oob_size - used_len;
\r
420 //for bad mark postion
\r
421 layout->oobfree[0].offset = 2;
\r
422 layout->oobfree[0].length = param->oob_size - used_len - 2;
\r
424 layout->eccbytes = used_len * param->sct_pg;
\r
426 void nand_hardware_config(struct mtd_info *mtd, struct nand_chip *chip, u8 id[5])
\r
430 struct sprd_tiger_nand_param * param;
\r
431 struct sprd_tiger_nand_info *tiger = mtd_to_tiger(mtd);
\r
433 array = ARRAY_SIZE(sprd_tiger_nand_param_tb);
\r
434 for (index = 0; index < array; index ++) {
\r
435 param = sprd_tiger_nand_param_tb + index;
\r
436 if ((param->id[0] == id[0])
\r
437 && (param->id[1] == id[1])
\r
438 && (param->id[2] == id[2])
\r
439 && (param->id[3] == id[3])
\r
440 && (param->id[4] == id[4]))
\r
443 if (index < array) {
\r
444 //save the param config
\r
445 tiger->ecc_mode = ecc_mode_convert(param->eccbit);
\r
446 tiger->m_size = param->eccsize;
\r
447 tiger->s_size = param->oob_size;
\r
448 tiger->a_cycles = param->a_cycles;
\r
449 tiger->sct_pg = param->sct_pg;
\r
450 tiger->info_pos = param->info_pos;
\r
451 tiger->info_size = param->info_size;
\r
452 tiger->write_size = tiger->m_size * tiger->sct_pg;
\r
453 tiger->ecc_pos = param->ecc_pos;
\r
454 chip->eccbitmode = param->eccbit;
\r
455 chip->ecc.bytes = (param->eccbit*14+7)/8;
\r
456 //tiger->bus_width = param->bus_width;
\r
457 if(param->bus_width)
\r
459 chip->options |= NAND_BUSWIDTH_16;
\r
463 chip->options &= ~NAND_BUSWIDTH_16;
\r
465 tiger->param = param;
\r
466 //update the mtd and nand default param after nand scan
\r
467 mtd->writesize = tiger->write_size;
\r
468 mtd->oobsize = tiger->s_size * tiger->sct_pg;
\r
469 /* Calculate the address shift from the page size */
\r
470 chip->page_shift = ffs(mtd->writesize) - 1;
\r
471 /* Convert chipsize to number of pages per chip -1. */
\r
472 chip->pagemask = (chip->chipsize >> chip->page_shift) - 1;
\r
473 sprd_tiger_nand_ecc_layout_gen(tiger, param, &sprd_tiger_nand_oob_default);
\r
474 chip->ecc.layout = &sprd_tiger_nand_oob_default;
\r
479 struct sprd_tiger_nand_param param1;
\r
481 //save the param config
\r
482 steps = mtd->writesize / CONFIG_SYS_NAND_ECCSIZE;
\r
483 tiger->ecc_mode = ecc_mode_convert(CONFIG_SYS_NAND_ECC_MODE);
\r
484 tiger->m_size = CONFIG_SYS_NAND_ECCSIZE;
\r
485 tiger->s_size = mtd->oobsize / steps;
\r
486 tiger->a_cycles = mtd->writesize / CONFIG_SYS_NAND_ECCSIZE;
\r
487 tiger->sct_pg = steps;
\r
488 tiger->info_pos = tiger->s_size - CONFIG_SYS_NAND_ECCBYTES - 1;
\r
489 tiger->info_size = 1;
\r
490 tiger->write_size = mtd->writesize;
\r
491 tiger->ecc_pos = tiger->s_size - CONFIG_SYS_NAND_ECCBYTES;
\r
492 param1.sct_pg = tiger->sct_pg;
\r
493 param1.info_pos = tiger->info_pos;
\r
494 param1.info_size = tiger->info_size;
\r
495 param1.oob_size = tiger->s_size;
\r
496 param1.eccbit = CONFIG_SYS_NAND_ECC_MODE;
\r
497 param1.eccsize = tiger->s_size;
\r
499 if(chip->chipsize > (128 << 20)) {
\r
500 tiger->a_cycles = 5;
\r
503 tiger->a_cycles = 4;
\r
505 sprd_tiger_nand_ecc_layout_gen(tiger, ¶m1, &sprd_tiger_nand_oob_default);
\r
506 chip->ecc.layout = &sprd_tiger_nand_oob_default;
\r
517 uint8_t dir; //if dir is 0, read dadta from NFC buffer, if 1, write data to NFC buffer
\r
520 } sprd_tiger_nand_data_param;
\r
521 static unsigned int sprd_tiger_data_trans(sprd_tiger_nand_data_param *param)
\r
526 cfg0 = NFC_ONLY_MST_MODE | MAIN_SPAR_APT | NFC_WPN;
\r
531 if(param->m_sct != 0)
\r
533 cfg0 |= (param->m_sct - 1) << SECTOR_NUM_OFFSET;
\r
535 cfg1 |= (param->m_size - 1);
\r
536 sprd_tiger_reg_write(NFC_MAIN_ADDR_REG, (uint32_t)param->m_buf);
\r
538 if(param->s_sct != 0)
\r
541 cfg1 |= (param->s_size - 1) << SPAR_SIZE_OFFSET;
\r
542 cfg2 |= (param->s_sct - 1) << SPAR_SECTOR_NUM_OFFSET;
\r
543 sprd_tiger_reg_write(NFC_SPAR_ADDR_REG, (uint32_t)param->s_buf);
\r
545 sprd_tiger_reg_write(NFC_CFG0_REG, cfg0);
\r
546 sprd_tiger_reg_write(NFC_CFG1_REG, cfg1);
\r
547 sprd_tiger_reg_write(NFC_CFG2_REG, cfg2);
\r
548 sprd_tiger_nand_int_clr(INT_STSMCH_CLR | INT_WP_CLR | INT_TO_CLR | INT_DONE_CLR);//clear all interrupt
\r
549 sprd_tiger_reg_write(NFC_START_REG, NFC_START);
\r
550 sprd_tiger_nand_wait_finish(&g_tiger);
\r
552 void sprd_ecc_ctrl(struct sprd_ecc_param *param, uint32_t dir)
\r
557 cfg0 = NFC_ONLY_ECC_MODE | MAIN_SPAR_APT;
\r
562 cfg1 |=(param->sinfo_size - 1) << SPAR_INFO_SIZE_OFFSET;
\r
563 cfg1 |=(param->sp_size - 1) << SPAR_SIZE_OFFSET;
\r
564 cfg1 |= (param->m_size - 1);
\r
566 cfg2 |= (param->sinfo_pos)<< SPAR_INFO_POS_OFFSET;
\r
567 cfg2 |= ecc_mode_convert(param->mode) << ECC_MODE_OFFSET;
\r
568 cfg2 |= param->ecc_pos;
\r
569 sprd_tiger_reg_write(NFC_CFG0_REG, cfg0);
\r
570 sprd_tiger_reg_write(NFC_CFG1_REG, cfg1);
\r
571 sprd_tiger_reg_write(NFC_CFG2_REG, cfg2);
\r
572 sprd_tiger_nand_int_clr(INT_STSMCH_CLR | INT_WP_CLR | INT_TO_CLR | INT_DONE_CLR);//clear all interrupt
\r
573 sprd_tiger_reg_write(NFC_START_REG, NFC_START);
\r
574 sprd_tiger_nand_wait_finish(&g_tiger);
\r
576 unsigned int sprd_ecc_encode(struct sprd_ecc_param *param)
\r
578 struct sprd_tiger_nand_info *tiger;
\r
579 sprd_tiger_nand_data_param d_param;
\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_tiger_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_tiger_data_trans(&d_param); //read the ecc value from nfc buffer
\r
607 //add one macro instruction to nand controller
\r
608 /*static */void sprd_tiger_nand_ins_init(struct sprd_tiger_nand_info *tiger)
\r
610 tiger->ins_num = 0;
\r
612 /*static */void sprd_tiger_nand_ins_add(uint16_t ins, struct sprd_tiger_nand_info *tiger)
\r
614 uint16_t *buf = (uint16_t *)tiger->ins;
\r
615 if(tiger->ins_num >= NAND_MC_BUFFER_SIZE)
\r
619 *(buf + tiger->ins_num) = ins;
\r
622 /*static */void sprd_tiger_nand_ins_exec(struct sprd_tiger_nand_info *tiger)
\r
627 for(i = 0; i < ((tiger->ins_num + 1) >> 1); i++)
\r
629 sprd_tiger_reg_write(NFC_INST0_REG + (i << 2), tiger->ins[i]);
\r
631 cfg0 = sprd_tiger_reg_read(NFC_CFG0_REG);
\r
648 sprd_tiger_nand_int_clr(INT_STSMCH_CLR | INT_WP_CLR | INT_TO_CLR | INT_DONE_CLR);//clear all interrupt
\r
649 sprd_tiger_reg_write(NFC_CFG0_REG, cfg0);
\r
650 sprd_tiger_reg_write(NFC_START_REG, NFC_START);
\r
652 static int sprd_tiger_nand_wait_finish(struct sprd_tiger_nand_info *tiger)
\r
654 unsigned int value;
\r
655 unsigned int counter = 0;
\r
656 while((counter < NFC_TIMEOUT_VAL/*time out*/))
\r
658 value = sprd_tiger_reg_read(NFC_INT_REG);
\r
659 if(value & INT_DONE_RAW)
\r
665 sprd_tiger_reg_write(NFC_INT_REG, 0xf00); //clear all interrupt status
\r
666 if(counter > NFC_TIMEOUT_VAL)
\r
673 static void sprd_tiger_nand_wp_en(struct sprd_tiger_nand_info *tiger, int en)
\r
684 static void sprd_tiger_select_chip(struct mtd_info *mtd, int chip)
\r
686 struct sprd_tiger_nand_info *tiger = mtd_to_tiger(mtd);
\r
687 if(chip < 0) { //for release caller
\r
690 //printf("sprd_tiger_select_chip, %x\r\n", chip);
\r
691 tiger->chip = chip;
\r
692 #ifdef CONFIG_NAND_SPL
\r
693 nand_hardware_config(mtd,tiger->nand);
\r
696 static void sprd_tiger_nand_read_status(struct sprd_tiger_nand_info *tiger)
\r
699 //printf("sprd_tiger_nand_read_status\r\n");
\r
700 sprd_tiger_nand_ins_init(tiger);
\r
701 sprd_tiger_nand_ins_add(NAND_MC_CMD(NAND_CMD_STATUS), tiger);
\r
702 sprd_tiger_nand_ins_add(NAND_MC_NOP(10), tiger); // added nop.
\r
703 sprd_tiger_nand_ins_add(NAND_MC_IDST(1), tiger);
\r
704 sprd_tiger_nand_ins_add(NFC_MC_DONE_ID, tiger);
\r
705 sprd_tiger_reg_write(NFC_CFG0_REG, NFC_ONLY_NAND_MODE);
\r
706 sprd_tiger_nand_ins_exec(tiger);
\r
707 sprd_tiger_nand_wait_finish(tiger);
\r
708 buf = (uint32_t *)s_oob_data;
\r
709 *buf = sprd_tiger_reg_read(NFC_STATUS0_REG);
\r
710 tiger->buf_head = 0;
\r
711 tiger->_buf_tail = 1;
\r
712 //printf("--sprd_tiger_nand_read_status--\r\n");
\r
714 static void sprd_tiger_nand_read_id(struct sprd_tiger_nand_info *tiger, uint32 *buf)
\r
716 //printf("sprd_tiger_nand_read_id\r\n");
\r
717 sprd_tiger_nand_ins_init(tiger);
\r
718 sprd_tiger_nand_ins_add(NAND_MC_CMD(NAND_CMD_READID), tiger);
\r
719 sprd_tiger_nand_ins_add(NAND_MC_ADDR(0), tiger);
\r
720 sprd_tiger_nand_ins_add(NAND_MC_NOP(10), tiger);
\r
721 sprd_tiger_nand_ins_add(NAND_MC_IDST(8), tiger);
\r
722 sprd_tiger_nand_ins_add(NFC_MC_DONE_ID, tiger);
\r
724 sprd_tiger_reg_write(NFC_CFG0_REG, NFC_ONLY_NAND_MODE);
\r
725 sprd_tiger_nand_ins_exec(tiger);
\r
726 sprd_tiger_nand_wait_finish(tiger);
\r
727 *buf = sprd_tiger_reg_read(NFC_STATUS0_REG);
\r
728 *(buf + 1) = sprd_tiger_reg_read(NFC_STATUS1_REG);
\r
729 tiger->buf_head = 0;
\r
730 tiger->_buf_tail = 8;
\r
731 //printf("--sprd_tiger_nand_read_id--\r\n");
\r
733 static void sprd_tiger_nand_reset(struct sprd_tiger_nand_info *tiger)
\r
735 //printf("sprd_tiger_nand_reset\r\n");
\r
736 sprd_tiger_nand_ins_init(tiger);
\r
737 sprd_tiger_nand_ins_add(NAND_MC_CMD(NAND_CMD_RESET), tiger);
\r
738 sprd_tiger_nand_ins_add(NFC_MC_WRB0_ID, tiger); //wait rb
\r
739 sprd_tiger_nand_ins_add(NFC_MC_DONE_ID, tiger);
\r
741 sprd_tiger_reg_write(NFC_CFG0_REG, NFC_ONLY_NAND_MODE);
\r
742 sprd_tiger_nand_ins_exec(tiger);
\r
743 sprd_tiger_nand_wait_finish(tiger);
\r
744 //printf("--sprd_tiger_nand_reset--\r\n");
\r
746 static u32 sprd_tiger_get_decode_sts(u32 index)
\r
751 reg_addr = NFC_STATUS0_REG + (index & 0xfffffffc);
\r
752 shift = (index & 0x3) >> 3;
\r
753 err = sprd_tiger_reg_read(reg_addr);
\r
755 if((err & ECC_ALL_FF))
\r
761 err &= ERR_ERR_NUM0_MASK;
\r
766 static int sprd_tiger_nand_read_lp(struct mtd_info *mtd,uint8_t *mbuf, uint8_t *sbuf,uint32_t raw)
\r
768 struct sprd_tiger_nand_info *tiger = mtd_to_tiger(mtd);
\r
769 struct nand_chip *chip = tiger->nand;
\r
771 uint32_t page_addr;
\r
777 page_addr = tiger->page;
\r
780 column = mtd->writesize;
\r
786 if(chip->options & NAND_BUSWIDTH_16)
\r
790 //printf("sprd_tiger_nand_read_lp,page_addr = %x,column = %x\r\n",page_addr, column);
\r
791 sprd_tiger_nand_ins_init(tiger);
\r
792 sprd_tiger_nand_ins_add(NAND_MC_CMD(NAND_CMD_READ0), tiger);
\r
793 sprd_tiger_nand_ins_add(NAND_MC_ADDR(column & 0xff), tiger);
\r
795 sprd_tiger_nand_ins_add(NAND_MC_ADDR(column & 0xff), tiger);
\r
797 sprd_tiger_nand_ins_add(NAND_MC_ADDR(page_addr & 0xff), tiger);
\r
799 sprd_tiger_nand_ins_add(NAND_MC_ADDR(page_addr & 0xff), tiger);
\r
801 if (5 == tiger->a_cycles)// five address cycles
\r
804 sprd_tiger_nand_ins_add(NAND_MC_ADDR(page_addr & 0xff), tiger);
\r
806 sprd_tiger_nand_ins_add(NAND_MC_CMD(NAND_CMD_READSTART), tiger);
\r
808 sprd_tiger_nand_ins_add(NFC_MC_WRB0_ID, tiger); //wait rb
\r
811 sprd_tiger_nand_ins_add(NAND_MC_SRDT, tiger);
\r
812 sprd_tiger_nand_ins_add(NAND_MC_NOP(10), tiger);
\r
813 //switch to main part
\r
814 sprd_tiger_nand_ins_add(NAND_MC_CMD(NAND_CMD_RNDOUT), tiger);
\r
815 sprd_tiger_nand_ins_add(NAND_MC_ADDR(0), tiger);
\r
816 sprd_tiger_nand_ins_add(NAND_MC_ADDR(0), tiger);
\r
817 sprd_tiger_nand_ins_add(NAND_MC_CMD(NAND_CMD_RNDOUTSTART), tiger);
\r
818 sprd_tiger_nand_ins_add(NAND_MC_NOP(10), tiger);
\r
819 sprd_tiger_nand_ins_add(NAND_MC_MRDT, tiger);
\r
823 sprd_tiger_nand_ins_add(NAND_MC_MRDT, tiger);
\r
825 sprd_tiger_nand_ins_add(NFC_MC_DONE_ID, tiger);
\r
826 //config registers
\r
827 cfg0 = NFC_AUTO_MODE | MAIN_SPAR_APT | ((tiger->sct_pg - 1)<< SECTOR_NUM_OFFSET);
\r
828 if((!raw) && mbuf && sbuf)
\r
830 cfg0 |= ECC_EN | DETECT_ALL_FF;
\r
832 if(chip->options & NAND_BUSWIDTH_16)
\r
836 cfg1 = (tiger->info_size - 1) << SPAR_INFO_SIZE_OFFSET;
\r
837 cfg2 = (tiger->ecc_mode << ECC_MODE_OFFSET) | (tiger->info_pos << SPAR_INFO_POS_OFFSET) | ((tiger->sct_pg - 1) << SPAR_SECTOR_NUM_OFFSET) | tiger->ecc_pos;
\r
839 #ifndef CONFIG_NAND_SPL
\r
842 Dcache_CleanRegion((unsigned int)mbuf, tiger->m_size*tiger->sct_pg);
\r
843 Dcache_InvalRegion((unsigned int)mbuf, tiger->m_size*tiger->sct_pg);
\r
848 Dcache_CleanRegion((unsigned int)sbuf, tiger->s_size*tiger->sct_pg);
\r
849 Dcache_InvalRegion((unsigned int)sbuf, tiger->s_size*tiger->sct_pg);
\r
854 cfg1 |= (tiger->m_size - 1) | ((tiger->s_size - 1)<< SPAR_SIZE_OFFSET);
\r
855 sprd_tiger_reg_write(NFC_MAIN_ADDR_REG, (uint32_t)mbuf);
\r
856 sprd_tiger_reg_write(NFC_SPAR_ADDR_REG, (uint32_t)sbuf);
\r
857 cfg0 |= MAIN_USE | SPAR_USE;
\r
863 cfg1 |= (tiger->m_size - 1);
\r
864 sprd_tiger_reg_write(NFC_MAIN_ADDR_REG, (uint32_t)mbuf);
\r
868 cfg1 |= (tiger->s_size - 1);
\r
869 sprd_tiger_reg_write(NFC_MAIN_ADDR_REG, (uint32_t)sbuf);
\r
873 sprd_tiger_reg_write(NFC_CFG0_REG, cfg0);
\r
874 sprd_tiger_reg_write(NFC_CFG1_REG, cfg1);
\r
875 sprd_tiger_reg_write(NFC_CFG2_REG, cfg2);
\r
877 sprd_tiger_nand_ins_exec(tiger);
\r
878 sprd_tiger_nand_wait_finish(tiger);
\r
880 for(i = 0; i < tiger->sct_pg; i++) {
\r
881 err = sprd_tiger_get_decode_sts(i);
\r
882 if(err == ERR_ERR_NUM0_MASK) {
\r
883 mtd->ecc_stats.failed++;
\r
886 mtd->ecc_stats.corrected += err;
\r
893 static int sprd_tiger_nand_read_sp(struct mtd_info *mtd,uint8_t *mbuf, uint8_t *sbuf,uint32_t raw)
\r
897 #ifndef CONFIG_NAND_SPL
\r
898 static int sprd_tiger_nand_write_lp(struct mtd_info *mtd,const uint8_t *mbuf, uint8_t *sbuf,uint32_t raw)
\r
900 struct sprd_tiger_nand_info *tiger = mtd_to_tiger(mtd);
\r
901 struct nand_chip *chip = tiger->nand;
\r
903 uint32_t page_addr;
\r
907 page_addr = tiger->page;
\r
912 column = mtd->writesize;
\r
914 if(chip->options & NAND_BUSWIDTH_16)
\r
918 sprd_tiger_nand_ins_init(tiger);
\r
919 sprd_tiger_nand_ins_add(NAND_MC_CMD(NAND_CMD_SEQIN), tiger);
\r
920 sprd_tiger_nand_ins_add(NAND_MC_ADDR(column & 0xff), tiger);
\r
922 sprd_tiger_nand_ins_add(NAND_MC_ADDR(column & 0xff), tiger);
\r
923 sprd_tiger_nand_ins_add(NAND_MC_ADDR(page_addr & 0xff), tiger);
\r
925 sprd_tiger_nand_ins_add(NAND_MC_ADDR(page_addr & 0xff), tiger);
\r
927 if (5 == tiger->a_cycles)// five address cycles
\r
930 sprd_tiger_nand_ins_add(NAND_MC_ADDR(page_addr & 0xff), tiger);
\r
932 sprd_tiger_nand_ins_add(NAND_MC_NOP(10), tiger);
\r
934 sprd_tiger_nand_ins_add(NAND_MC_MWDT, tiger);
\r
937 sprd_tiger_nand_ins_add(NAND_MC_SWDT, tiger);
\r
939 sprd_tiger_nand_ins_add(NAND_MC_CMD(NAND_CMD_PAGEPROG), tiger);
\r
940 sprd_tiger_nand_ins_add(NFC_MC_WRB0_ID, tiger); //wait rb
\r
942 sprd_tiger_nand_ins_add(NFC_MC_DONE_ID, tiger);
\r
943 //config registers
\r
944 cfg0 = NFC_AUTO_MODE | NFC_RW | NFC_WPN | MAIN_SPAR_APT | ((tiger->sct_pg - 1)<< SECTOR_NUM_OFFSET);
\r
945 if((!raw) && mbuf && sbuf)
\r
949 if(chip->options & NAND_BUSWIDTH_16)
\r
953 cfg1 = ((tiger->info_size - 1) << SPAR_INFO_SIZE_OFFSET);
\r
954 cfg2 = (tiger->ecc_mode << ECC_MODE_OFFSET) | (tiger->info_pos << SPAR_INFO_POS_OFFSET) | ((tiger->sct_pg - 1) << SPAR_SECTOR_NUM_OFFSET) | tiger->ecc_pos;
\r
958 Dcache_CleanRegion((unsigned int)mbuf, tiger->m_size*tiger->sct_pg);
\r
959 Dcache_InvalRegion((unsigned int)mbuf, tiger->m_size*tiger->sct_pg);
\r
964 Dcache_CleanRegion((unsigned int)sbuf, tiger->s_size*tiger->sct_pg);
\r
965 Dcache_InvalRegion((unsigned int)sbuf, tiger->s_size*tiger->sct_pg);
\r
969 cfg0 |= MAIN_USE | SPAR_USE;
\r
970 cfg1 = (tiger->m_size - 1) | ((tiger->s_size - 1) << SPAR_SIZE_OFFSET);
\r
971 sprd_tiger_reg_write(NFC_MAIN_ADDR_REG, (uint32_t)mbuf);
\r
972 sprd_tiger_reg_write(NFC_SPAR_ADDR_REG, (uint32_t)sbuf);
\r
979 cfg1 |= tiger->m_size - 1;
\r
980 sprd_tiger_reg_write(NFC_MAIN_ADDR_REG, (uint32_t)mbuf);
\r
984 cfg1 |= tiger->s_size - 1;
\r
985 sprd_tiger_reg_write(NFC_MAIN_ADDR_REG, (uint32_t)sbuf);
\r
988 sprd_tiger_reg_write(NFC_CFG0_REG, cfg0);
\r
989 sprd_tiger_reg_write(NFC_CFG1_REG, cfg1);
\r
990 sprd_tiger_reg_write(NFC_CFG2_REG, cfg2);
\r
991 sprd_tiger_nand_ins_exec(tiger);
\r
992 sprd_tiger_nand_wait_finish(tiger);
\r
995 static int sprd_tiger_nand_write_sp(struct mtd_info *mtd,const uint8_t *mbuf, uint8_t *sbuf,uint32_t raw)
\r
1000 static void sprd_tiger_erase(struct mtd_info *mtd, int page_addr)
\r
1002 struct sprd_tiger_nand_info *tiger = mtd_to_tiger(mtd);
\r
1003 uint32_t cfg0 = 0;
\r
1004 //printf("sprd_tiger_erase, %x\r\n", page_addr);
\r
1005 sprd_tiger_nand_ins_init(tiger);
\r
1006 sprd_tiger_nand_ins_add(NAND_MC_CMD(NAND_CMD_ERASE1), tiger);
\r
1007 sprd_tiger_nand_ins_add(NAND_MC_ADDR(page_addr & 0xff), tiger);
\r
1009 sprd_tiger_nand_ins_add(NAND_MC_ADDR(page_addr & 0xff), tiger);
\r
1010 if((5 == tiger->a_cycles) || ((4 == tiger->a_cycles) && (512 == tiger->write_size)))
\r
1013 sprd_tiger_nand_ins_add(NAND_MC_ADDR(page_addr & 0xff), tiger);
\r
1015 sprd_tiger_nand_ins_add(NAND_MC_CMD(NAND_CMD_ERASE2), tiger);
\r
1016 sprd_tiger_nand_ins_add(NFC_MC_WRB0_ID, tiger); //wait rb
\r
1018 sprd_tiger_nand_ins_add(NFC_MC_DONE_ID, tiger);
\r
1019 cfg0 = NFC_WPN | NFC_ONLY_NAND_MODE;
\r
1020 sprd_tiger_reg_write(NFC_CFG0_REG, cfg0);
\r
1021 sprd_tiger_nand_ins_exec(tiger);
\r
1022 sprd_tiger_nand_wait_finish(tiger);
\r
1023 //printf("--sprd_tiger_erase--\r\n");
\r
1025 static uint8_t sprd_tiger_read_byte(struct mtd_info *mtd)
\r
1027 uint8_t ch = 0xff;
\r
1028 struct sprd_tiger_nand_info *tiger = mtd_to_tiger(mtd);
\r
1029 if(tiger->buf_head < tiger->_buf_tail)
\r
1031 ch = s_oob_data[tiger->buf_head ++];
\r
1035 static uint16_t sprd_tiger_read_word(struct mtd_info *mtd)
\r
1037 uint16_t data = 0xffff;
\r
1038 struct sprd_tiger_nand_info *tiger = mtd_to_tiger(mtd);
\r
1039 if(tiger->buf_head < (tiger->_buf_tail - 1))
\r
1041 data = s_oob_data[tiger->buf_head ++];
\r
1042 data |= ((uint16_t)s_oob_data[tiger->buf_head ++]) << 8;
\r
1046 static int sprd_tiger_waitfunc(struct mtd_info *mtd, struct nand_chip *chip)
\r
1050 static int sprd_tiger_ecc_calculate(struct mtd_info *mtd, const uint8_t *data,
\r
1051 uint8_t *ecc_code)
\r
1055 static int sprd_tiger_ecc_correct(struct mtd_info *mtd, uint8_t *data,
\r
1056 uint8_t *read_ecc, uint8_t *calc_ecc)
\r
1060 static int sprd_tiger_read_page(struct mtd_info *mtd, struct nand_chip *chip,
\r
1061 uint8_t *buf, int page)
\r
1063 struct sprd_tiger_nand_info *tiger = mtd_to_tiger(mtd);
\r
1064 tiger->page = page;
\r
1065 if(512 == mtd->writesize)
\r
1067 sprd_tiger_nand_read_sp(mtd, buf, chip->oob_poi, 0);
\r
1071 sprd_tiger_nand_read_lp(mtd, buf, chip->oob_poi, 0);
\r
1075 static int sprd_tiger_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
\r
1076 uint8_t *buf, int page)
\r
1078 struct sprd_tiger_nand_info *tiger = mtd_to_tiger(mtd);
\r
1079 tiger->page = page;
\r
1080 if(512 == mtd->writesize)
\r
1082 sprd_tiger_nand_read_sp(mtd, buf, chip->oob_poi, 1);
\r
1086 sprd_tiger_nand_read_lp(mtd, buf, chip->oob_poi, 1);
\r
1090 static int sprd_tiger_read_oob(struct mtd_info *mtd, struct nand_chip *chip,
\r
1091 int page, int sndcmd)
\r
1093 struct sprd_tiger_nand_info *tiger = mtd_to_tiger(mtd);
\r
1094 tiger->page = page;
\r
1095 if(512 == mtd->writesize)
\r
1097 sprd_tiger_nand_read_sp(mtd, 0, chip->oob_poi, 1);
\r
1101 sprd_tiger_nand_read_lp(mtd, 0, chip->oob_poi, 1);
\r
1105 #ifndef CONFIG_NAND_SPL
\r
1106 static void sprd_tiger_write_page(struct mtd_info *mtd, struct nand_chip *chip,
\r
1107 const uint8_t *buf)
\r
1109 if(512 == mtd->writesize)
\r
1111 sprd_tiger_nand_write_sp(mtd, buf, chip->oob_poi, 0);
\r
1115 sprd_tiger_nand_write_lp(mtd, buf, chip->oob_poi, 0);
\r
1119 static void sprd_tiger_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
\r
1120 const uint8_t *buf)
\r
1122 if(512 == mtd->writesize)
\r
1124 sprd_tiger_nand_write_sp(mtd, buf, chip->oob_poi, 1);
\r
1128 sprd_tiger_nand_write_lp(mtd, buf, chip->oob_poi, 1);
\r
1131 static int sprd_tiger_write_oob(struct mtd_info *mtd, struct nand_chip *chip,
\r
1134 struct sprd_tiger_nand_info *tiger = mtd_to_tiger(mtd);
\r
1135 tiger->page = page;
\r
1136 if(512 == mtd->writesize)
\r
1138 sprd_tiger_nand_write_sp(mtd, 0, chip->oob_poi, 1);
\r
1142 sprd_tiger_nand_write_lp(mtd, 0, chip->oob_poi, 1);
\r
1148 * nand_block_bad - [DEFAULT] Read bad block marker from the chip
\r
1149 * @mtd: MTD device structure
\r
1150 * @ofs: offset from device start
\r
1151 * @getchip: 0, if the chip is already selected
\r
1153 * Check, if the block is bad.
\r
1155 static int sprd_tiger_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)
\r
1157 int page, chipnr, res = 0;
\r
1158 struct sprd_tiger_nand_info *tiger = mtd_to_tiger(mtd);
\r
1159 struct nand_chip *chip = mtd->priv;
\r
1163 page = (int)(ofs >> chip->page_shift) & chip->pagemask;
\r
1166 chipnr = (int)(ofs >> chip->chip_shift);
\r
1167 /* Select the NAND device */
\r
1168 chip->select_chip(mtd, chipnr);
\r
1171 chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page);
\r
1172 if(512 == tiger->write_size) {
\r
1173 sprd_tiger_nand_read_sp(mtd, 0, s_oob_data, 1);
\r
1176 sprd_tiger_nand_read_lp(mtd, 0, s_oob_data, 1);
\r
1178 tiger->buf_head = 0;
\r
1179 tiger->_buf_tail = mtd->oobsize;
\r
1180 buf = (uint16_t *)(s_oob_data + chip->badblockpos);
\r
1182 if (chip->options & NAND_BUSWIDTH_16) {
\r
1184 if ((bad & 0xFF) != 0xff) {
\r
1188 bad = *(buf) & 0xff;
\r
1195 static void sprd_tiger_nand_cmdfunc(struct mtd_info *mtd, unsigned int command,
\r
1196 int column, int page_addr)
\r
1198 struct sprd_tiger_nand_info *tiger = mtd_to_tiger(mtd);
\r
1199 /* Emulate NAND_CMD_READOOB */
\r
1200 if (command == NAND_CMD_READOOB) {
\r
1201 column += mtd->writesize;
\r
1202 command = NAND_CMD_READ0;
\r
1205 * program and erase have their own busy handlers
\r
1206 * status, sequential in, and deplete1 need no delay
\r
1208 switch (command) {
\r
1209 case NAND_CMD_STATUS:
\r
1210 sprd_tiger_nand_read_status(tiger);
\r
1212 case NAND_CMD_READID:
\r
1213 sprd_tiger_nand_read_id(tiger, (uint32 *)s_oob_data);
\r
1215 case NAND_CMD_RESET:
\r
1216 sprd_tiger_nand_reset(tiger);
\r
1218 case NAND_CMD_ERASE1:
\r
1219 sprd_tiger_erase(mtd, page_addr);
\r
1221 case NAND_CMD_READ0:
\r
1222 case NAND_CMD_SEQIN:
\r
1223 tiger->column = column;
\r
1224 tiger->page = page_addr;
\r
1229 static void sprd_tiger_nand_hwecc_ctl(struct mtd_info *mtd, int mode)
\r
1231 return; //do nothing
\r
1233 static void sprd_tiger_nand_hw_init(struct sprd_tiger_nand_info *tiger)
\r
1238 sprd_tiger_reg_or(0x20900200, BIT_8);
\r
1240 val = sprd_tiger_reg_read(0x20900210);
\r
1241 sprd_tiger_reg_or(0x20900210, BIT_5);
\r
1242 for(i = 0; i < 0xffff; i++);
\r
1243 sprd_tiger_reg_and(0x20900210, ~BIT_5);
\r
1244 val |= (4) | (4 << NFC_RWH_OFFSET) | (3 << NFC_RWE_OFFSET) | (3 << NFC_RWS_OFFSET) | (3 << NFC_ACE_OFFSET) | (3 << NFC_ACS_OFFSET);
\r
1246 sprd_tiger_reg_write(NFC_TIMING_REG, val);
\r
1247 sprd_tiger_reg_write(NFC_TIMEOUT_REG, 0x80400000);
\r
1248 sprd_tiger_reg_or(PIN_NFRB_REG, BIT_7); //set PIN_NFRB pull up
\r
1249 sprd_tiger_reg_or(PIN_CTL2_REG, BIT_17); //set PIN_NFRB pull up resiter 4.7k
\r
1250 for (i=PIN_NFWPN_REG; i<=PIN_NFD15_REG; i+=4)
\r
1252 sprd_tiger_reg_or( i, BIT_9);
\r
1253 sprd_tiger_reg_and(i, ~(BIT_8|BIT_10|BIT_6));
\r
1255 //close write protect
\r
1256 sprd_tiger_nand_wp_en(tiger, 0);
\r
1258 int board_nand_init(struct nand_chip *chip)
\r
1260 printf("board_nand_init\r\n");
\r
1261 sprd_tiger_nand_hw_init(&g_tiger);
\r
1262 chip->select_chip = sprd_tiger_select_chip;
\r
1263 chip->cmdfunc = sprd_tiger_nand_cmdfunc;
\r
1264 chip->read_byte = sprd_tiger_read_byte;
\r
1265 chip->read_word = sprd_tiger_read_word;
\r
1266 chip->waitfunc = sprd_tiger_waitfunc;
\r
1267 chip->ecc.mode = NAND_ECC_HW;
\r
1268 chip->ecc.calculate = sprd_tiger_ecc_calculate;
\r
1269 chip->ecc.hwctl = sprd_tiger_nand_hwecc_ctl;
\r
1271 chip->ecc.correct = sprd_tiger_ecc_correct;
\r
1272 chip->ecc.read_page = sprd_tiger_read_page;
\r
1273 chip->ecc.read_page_raw = sprd_tiger_read_page_raw;
\r
1274 #ifndef CONFIG_NAND_SPL
\r
1275 chip->ecc.write_page = sprd_tiger_write_page;
\r
1276 chip->ecc.write_page_raw = sprd_tiger_write_page_raw;
\r
1277 chip->ecc.write_oob = sprd_tiger_write_oob;
\r
1279 chip->ecc.read_oob = sprd_tiger_read_oob;
\r
1280 chip->erase_cmd = sprd_tiger_erase;
\r
1282 chip->ecc.bytes = CONFIG_SYS_NAND_ECCBYTES;
\r
1283 g_tiger.ecc_mode = CONFIG_SYS_NAND_ECC_MODE;
\r
1284 g_tiger.nand = chip;
\r
1285 #ifndef CONFIG_NAND_SPL
\r
1286 tiger_set_timing_config(&g_tiger, 153);
\r
1288 chip->eccbitmode = g_tiger.ecc_mode;
\r
1289 chip->ecc.size = CONFIG_SYS_NAND_ECCSIZE;
\r
1291 chip->options |= NAND_BUSWIDTH_16;
\r
1296 static unsigned long nfc_read_status(void)
\r
1298 unsigned long status = 0;
\r
1300 sprd_tiger_nand_read_status(&g_tiger);
\r
1301 status = s_oob_data[0];
\r
1306 #ifndef CONFIG_NAND_SPL
\r
1307 static int sprd_scan_one_block(int blk, int erasesize, int writesize)
\r
1310 int status = 1, ii;
\r
1312 int oobsize = mtdoobsize;
\r
1313 int column, page_addr;
\r
1315 page_addr = blk * (erasesize / writesize);
\r
1316 for (ii = 0; ii < 2; ii ++) {
\r
1317 printf("please debug here : %s %d\n", __FUNCTION__, __LINE__);
\r
1318 sprd_tiger_nand_ins_init(&g_tiger);
\r
1319 sprd_tiger_nand_ins_add(NAND_MC_CMD(NAND_CMD_READ0), &g_tiger);
\r
1320 sprd_tiger_nand_ins_add(NAND_MC_CMD(NAND_CMD_READSTART), &g_tiger);
\r
1321 if ((s_oob_data[0] != 0xff) || (s_oob_data[1] != 0xff))
\r
1323 } //for (ii = 0; ii < 2; ii ++)
\r
1325 if ((s_oob_data[0] == 0xff) && (s_oob_data[1] == 0xff))
\r
1326 status = 0; //good block
\r
1328 status = 1; //bad block
\r
1333 static unsigned long nand_ctl_erase_block(int blk, int erasesize, int writesize)
\r
1338 page_addr = blk * (erasesize / writesize);
\r
1339 sprd_tiger_erase(&g_tiger, page_addr);
\r
1340 status = nfc_read_status();
\r
1345 void nand_scan_patition(int blocks, int erasesize, int writesize)
\r
1352 for (blk = 0; blk < blocks; blk ++) {
\r
1353 ret = sprd_scan_one_block(blk, erasesize, writesize);
\r
1355 printf("\n%d is bad, scrub to erase it, ", blk);
\r
1356 ret = nand_ctl_erase_block(blk, erasesize, writesize);
\r
1357 printf("0x%02x\n", ret);
\r
1359 ret = nand_ctl_erase_block(blk, erasesize, writesize);
\r
1360 printf("erasing block : %d %d % \r", blk, (blk * 100 ) / blocks);
\r
1364 int nand_scan_block(int block, int erasesize, int writesize){
\r
1366 ret = nand_ctl_erase_block(block, erasesize, writesize);
\r