3 #include <asm/arch/bits.h>
\r
4 #include <asm/arch/chip_drv_config_extern.h>
\r
5 #include <asm/arch/regs_nfc.h>
\r
6 #include <asm/arch/regs_cpc.h>
\r
7 #include <asm/arch/sdram_cfg.h>
\r
10 #include <linux/mtd/nand.h>
\r
12 #ifdef CONFIG_NAND_SPL
\r
13 #define printf(arg...) do{}while(0)
\r
16 #define NFC_ECC_EVENT 1
\r
17 #define NFC_DONE_EVENT 2
\r
18 #define NFC_TX_DMA_EVENT 4
\r
19 #define NFC_RX_DMA_EVENT 8
\r
20 #define NFC_ERR_EVENT 16
\r
21 #define NFC_TIMEOUT_EVENT 32
\r
22 #define NFC_TIMEOUT_VAL 0x1000000
\r
24 /* 2 bit correct, sc8810 support 1, 2, 4, 8, 12,14, 24 */
\r
25 #define CONFIG_SYS_NAND_ECC_MODE 2
\r
26 /* Number of ECC bytes per OOB - S3C6400 calculates 4 bytes ECC in 1-bit mode */
\r
27 #define CONFIG_SYS_NAND_ECCBYTES 4
\r
28 /* Size of the block protected by one OOB (Spare Area in Samsung terminology) */
\r
29 #define CONFIG_SYS_NAND_ECCSIZE 512
\r
31 struct sc8810_nand_timing_param {
\r
39 struct sc8810_nand_info {
\r
41 struct nand_chip *chip;
\r
42 unsigned int cfg0_setting;
\r
43 unsigned int ecc0_cfg_setting;
\r
44 unsigned int ecc1_cfg_setting;
\r
45 u8 asy_cle; //address cycles, can be set 3, 4, 5
\r
46 u8 advance;// advance property, can be set 0, 1
\r
47 u8 bus_width; //bus width, can be 0 or 1
\r
48 u8 ecc_mode; // ecc mode can be 1, 2, 4, 8, 12, 16,24
\r
49 u8 mc_ins_num; // micro instruction number
\r
50 u8 mc_addr_ins_num; //micro address instruction number
\r
51 u16 ecc_postion; //ecc postion
\r
52 u16 b_pointer; // nfc buffer pointer
\r
53 u16 addr_array[5];// the addrss of the flash to operation
\r
56 struct sc8810_nand_page_oob {
\r
59 unsigned char cyc_3;
\r
60 unsigned char cyc_4;
\r
61 unsigned char cyc_5;
\r
63 int oobsize; /* total oob size */
\r
64 int eccsize; /* per ??? bytes data for ecc calcuate once time */
\r
65 int eccbit; /* ecc level per eccsize */
\r
68 struct nand_spec_str{
\r
74 struct sc8810_nand_timing_param timing_cfg;
\r
77 static struct nand_spec_str *ptr_nand_spec = NULL;
\r
79 #define NF_MC_CMD_ID (0xFD)
\r
80 #define NF_MC_ADDR_ID (0xF1)
\r
81 #define NF_MC_WAIT_ID (0xF2)
\r
82 #define NF_MC_RWORD_ID (0xF3)
\r
83 #define NF_MC_RBLK_ID (0xF4)
\r
84 #define NF_MC_WWORD_ID (0xF6)
\r
85 #define NF_MC_WBLK_ID (0xF7)
\r
86 #define NF_MC_DEACTV_ID (0xF9)
\r
87 #define NF_MC_NOP_ID (0xFA)
\r
88 #define NF_PARA_20M 0x7ac05 //trwl = 0 trwh = 0
\r
89 #define NF_PARA_40M 0x7ac15 //trwl = 1 trwh = 0
\r
90 #define NF_PARA_53M 0x7ad26 //trwl = 2 trwh = 1
\r
91 #define NF_PARA_80M 0x7ad37 //trwl = 3 trwh = 1
\r
92 #define NF_PARA_DEFAULT 0x7ad77 //trwl = 7 trwh = 1
\r
94 #define REG_AHB_CTL0 (*((volatile unsigned int *)(AHB_CTL0)))
\r
95 #define REG_AHB_SOFT_RST (*((volatile unsigned int *)(AHB_SOFT_RST)))
\r
97 #define REG_GR_NFC_MEM_DLY (*((volatile unsigned int *)(GR_NFC_MEM_DLY)))
\r
99 static int mtderasesize = 0;
\r
100 static int mtdwritesize = 0;
\r
101 static int mtdoobsize = 0;
\r
103 static struct sc8810_nand_info g_info ={0};
\r
104 static nand_ecc_modes_t sprd_ecc_mode = NAND_ECC_NONE;
\r
105 static __attribute__((aligned(4))) unsigned char io_wr_port[NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZE];
\r
106 static char nand_id_table[5]={0};
\r
107 static int re_oob_layout=0;
\r
109 struct nand_ecclayout _nand_oob_64 = {
\r
112 40, 41, 42, 43, 44, 45, 46, 47,
\r
113 48, 49, 50, 51, 52, 53, 54, 55,
\r
114 56, 57, 58, 59, 60, 61, 62, 63},
\r
120 struct nand_ecclayout _nand_oob_64_4bit = {
\r
123 36, 37, 38, 39, 40, 41, 42, 43,
\r
124 44, 45, 46, 47, 48, 49, 50, 51,
\r
125 52, 53, 54, 55, 56, 57, 58, 59,
\r
133 static struct nand_ecclayout nand_oob_128 = {
\r
136 80, 81, 82, 83, 84, 85, 86, 87,
\r
137 88, 89, 90, 91, 92, 93, 94, 95,
\r
138 96, 97, 98, 99, 100, 101, 102, 103,
\r
139 104, 105, 106, 107, 108, 109, 110, 111,
\r
140 112, 113, 114, 115, 116, 117, 118, 119,
\r
141 120, 121, 122, 123, 124, 125, 126, 127},
\r
147 static struct nand_ecclayout _nand_oob_128 = {
\r
150 72, 73, 74, 75, 76, 77, 78, 79,
\r
151 80, 81, 82, 83, 84, 85, 86, 87,
\r
152 88, 89, 90, 91, 92, 93, 94, 95,
\r
153 96, 97, 98, 99, 100, 101, 102, 103,
\r
154 104, 105, 106, 107, 108, 109, 110, 111,
\r
155 112, 113, 114, 115, 116, 117, 118, 119,
\r
156 120, 121, 122, 123, 124, 125, 126, 127},
\r
162 static struct nand_ecclayout _nand_oob_224 = {
\r
165 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124,
\r
166 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137,
\r
167 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150,
\r
168 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163,
\r
169 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176,
\r
170 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189,
\r
171 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202,
\r
172 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215,
\r
173 216, 217, 218, 219, 220, 221, 222, 223},
\r
181 static struct nand_ecclayout _nand_oob_256 = {
\r
184 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156,
\r
185 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169,
\r
186 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182,
\r
187 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195,
\r
188 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208,
\r
189 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221,
\r
190 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234,
\r
191 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247,
\r
192 248, 249, 250, 251, 252, 253, 254, 255},
\r
199 struct sc8810_nand_timing_param nand_timing =
\r
210 /* only for special 4kpage or 8kpage nand flash, no 2kpage or normal 4kpage or normal 8kpage */
\r
211 static struct sc8810_nand_page_oob nand_config_table[] =
\r
213 {0xec, 0xbc, 0x00, 0x66, 0x56, 4096, 128, 512, 4},
\r
214 {0x2c, 0xb3, 0x90, 0x66, 0x64, 4096, 224, 512, 8},
\r
215 {0x2c, 0xbc, 0x90, 0x66, 0x54, 4096, 224, 512, 8},
\r
216 {0xec, 0xb3, 0x01, 0x66, 0x5a, 4096, 128, 512, 4},
\r
217 {0xec, 0xbc, 0x00, 0x6a, 0x56, 4096, 256, 512, 8},
\r
218 {0xad, 0xbc, 0x90, 0x55, 0x56, 2048, 64, 512, 4},
\r
219 {0x2c, 0xbc, 0x90, 0x55, 0x56, 2048, 64, 512, 4},
\r
220 {0x2c, 0xb3, 0xd1, 0x55, 0x56, 2048, 64, 512, 4},
\r
221 {0xc8, 0xbc, 0x90, 0x55, 0x54, 2048, 64, 512, 4}
\r
224 /* some nand id could not be calculated the pagesize by mtd, replace it with a known id which has the same format. */
\r
225 static unsigned char nand_id_replace_table[][10] =
\r
227 {0xad, 0xb3, 0x91, 0x11, 0x00, /*replace with*/ 0xec, 0xbc, 0x00, 0x66, 0x56},
\r
228 {0xad, 0xbc, 0x90, 0x11, 0x00, /*replace with*/ 0xec, 0xbc, 0x00, 0x66, 0x56}
\r
231 #if !defined(CONFIG_NAND_SPL)
\r
232 static const struct nand_spec_str nand_spec_table[] = {
\r
233 {0x2c, 0xb3, 0xd1, 0x55, 0x5a, {10, 10, 12, 10, 20, 50}},// MT29C8G96MAAFBACKD-5, MT29C4G96MAAHBACKD-5
\r
234 {0x2c, 0xba, 0x80, 0x55, 0x50, {10, 10, 12, 10, 20, 50}},// MT29C2G48MAKLCJA-5 IT
\r
235 {0x2c, 0xbc, 0x90, 0x55, 0x56, {10, 10, 12, 10, 20, 50}},// KTR0405AS-HHg1, KTR0403AS-HHg1, MT29C4G96MAZAPDJA-5 IT
\r
237 {0x98, 0xac, 0x90, 0x15, 0x76, {12, 10, 12, 10, 20, 50}},// TYBC0A111392KC
\r
238 {0x98, 0xbc, 0x90, 0x55, 0x76, {12, 15, 15, 10, 20, 50}},// TYBC0A111430KC, KSLCBBL1FB4G3A, KSLCBBL1FB2G3A
\r
239 {0x98, 0xbc, 0x90, 0x66, 0x76, {12, 15, 15, 10, 20, 50}},// KSLCCBL1FB2G3A_mvr400
\r
241 {0xad, 0xbc, 0x90, 0x11, 0x00, {25, 15, 25, 10, 20, 50}},// H9DA4VH4JJMMCR-4EMi, H9DA4VH2GJMMCR-4EM
\r
242 {0xad, 0xbc, 0x90, 0x55, 0x54, {25, 15, 25, 10, 20, 50}},//
\r
243 {0xad, 0xbc, 0x90, 0x55, 0x56, {25, 20, 30, 10, 20, 50}},//H9DA4GH2GJBMCR
\r
245 {0xec, 0xb3, 0x01, 0x66, 0x5a, {21, 10, 21, 10, 20, 50}},// KBY00U00VA-B450
\r
246 {0xec, 0xbc, 0x00, 0x55, 0x54, {21, 10, 21, 10, 20, 50}},// KA100O015M-AJTT
\r
247 {0xec, 0xbc, 0x00, 0x6a, 0x56, {21, 10, 21, 10, 20, 50}},// K524G2GACH-B050
\r
248 {0xec, 0xbc, 0x01, 0x55, 0x48, {21, 15, 21, 10, 20, 50}},// KBY00N00HM-A448
\r
250 {0, 0, 0, 0, 0, {0, 0, 0, 0, 0, 0}}
\r
254 void read_chip_id(void);
\r
255 static void nfc_reg_write(unsigned int addr, unsigned int value)
\r
257 writel(value, addr);
\r
259 static unsigned int nfc_reg_read(unsigned int addr)
\r
261 return readl(addr);
\r
264 static void nfc_mcr_inst_init(void)
\r
266 g_info.mc_ins_num = 0;
\r
267 g_info.b_pointer = 0;
\r
268 g_info.mc_addr_ins_num = 0;
\r
270 void nfc_mcr_inst_add(u32 ins, u32 mode)
\r
272 unsigned int offset;
\r
273 unsigned int high_flag;
\r
274 unsigned int reg_value;
\r
275 offset = g_info.mc_ins_num >> 1;
\r
276 high_flag = g_info.mc_ins_num & 0x1;
\r
277 if(NF_MC_ADDR_ID == mode)
\r
279 g_info.addr_array[g_info.mc_addr_ins_num ++] = ins;
\r
283 reg_value = nfc_reg_read(NFC_START_ADDR0 + (offset << 2));
\r
284 reg_value &= 0x0000ffff;
\r
285 reg_value |= ins << 24;
\r
286 reg_value |= mode << 16;
\r
290 reg_value = nfc_reg_read(NFC_START_ADDR0 + (offset << 2));
\r
291 reg_value &= 0xffff0000;
\r
292 reg_value |= ins << 8;
\r
293 reg_value |= mode;
\r
295 nfc_reg_write(NFC_START_ADDR0 + (offset << 2), reg_value);
\r
296 g_info.mc_ins_num ++;
\r
298 static unsigned int nfc_mcr_inst_exc(void)
\r
300 unsigned int value;
\r
301 value = nfc_reg_read(NFC_CFG0);
\r
302 if(g_info.chip->options & NAND_BUSWIDTH_16)
\r
304 value |= NFC_BUS_WIDTH_16;
\r
308 value &= ~NFC_BUS_WIDTH_16;
\r
310 value |= (1 << NFC_CMD_SET_OFFSET);
\r
311 nfc_reg_write(NFC_CFG0, value);
\r
312 value = NFC_CMD_VALID | ((unsigned int)NF_MC_NOP_ID) | ((g_info.mc_ins_num - 1) << 16);
\r
313 nfc_reg_write(NFC_CMD, value);
\r
317 static unsigned int nfc_mcr_inst_exc_for_id(void)
\r
319 unsigned int value;
\r
321 value = nfc_reg_read(NFC_CFG0);
\r
322 value &= ~NFC_BUS_WIDTH_16;
\r
323 value |= (1 << NFC_CMD_SET_OFFSET);
\r
325 nfc_reg_write(NFC_CFG0, value);
\r
326 value = NFC_CMD_VALID | ((unsigned int)NF_MC_NOP_ID) |((g_info.mc_ins_num - 1) << 16);
\r
327 nfc_reg_write(NFC_CMD, value);
\r
331 static void sc8810_nand_wp_en(int en)
\r
333 unsigned int value;
\r
336 value = nfc_reg_read(NFC_CFG0);
\r
337 value &= ~ NFC_WPN;
\r
338 nfc_reg_write(NFC_CFG0, value);
\r
342 value = nfc_reg_read(NFC_CFG0);
\r
344 nfc_reg_write(NFC_CFG0, value);
\r
347 static int sc8810_nfc_wait_command_finish(unsigned int flag)
\r
349 unsigned int event = 0;
\r
350 unsigned int value;
\r
351 unsigned int counter = 0;
\r
352 while(((event & flag) != flag) && (counter < NFC_TIMEOUT_VAL/*time out*/))
\r
354 value = nfc_reg_read(NFC_CLR_RAW);
\r
355 if(value & NFC_ECC_DONE_RAW)
\r
357 event |= NFC_ECC_EVENT;
\r
359 if(value & NFC_DONE_RAW)
\r
361 event |= NFC_DONE_EVENT;
\r
365 nfc_reg_write(NFC_CLR_RAW, 0xffff0000); //clear all interrupt status
\r
366 if(counter > NFC_TIMEOUT_VAL)
\r
369 for (i=0; i<40; i++)
\r
371 printk("\r\nnfc cmd reg addr:0x%x, value:0x%xx!\r\n", NFC_CMD+i);
\r
378 unsigned int ecc_mode_convert(u32 mode)
\r
410 unsigned int sc8810_ecc_encode(struct sc8810_ecc_param *param)
\r
413 reg = (param->m_size - 1);
\r
414 memcpy((void *)NFC_MBUF_ADDR, param->p_mbuf, param->m_size);
\r
415 nfc_reg_write(NFC_ECC_CFG1, reg);
\r
417 reg = (ecc_mode_convert(param->mode)) << NFC_ECC_MODE_OFFSET;
\r
418 reg |= (param->ecc_pos << NFC_ECC_SP_POS_OFFSET) | ((param->sp_size - 1) << NFC_ECC_SP_SIZE_OFFSET) | ((param->ecc_num -1)<< NFC_ECC_NUM_OFFSET);
\r
419 reg |= NFC_ECC_ACTIVE;
\r
420 nfc_reg_write(NFC_ECC_CFG0, reg);
\r
421 sc8810_nfc_wait_command_finish(NFC_ECC_EVENT);
\r
422 memcpy(param->p_sbuf, (u8 *)NFC_SBUF_ADDR,param->sp_size);
\r
425 static u32 sc8810_get_decode_sts(void)
\r
428 err = nfc_reg_read(NFC_ECC_STS0);
\r
436 static u32 sc8810_ecc_decode(struct sc8810_ecc_param *param)
\r
441 memcpy((void *)NFC_MBUF_ADDR, param->p_mbuf, param->m_size);
\r
442 memcpy((void *)NFC_SBUF_ADDR, param->p_sbuf, param->sp_size);
\r
443 reg = (param->m_size - 1);
\r
444 nfc_reg_write(NFC_ECC_CFG1, reg);
\r
446 reg = (ecc_mode_convert(param->mode)) << NFC_ECC_MODE_OFFSET;
\r
447 reg |= (param->ecc_pos << NFC_ECC_SP_POS_OFFSET) | ((param->sp_size - 1) << NFC_ECC_SP_SIZE_OFFSET) | ((param->ecc_num -1)<< NFC_ECC_NUM_OFFSET);
\r
448 reg |= NFC_ECC_DECODE;
\r
449 reg |= NFC_ECC_ACTIVE;
\r
450 nfc_reg_write(NFC_ECC_CFG0, reg);
\r
451 sc8810_nfc_wait_command_finish(NFC_ECC_EVENT);
\r
452 ret = sc8810_get_decode_sts();
\r
453 if (ret != 0 && ret != -1) {
\r
454 //printk(KERN_INFO "sc8810_ecc_decode sts = %x\n",ret);
\r
457 size = param->sp_size;
\r
461 if (param->p_sbuf[size] != 0xff)
\r
466 size = param->m_size;
\r
471 if (param->p_mbuf[size] != 0xff)
\r
481 if((ret != -1) && (ret != 0))
\r
483 memcpy(param->p_mbuf, (void *)NFC_MBUF_ADDR, param->m_size);
\r
484 memcpy(param->p_sbuf, (void *)NFC_SBUF_ADDR, param->sp_size);
\r
491 static void set_nfc_param(unsigned long nfc_clk)
\r
495 cycles = nand_timing.acs_time / (1000000000 / nfc_clk);
\r
496 value |= (cycles << NFC_ACS_OFFSET);
\r
498 cycles = nand_timing.rwh_time / (1000000000 / nfc_clk);
\r
499 value |= (cycles << NFC_RWH_OFFSET);
\r
501 cycles = nand_timing.rwl_time / (1000000000 / nfc_clk);
\r
502 value |= (cycles << NFC_RWL_OFFSET);
\r
504 cycles = nand_timing.acr_time / (1000000000 / nfc_clk);
\r
505 value |= (cycles << NFC_ACR_OFFSET);
\r
507 cycles = nand_timing.rr_time / (1000000000 / nfc_clk);
\r
508 value |= (cycles << NFC_RR_OFFSET);
\r
510 cycles = nand_timing.ceh_time / (1000000000 / nfc_clk);
\r
511 value |= (cycles << NFC_CEH_OFFSET);
\r
512 nfc_reg_write(NFC_TIMING, value);
\r
514 // local_irq_restore(flags);
\r
518 #if !defined(CONFIG_NAND_SPL)
\r
519 static struct nand_spec_str *get_nand_spec(u8 *nand_id)
\r
522 while(nand_spec_table[i].mid != 0){
\r
524 (nand_id[0] == nand_spec_table[i].mid)
\r
525 && (nand_id[1] == nand_spec_table[i].did)
\r
526 && (nand_id[2] == nand_spec_table[i].id3)
\r
527 && (nand_id[3] == nand_spec_table[i].id4)
\r
528 && (nand_id[4] == nand_spec_table[i].id5)
\r
530 return &nand_spec_table[i];
\r
534 return (struct nand_spec_str *)0;
\r
537 #define DELAY_NFC_TO_PAD 9
\r
538 #define DELAY_PAD_TO_NFC 6
\r
539 #define DELAY_RWL (DELAY_NFC_TO_PAD + DELAY_PAD_TO_NFC)
\r
541 static void set_nfc_timing(struct sc8810_nand_timing_param *nand_timing, u32 nfc_clk_MHz)
\r
545 cycles = nand_timing->acs_time * nfc_clk_MHz / 1000 + 1;
\r
546 value |= ((cycles & 0x1F) << NFC_ACS_OFFSET);
\r
548 cycles = nand_timing->rwh_time * nfc_clk_MHz / 1000 + 2;
\r
549 value |= ((cycles & 0x1F) << NFC_RWH_OFFSET);
\r
551 cycles = (nand_timing->rwl_time+DELAY_RWL) * nfc_clk_MHz / 1000 + 1;
\r
552 value |= ((cycles & 0x3F) << NFC_RWL_OFFSET);
\r
554 cycles = nand_timing->acr_time * nfc_clk_MHz / 1000 + 1;
\r
555 value |= ((cycles & 0x1F) << NFC_ACR_OFFSET);
\r
557 cycles = nand_timing->rr_time * nfc_clk_MHz / 1000 + 1;
\r
558 value |= ((cycles & 0x1F) << NFC_RR_OFFSET);
\r
560 cycles = nand_timing->ceh_time * nfc_clk_MHz / 1000 + 1;
\r
561 value |= ((cycles & 0x3F) << NFC_CEH_OFFSET);
\r
563 nfc_reg_write(NFC_TIMING, value);
\r
565 debug("set_nfc_timing NFC_TIMING: %x ", nfc_reg_read(NFC_TIMING));
\r
569 static void sc8810_nand_hw_init(void)
\r
573 REG_AHB_CTL0 |= BIT_8;//no BIT_9
\r
574 REG_AHB_SOFT_RST |= BIT_5;
\r
575 for(ik_cnt = 0; ik_cnt < 0xffff; ik_cnt++);
\r
576 REG_AHB_SOFT_RST &= ~BIT_5;
\r
578 sc8810_nand_wp_en(0);
\r
579 //nfc_reg_write(NFC_TIMING, ((6 << 0) | (6 << 5) | (10 << 10) | (6 << 16) | (5 << 21) | (5 << 26)));
\r
580 nfc_reg_write(NFC_TIMING, ((12 << 0) | (7 << 5) | (10 << 10) | (6 << 16) | (5 << 21) | (7 << 26)));
\r
581 nfc_reg_write(NFC_TIMING+0X4, 0xffffffff);//TIMEOUT
\r
582 //set_nfc_param(0);//53MHz
\r
584 static void sc8810_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
\r
586 memcpy(buf, g_info.b_pointer + io_wr_port,len);
\r
587 g_info.b_pointer += len;
\r
589 static void sc8810_nand_write_buf(struct mtd_info *mtd, const uint8_t *buf,
\r
592 memcpy(g_info.b_pointer + io_wr_port, (unsigned char*)buf,len);
\r
593 g_info.b_pointer += len;
\r
595 static u_char sc8810_nand_read_byte(struct mtd_info *mtd)
\r
598 ch = io_wr_port[g_info.b_pointer ++];
\r
601 static u16 sc8810_nand_read_word(struct mtd_info *mtd)
\r
604 ch = io_wr_port[g_info.b_pointer ++];
\r
605 ch |= io_wr_port[g_info.b_pointer ++] << 8;
\r
609 static void sc8810_nand_data_add(unsigned int bytes, unsigned int bus_width, unsigned int read)
\r
616 word = bytes & 0xff;
\r
621 word = (bytes & 0x1ff) >> 1;
\r
627 nfc_mcr_inst_add(blk - 1, NF_MC_RBLK_ID);
\r
631 nfc_mcr_inst_add(word - 1, NF_MC_RWORD_ID);
\r
638 nfc_mcr_inst_add(blk - 1, NF_MC_WBLK_ID);
\r
642 nfc_mcr_inst_add(word - 1, NF_MC_WWORD_ID);
\r
647 static void correct_invalid_id(unsigned char *buf)
\r
649 unsigned char id[5];
\r
651 int num = sizeof(nand_id_replace_table) / sizeof(nand_id_replace_table[0]);
\r
654 memcpy(id, (void *)NFC_MBUF_ADDR, 5);
\r
656 for (index=0; index<num; index++)
\r
658 if (id[0] == nand_id_replace_table[index][0] &&
\r
659 id[1] == nand_id_replace_table[index][1] &&
\r
660 id[2] == nand_id_replace_table[index][2] &&
\r
661 id[3] == nand_id_replace_table[index][3] &&
\r
662 id[4] == nand_id_replace_table[index][4])
\r
670 buf[0] = nand_id_replace_table[index][5];
\r
671 buf[1] = nand_id_replace_table[index][6];
\r
672 buf[2] = nand_id_replace_table[index][7];
\r
673 buf[3] = nand_id_replace_table[index][8];
\r
674 buf[4] = nand_id_replace_table[index][9];
\r
676 printf("nand id(%02x,%02x,%02x,%02x,%02x) is invalid, correct it by(%02x,%02x,%02x,%02x,%02x)\n",
\r
677 id[0],id[1],id[2],id[3],id[4], buf[0],buf[1],buf[2],buf[3],buf[4]);
\r
681 memcpy(buf, (void *)NFC_MBUF_ADDR, 5);
\r
685 static void sc8810_nand_hwcontrol(struct mtd_info *mtd, int cmd,
\r
688 struct nand_chip *chip = (struct nand_chip *)(mtd->priv);
\r
690 if (ctrl & NAND_CLE) {
\r
692 case NAND_CMD_RESET:
\r
693 nfc_mcr_inst_init();
\r
694 nfc_mcr_inst_add(cmd, NF_MC_CMD_ID);
\r
695 nfc_mcr_inst_exc();
\r
696 sc8810_nfc_wait_command_finish(NFC_DONE_EVENT);
\r
698 case NAND_CMD_STATUS:
\r
699 nfc_mcr_inst_init();
\r
700 //nfc_reg_write(NFC_CMD, 0x80000070);
\r
701 //sc8810_nfc_wait_command_finish(NFC_DONE_EVENT);
\r
702 //memcpy(io_wr_port, (void *)NFC_ID_STS, 1);
\r
703 nfc_mcr_inst_add(0x70, NF_MC_CMD_ID);
\r
704 nfc_mcr_inst_add(0x10, NF_MC_NOP_ID);//add nop clk for twrh timing param
\r
705 nfc_mcr_inst_add(3, NF_MC_RWORD_ID);
\r
706 nfc_mcr_inst_exc_for_id();
\r
707 sc8810_nfc_wait_command_finish(NFC_DONE_EVENT);
\r
708 memcpy(io_wr_port, (void *)NFC_MBUF_ADDR, 1);
\r
709 //printf("read status3 0x%x, 0x%x\r\n", io_wr_port[0], nfc_reg_read(NFC_MBUF_ADDR));
\r
711 case NAND_CMD_READID:
\r
712 nfc_mcr_inst_init();
\r
713 nfc_mcr_inst_add(cmd, NF_MC_CMD_ID);
\r
714 nfc_mcr_inst_add(0x00, NF_MC_ADDR_ID);
\r
715 nfc_mcr_inst_add(0x10, NF_MC_NOP_ID);//add nop clk for twrh timing param
\r
716 nfc_mcr_inst_add(7, NF_MC_RWORD_ID);
\r
717 nfc_mcr_inst_exc_for_id();
\r
718 sc8810_nfc_wait_command_finish(NFC_DONE_EVENT);
\r
719 //memcpy(io_wr_port, (void *)NFC_MBUF_ADDR, 5);
\r
720 correct_invalid_id(io_wr_port);
\r
722 case NAND_CMD_ERASE1:
\r
723 nfc_mcr_inst_init();
\r
724 nfc_mcr_inst_add(cmd, NF_MC_CMD_ID);
\r
726 case NAND_CMD_ERASE2:
\r
727 nfc_mcr_inst_add(cmd, NF_MC_CMD_ID);
\r
728 nfc_mcr_inst_add(0, NF_MC_WAIT_ID);
\r
729 nfc_mcr_inst_exc();
\r
730 sc8810_nfc_wait_command_finish(NFC_DONE_EVENT);
\r
732 case NAND_CMD_READ0:
\r
733 nfc_mcr_inst_init();
\r
734 nfc_mcr_inst_add(cmd, NF_MC_CMD_ID);
\r
736 case NAND_CMD_READSTART:
\r
737 nfc_mcr_inst_add(cmd, NF_MC_CMD_ID);
\r
738 nfc_mcr_inst_add(0x10, NF_MC_NOP_ID); /* add nop clk */
\r
739 nfc_mcr_inst_add(0, NF_MC_WAIT_ID);
\r
740 if((!g_info.addr_array[0]) && (!g_info.addr_array[1]) )//main part
\r
741 size = mtd->writesize +mtd->oobsize;
\r
743 size = mtd->oobsize;
\r
744 sc8810_nand_data_add(size, chip->options & NAND_BUSWIDTH_16, 1);
\r
745 nfc_mcr_inst_exc();
\r
746 sc8810_nfc_wait_command_finish(NFC_DONE_EVENT);
\r
747 memcpy(io_wr_port, (void *)NFC_MBUF_ADDR, size);
\r
749 case NAND_CMD_SEQIN:
\r
750 nfc_mcr_inst_init();
\r
751 nfc_mcr_inst_add(NAND_CMD_SEQIN, NF_MC_CMD_ID);
\r
753 case NAND_CMD_PAGEPROG:
\r
754 memcpy((void *)NFC_MBUF_ADDR, io_wr_port, g_info.b_pointer);
\r
755 nfc_mcr_inst_add(0x10, NF_MC_NOP_ID);//add nop clk for twrh timing param
\r
756 sc8810_nand_data_add(g_info.b_pointer, chip->options & NAND_BUSWIDTH_16, 0);
\r
757 nfc_mcr_inst_add(cmd, NF_MC_CMD_ID);
\r
758 nfc_mcr_inst_add(0, NF_MC_WAIT_ID);
\r
759 nfc_mcr_inst_exc();
\r
760 sc8810_nfc_wait_command_finish(NFC_DONE_EVENT);
\r
766 else if(ctrl & NAND_ALE) {
\r
767 nfc_mcr_inst_add(cmd & 0xff, NF_MC_ADDR_ID);
\r
770 static int sc8810_nand_devready(struct mtd_info *mtd)
\r
772 unsigned long value = 0;
\r
774 value = nfc_reg_read(NFC_CMD);
\r
775 if ((value & NFC_CMD_VALID) != 0)
\r
779 return 1; /* ready */
\r
783 static void sc8810_nand_select_chip(struct mtd_info *mtd, int chip)
\r
785 //struct nand_chip *this = mtd->priv;
\r
786 //struct sprd_nand_info *info = this->priv;
\r
787 #ifdef CONFIG_NAND_SPL
\r
788 mtd->erasesize = mtderasesize;
\r
789 mtd->writesize = mtdwritesize;
\r
790 mtd->oobsize = mtdoobsize;
\r
794 static int sc8810_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code)
\r
796 struct sc8810_ecc_param param;
\r
797 struct nand_chip *this = (struct nand_chip *)(mtd->priv);
\r
798 param.mode = g_info.ecc_mode;
\r
800 param.sp_size = this->ecc.bytes;
\r
802 param.m_size = this->ecc.size;
\r
803 param.p_mbuf = (u8 *)dat;
\r
804 param.p_sbuf = ecc_code;
\r
805 if (sprd_ecc_mode == NAND_ECC_WRITE) {
\r
806 sc8810_ecc_encode(¶m);
\r
807 sprd_ecc_mode = NAND_ECC_NONE;
\r
811 static void sc8810_nand_enable_hwecc(struct mtd_info *mtd, int mode)
\r
813 sprd_ecc_mode = mode;
\r
815 static int sc8810_nand_correct_data(struct mtd_info *mtd, uint8_t *dat,
\r
816 uint8_t *read_ecc, uint8_t *calc_ecc)
\r
818 struct sc8810_ecc_param param;
\r
819 struct nand_chip *this = (struct nand_chip *)(mtd->priv);
\r
821 param.mode = g_info.ecc_mode;
\r
823 param.sp_size = this->ecc.bytes;
\r
825 param.m_size = this->ecc.size;
\r
826 param.p_mbuf = dat;
\r
827 param.p_sbuf = read_ecc;
\r
828 ret = sc8810_ecc_decode(¶m);
\r
832 void nand_spl_hardware_config(struct nand_chip *this, u8 id[5])
\r
837 array = sizeof(nand_config_table) / sizeof(struct sc8810_nand_page_oob);
\r
838 for (index = 0; index < array; index ++) {
\r
839 if ((nand_config_table[index].m_c == id[0]) && (nand_config_table[index].d_c == id[1]) && (nand_config_table[index].cyc_3 == id[2]) && (nand_config_table[index].cyc_4 == id[3]) && (nand_config_table[index].cyc_5 == id[4]))
\r
843 if (index < array) {
\r
844 this->ecc.size = nand_config_table[index].eccsize;
\r
845 g_info.ecc_mode = nand_config_table[index].eccbit;
\r
846 this->eccbitmode = g_info.ecc_mode;
\r
847 /* 4 bit ecc, per 512 bytes can creat 13 * 4 = 52 bit , 52 / 8 = 7 bytes
\r
848 8 bit ecc, per 512 bytes can creat 13 * 8 = 104 bit , 104 / 8 = 13 bytes, junqiang say use 14 bytes */
\r
849 switch (g_info.ecc_mode) {
\r
851 /* 4 bit ecc, per 512 bytes can creat 13 * 4 = 52 bit , 52 / 8 = 7 bytes */
\r
852 this->ecc.bytes = 7;
\r
853 if(nand_config_table[index].oobsize == 64)
\r
854 this->ecc.layout = &_nand_oob_64_4bit;
\r
856 this->ecc.layout = &_nand_oob_128;
\r
859 /* 8 bit ecc, per 512 bytes can creat 13 * 8 = 104 bit , 104 / 8 = 14 bytes */
\r
860 this->ecc.bytes = 14;
\r
861 if (nand_config_table[index].oobsize == 224)
\r
862 this->ecc.layout = &_nand_oob_224;
\r
864 this->ecc.layout = &_nand_oob_256;
\r
865 mtdoobsize = nand_config_table[index].oobsize;
\r
871 #ifndef CONFIG_NAND_SPL
\r
872 void nand_hardware_config(struct mtd_info *mtd, struct nand_chip *this, unsigned char id[8])
\r
877 /*for (index = 0; index < 5; index ++)
\r
878 printk(" %02x ", id[index]);
\r
881 for (index = 0; index < 5; index ++)
\r
882 this->nandid[index] = id[index];
\r
884 array = sizeof(nand_config_table) / sizeof(nand_config_table[0]);
\r
885 for (index = 0; index < array; index ++) {
\r
886 if ((nand_config_table[index].m_c == id[0])
\r
887 && (nand_config_table[index].d_c == id[1])
\r
888 && (nand_config_table[index].cyc_3 == id[2])
\r
889 && (nand_config_table[index].cyc_4 == id[3])
\r
890 && (nand_config_table[index].cyc_5 == id[4])
\r
895 if (index < array) {
\r
896 this->ecc.size = nand_config_table[index].eccsize;
\r
897 g_info.ecc_mode = nand_config_table[index].eccbit;
\r
898 this->eccbitmode = g_info.ecc_mode;
\r
899 /* 4 bit ecc, per 512 bytes can creat 13 * 4 = 52 bit , 52 / 8 = 7 bytes
\r
900 8 bit ecc, per 512 bytes can creat 13 * 8 = 104 bit , 104 / 8 = 14 bytes */
\r
901 switch (g_info.ecc_mode) {
\r
903 /* 4 bit ecc, per 512 bytes can creat 14 * 4 = 56 bit , 56 / 8 = 7 bytes */
\r
904 this->ecc.bytes = 7;
\r
905 if(nand_config_table[index].oobsize == 64)
\r
906 this->ecc.layout = &_nand_oob_64_4bit;
\r
908 this->ecc.layout = &_nand_oob_128;
\r
911 /* 8 bit ecc, per 512 bytes can creat 13 * 8 = 104 bit , 104 / 8 = 14 bytes */
\r
912 this->ecc.bytes = 14;
\r
913 if (nand_config_table[index].oobsize == 224)
\r
914 this->ecc.layout = &_nand_oob_224;
\r
916 this->ecc.layout = &_nand_oob_256;
\r
917 mtd->oobsize = nand_config_table[index].oobsize;
\r
920 mtdoobsize = nand_config_table[index].oobsize;
\r
922 printk("The type of nand flash is 2KB page, so use default configuration!\n");
\r
926 int board_nand_init(struct nand_chip *this)
\r
930 g_info.chip = this;
\r
931 sc8810_nand_hw_init();
\r
933 this->IO_ADDR_R = this->IO_ADDR_W = (void __iomem *)NFC_MBUF_ADDR;
\r
934 this->cmd_ctrl = sc8810_nand_hwcontrol;
\r
935 this->dev_ready = sc8810_nand_devready;
\r
936 this->select_chip = sc8810_nand_select_chip;
\r
938 this->ecc.calculate = sc8810_nand_calculate_ecc;
\r
939 this->ecc.correct = sc8810_nand_correct_data;
\r
940 this->ecc.hwctl = sc8810_nand_enable_hwecc;
\r
941 this->ecc.mode = NAND_ECC_HW;
\r
942 this->read_buf = sc8810_nand_read_buf;
\r
943 this->write_buf = sc8810_nand_write_buf;
\r
944 this->read_byte = sc8810_nand_read_byte;
\r
945 this->read_word = sc8810_nand_read_word;
\r
948 /* The 4th id byte is the important one */
\r
950 #if !defined(CONFIG_NAND_SPL)
\r
951 ptr_nand_spec = get_nand_spec(io_wr_port);
\r
953 if (ptr_nand_spec != NULL)
\r
954 set_nfc_timing(&ptr_nand_spec->timing_cfg, 153);
\r
956 //nfc_reg_write(NFC_TIMING, ((6 << 0) | (6 << 5) | (10 << 10) | (6 << 16) | (5 << 21) | (5 << 26)));
\r
957 nfc_reg_write(NFC_TIMING, ((12 << 0) | (7 << 5) | (10 << 10) | (6 << 16) | (5 << 21) | (7 << 26)));
\r
960 extid = io_wr_port[3];
\r
961 /* Calc pagesize */
\r
962 mtdwritesize = 1024 << (extid & 0x3);
\r
965 mtdoobsize = (8 << (extid & 0x01)) * (mtdwritesize >> 9);
\r
967 /* Calc blocksize. Blocksize is multiples of 64KiB */
\r
968 mtderasesize = (64 * 1024) << (extid & 0x03);
\r
970 this->ecc.bytes = CONFIG_SYS_NAND_ECCBYTES;
\r
971 g_info.ecc_mode = CONFIG_SYS_NAND_ECC_MODE;
\r
972 this->eccbitmode = g_info.ecc_mode;
\r
973 this->ecc.size = CONFIG_SYS_NAND_ECCSIZE;
\r
974 #ifdef CONFIG_NAND_SPL
\r
975 if (mtdoobsize == 64)
\r
976 this->ecc.layout = &_nand_oob_64;
\r
977 else if (mtdoobsize == 128)
\r
978 this->ecc.layout = &nand_oob_128;
\r
979 nand_spl_hardware_config(this, io_wr_port);
\r
981 this->chip_delay = 20;
\r
982 this->priv = &g_info;
\r
983 this->options |= NAND_BUSWIDTH_16 | NAND_USE_FLASH_BBT;
\r
987 #ifndef CONFIG_NAND_SPL
\r
988 static unsigned long nfc_read_status(void)
\r
990 unsigned long status = 0;
\r
991 int i, cmd = NAND_CMD_STATUS;
\r
993 nfc_mcr_inst_init();
\r
994 nfc_reg_write(NFC_CMD, 0x80000070);
\r
995 sc8810_nfc_wait_command_finish(NFC_DONE_EVENT);
\r
996 memcpy(io_wr_port, (void *)NFC_ID_STS, 1);
\r
998 status = io_wr_port[0];
\r
1002 static int sprd_scan_one_block(int blk, int erasesize, int writesize)
\r
1005 int status = 1, ii;
\r
1007 int oobsize = mtdoobsize;
\r
1008 int column, page_addr;
\r
1010 page_addr = blk * (erasesize / writesize);
\r
1011 for (ii = 0; ii < 2; ii ++) {
\r
1012 nfc_mcr_inst_init();
\r
1013 cmd = NAND_CMD_READ0;
\r
1014 nfc_mcr_inst_add(cmd, NF_MC_CMD_ID);
\r
1016 column = writesize;
\r
1017 if (column != -1) {
\r
1018 /* Adjust columns for 16 bit buswidth */
\r
1020 nfc_mcr_inst_add(column & 0xff, NF_MC_ADDR_ID);
\r
1021 nfc_mcr_inst_add((column >> 8) & 0xff, NF_MC_ADDR_ID);
\r
1024 if (page_addr != -1) {
\r
1025 nfc_mcr_inst_add(page_addr & 0xff, NF_MC_ADDR_ID);
\r
1026 nfc_mcr_inst_add((page_addr >> 8) & 0xff, NF_MC_ADDR_ID);
\r
1027 /* One more address cycle for devices > 128MiB */
\r
1028 nfc_mcr_inst_add((page_addr >> 16) & 0xff, NF_MC_ADDR_ID);
\r
1031 cmd = NAND_CMD_READSTART;
\r
1032 nfc_mcr_inst_add(cmd, NF_MC_CMD_ID);
\r
1033 nfc_mcr_inst_add(0, NF_MC_WAIT_ID);
\r
1035 if((!g_info.addr_array[0]) && (!g_info.addr_array[1]) )
\r
1036 size = writesize + oobsize;//main part
\r
1039 sc8810_nand_data_add(size, 1, 1);
\r
1041 nfc_mcr_inst_exc();
\r
1042 sc8810_nfc_wait_command_finish(NFC_DONE_EVENT);
\r
1044 memcpy(io_wr_port, (void *)NFC_MBUF_ADDR, size);
\r
1046 for (i = 0; i < size; i++) {
\r
1047 /*if ((i % 16) == 0)
\r
1049 printf("io_wr_port[%d] = 0x%02x\n", i, io_wr_port[i]);
\r
1052 if ((io_wr_port[0] != 0xff) || (io_wr_port[1] != 0xff))
\r
1054 } //for (ii = 0; ii < 2; ii ++)
\r
1056 if ((io_wr_port[0] == 0xff) && (io_wr_port[1] == 0xff))
\r
1057 status = 0; //good block
\r
1059 status = 1; //bad block
\r
1064 static unsigned long nand_ctl_erase_block(int blk, int erasesize, int writesize)
\r
1069 nfc_mcr_inst_init();
\r
1070 cmd = NAND_CMD_ERASE1;
\r
1071 nfc_mcr_inst_add(cmd, NF_MC_CMD_ID);
\r
1072 page_addr = blk * (erasesize / writesize);
\r
1073 if (page_addr != -1) {
\r
1074 nfc_mcr_inst_add(page_addr & 0xff, NF_MC_ADDR_ID);
\r
1075 nfc_mcr_inst_add((page_addr >> 8) & 0xff, NF_MC_ADDR_ID);
\r
1076 /* One more address cycle for devices > 128MiB */
\r
1077 nfc_mcr_inst_add((page_addr >> 16) & 0xff, NF_MC_ADDR_ID);
\r
1080 cmd = NAND_CMD_ERASE2;
\r
1081 nfc_mcr_inst_add(cmd, NF_MC_CMD_ID);
\r
1082 nfc_mcr_inst_add(0, NF_MC_WAIT_ID);
\r
1083 nfc_mcr_inst_exc();
\r
1084 sc8810_nfc_wait_command_finish(NFC_DONE_EVENT);
\r
1086 status = nfc_read_status();
\r
1091 void read_chip_id(void)
\r
1093 int i, cmd = NAND_CMD_READID;
\r
1095 nfc_mcr_inst_init();
\r
1096 nfc_mcr_inst_add(cmd, NF_MC_CMD_ID);
\r
1097 nfc_mcr_inst_add(0x00, NF_MC_ADDR_ID);
\r
1098 nfc_mcr_inst_add(0x10, NF_MC_NOP_ID);//add nop clk for twrh timing param
\r
1099 nfc_mcr_inst_add(7, NF_MC_RWORD_ID);
\r
1100 nfc_mcr_inst_exc_for_id();
\r
1101 sc8810_nfc_wait_command_finish(NFC_DONE_EVENT);
\r
1102 //memcpy(io_wr_port, (void *)NFC_MBUF_ADDR, 5);
\r
1103 correct_invalid_id(io_wr_port);
\r
1104 #ifndef CONFIG_NAND_SPL
\r
1105 for (i = 0; i < 5; i++)
\r
1106 printf(" %02x ", io_wr_port[i]);
\r
1111 #ifndef CONFIG_NAND_SPL
\r
1112 void nand_scan_patition(int blocks, int erasesize, int writesize)
\r
1119 for (blk = 0; blk < blocks; blk ++) {
\r
1120 ret = sprd_scan_one_block(blk, erasesize, writesize);
\r
1122 printf("\n%d is bad, scrub to erase it, ", blk);
\r
1123 ret = nand_ctl_erase_block(blk, erasesize, writesize);
\r
1124 printf("0x%02x\n", ret);
\r
1126 ret = nand_ctl_erase_block(blk, erasesize, writesize);
\r
1127 printf("erasing block : %d %d % \r", blk, (blk * 100 ) / blocks);
\r
1131 int nand_scan_block(int block, int erasesize, int writesize){
\r
1133 ret = nand_ctl_erase_block(block, erasesize, writesize);
\r