blob: cae4834eb3314cf24a0b2ce91eb27e3d4e7a927b [file] [log] [blame]
Dima Zavin03cf4312009-01-23 16:38:30 -08001/*
2 * Copyright (c) 2008, Google Inc.
3 * All rights reserved.
Shashank Mittal246f8d02011-01-21 17:12:27 -08004 * Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
Dima Zavin03cf4312009-01-23 16:38:30 -08005 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in
Shashank Mittalc20b5a12009-11-18 19:35:30 -080013 * the documentation and/or other materials provided with the
Dima Zavin03cf4312009-01-23 16:38:30 -080014 * distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
19 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
20 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
22 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
Shashank Mittalc20b5a12009-11-18 19:35:30 -080023 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
Dima Zavin03cf4312009-01-23 16:38:30 -080024 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
26 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#include <debug.h>
31#include <reg.h>
32#include <stdlib.h>
33#include <string.h>
34#include <dev/flash.h>
35#include <lib/ptable.h>
Ajay Dudani168f6cb2009-12-07 19:04:02 -080036#include <nand.h>
Dima Zavin03cf4312009-01-23 16:38:30 -080037
38#include "dmov.h"
Dima Zavin03cf4312009-01-23 16:38:30 -080039
40#define VERBOSE 0
Dima Zavin5582c7d2009-03-03 15:17:59 -080041#define VERIFY_WRITE 0
42
43static void *flash_spare;
44static void *flash_data;
Chandan Uddaraju14e57eb2010-06-28 12:11:06 -070045void platform_config_interleaved_mode_gpios(void);
Dima Zavin03cf4312009-01-23 16:38:30 -080046
47typedef struct dmov_ch dmov_ch;
Shashank Mittalc20b5a12009-11-18 19:35:30 -080048struct dmov_ch
Dima Zavin03cf4312009-01-23 16:38:30 -080049{
50 volatile unsigned cmd;
51 volatile unsigned result;
52 volatile unsigned status;
53 volatile unsigned config;
54};
55
56static void dmov_prep_ch(dmov_ch *ch, unsigned id)
57{
58 ch->cmd = DMOV_CMD_PTR(id);
59 ch->result = DMOV_RSLT(id);
60 ch->status = DMOV_STATUS(id);
61 ch->config = DMOV_CONFIG(id);
62}
63
64#define SRC_CRCI_NAND_CMD CMD_SRC_CRCI(DMOV_NAND_CRCI_CMD)
65#define DST_CRCI_NAND_CMD CMD_DST_CRCI(DMOV_NAND_CRCI_CMD)
66#define SRC_CRCI_NAND_DATA CMD_SRC_CRCI(DMOV_NAND_CRCI_DATA)
67#define DST_CRCI_NAND_DATA CMD_DST_CRCI(DMOV_NAND_CRCI_DATA)
68
Channagoud Kadabi404a7062011-03-21 19:27:50 +053069#define CFG0_RAW 0xA80420C0
70#define CFG1_RAW 0x5045D
71
72#define CFG0_RAW_BCHECC 0xA80428C0
Shashank Mittalad3d05c2009-11-19 15:53:57 -080073
Dima Zavin03cf4312009-01-23 16:38:30 -080074static unsigned CFG0, CFG1;
Shashank Mittal8e49dec2010-03-01 15:19:04 -080075static unsigned CFG0_M, CFG1_M;
76static unsigned CFG0_A, CFG1_A;
Channagoud Kadabi404a7062011-03-21 19:27:50 +053077static unsigned NAND_CFG0_RAW, NAND_CFG1_RAW;
78static unsigned ECC_BCH_CFG;
79
80static uint32_t enable_bch_ecc;
Dima Zavin03cf4312009-01-23 16:38:30 -080081
82#define CFG1_WIDE_FLASH (1U << 1)
83
84#define paddr(n) ((unsigned) (n))
85
86static int dmov_exec_cmdptr(unsigned id, unsigned *ptr)
87{
88 dmov_ch ch;
89 unsigned n;
90
91 dmov_prep_ch(&ch, id);
92
93 writel(DMOV_CMD_PTR_LIST | DMOV_CMD_ADDR(paddr(ptr)), ch.cmd);
94
95 while(!(readl(ch.status) & DMOV_STATUS_RSLT_VALID)) ;
96
97 n = readl(ch.status);
98 while(DMOV_STATUS_RSLT_COUNT(n)) {
99 n = readl(ch.result);
100 if(n != 0x80000002) {
101 dprintf(CRITICAL, "ERROR: result: %x\n", n);
102 dprintf(CRITICAL, "ERROR: flush: %x %x %x %x\n",
103 readl(DMOV_FLUSH0(DMOV_NAND_CHAN)),
104 readl(DMOV_FLUSH1(DMOV_NAND_CHAN)),
105 readl(DMOV_FLUSH2(DMOV_NAND_CHAN)),
106 readl(DMOV_FLUSH3(DMOV_NAND_CHAN)));
107 }
108 n = readl(ch.status);
109 }
110
111 return 0;
112}
113
Dima Zavinca337f52009-03-02 16:41:44 -0800114static struct flash_info flash_info;
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800115static unsigned flash_pagesize = 0;
Chandan Uddaraju14e57eb2010-06-28 12:11:06 -0700116static int interleaved_mode = 0;
Channagoud Kadabibeb17d52011-03-25 17:14:00 +0530117static unsigned num_pages_per_blk = 0;
118static unsigned num_pages_per_blk_mask = 0;
Dima Zavin03cf4312009-01-23 16:38:30 -0800119
Shashank Mittal83d16d02009-11-18 16:54:42 -0800120struct flash_identification {
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800121 unsigned flash_id;
122 unsigned mask;
123 unsigned density;
124 unsigned widebus;
125 unsigned pagesize;
126 unsigned blksize;
127 unsigned oobsize;
128 unsigned onenand;
Shashank Mittal83d16d02009-11-18 16:54:42 -0800129};
130
131static struct flash_identification supported_flash[] =
132{
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800133 /* Flash ID ID Mask Density(MB) Wid Pgsz Blksz oobsz onenand Manuf */
134 {0x00000000, 0xFFFFFFFF, 0, 0, 0, 0, 0, 0}, /*ONFI*/
135 {0x1500aaec, 0xFF00FFFF, (256<<20), 0, 2048, (2048<<6), 64, 0}, /*Sams*/
136 {0x5500baec, 0xFF00FFFF, (256<<20), 1, 2048, (2048<<6), 64, 0}, /*Sams*/
137 {0x1500aa98, 0xFFFFFFFF, (256<<20), 0, 2048, (2048<<6), 64, 0}, /*Tosh*/
138 {0x5500ba98, 0xFFFFFFFF, (256<<20), 1, 2048, (2048<<6), 64, 0}, /*Tosh*/
Ajay Dudani86e1b422009-12-04 20:49:50 -0800139 {0xd580b12c, 0xFFFFFFFF, (256<<20), 1, 2048, (2048<<6), 64, 0}, /*Micr*/
Chandan Uddaraju40605112010-08-09 14:25:08 -0700140 {0x5590bc2c, 0xFFFFFFFF, (512<<20), 1, 2048, (2048<<6), 64, 0}, /*Micr*/
Chandan Uddaraju0ec234c2009-11-24 22:34:50 -0800141 {0x1580aa2c, 0xFFFFFFFF, (256<<20), 0, 2048, (2048<<6), 64, 0}, /*Micr*/
Shashank Mittalab958e52010-12-03 17:57:22 -0800142 {0x1590aa2c, 0xFFFFFFFF, (256<<20), 0, 2048, (2048<<6), 64, 0}, /*Micr*/
Ajay Dudani513fb742010-05-24 20:39:26 -0700143 {0x1590ac2c, 0xFFFFFFFF, (512<<20), 0, 2048, (2048<<6), 64, 0}, /*Micr*/
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800144 {0x5580baad, 0xFFFFFFFF, (256<<20), 1, 2048, (2048<<6), 64, 0}, /*Hynx*/
145 {0x5510baad, 0xFFFFFFFF, (256<<20), 1, 2048, (2048<<6), 64, 0}, /*Hynx*/
146 {0x004000ec, 0xFFFFFFFF, (256<<20), 0, 2048, (2048<<6), 64, 1}, /*Sams*/
147 {0x005c00ec, 0xFFFFFFFF, (256<<20), 0, 2048, (2048<<6), 64, 1}, /*Sams*/
148 {0x005800ec, 0xFFFFFFFF, (256<<20), 0, 2048, (2048<<6), 64, 1}, /*Sams*/
Chandan Uddaraju40605112010-08-09 14:25:08 -0700149 {0x6600bcec, 0xFF00FFFF, (512<<20), 1, 4096, (4096<<6), 128, 0}, /*Sams*/
Shashank Mittal246f8d02011-01-21 17:12:27 -0800150 {0x5580ba2c, 0xFFFFFFFF, (256<<20), 1, 2048, (2048<<6), 64, 0}, /*Hynx*/
Shashank Mittalef325412011-04-01 13:48:26 -0700151 {0x6600b3ec, 0xFFFFFFFF, (512<<20), 1, 4096, (4096<<6), 128, 0}, /*Sams*/
Channagoud Kadabi404a7062011-03-21 19:27:50 +0530152 {0x2600482c, 0xFF00FFFF, (2048<<20), 0, 4096, (4096<<7), 224 , 0}, /*8bit bch ecc*/
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800153 /* Note: Width flag is 0 for 8 bit Flash and 1 for 16 bit flash */
154 /* Note: Onenand flag is 0 for NAND Flash and 1 for OneNAND flash */
155 /* Note: The First row will be filled at runtime during ONFI probe */
Shashank Mittal83d16d02009-11-18 16:54:42 -0800156};
Shashank Mittal8e49dec2010-03-01 15:19:04 -0800157static void set_nand_configuration(char type)
158{
159 if(type == TYPE_MODEM_PARTITION)
160 {
161 CFG0 = CFG0_M;
162 CFG1 = CFG1_M;
163 }
164 else
165 {
166 CFG0 = CFG0_A;
167 CFG1 = CFG1_A;
168 }
169}
Shashank Mittal83d16d02009-11-18 16:54:42 -0800170
171static void flash_nand_read_id(dmov_s *cmdlist, unsigned *ptrlist)
Dima Zavin03cf4312009-01-23 16:38:30 -0800172{
173 dmov_s *cmd = cmdlist;
174 unsigned *ptr = ptrlist;
175 unsigned *data = ptrlist + 4;
176
177 data[0] = 0 | 4;
178 data[1] = NAND_CMD_FETCH_ID;
179 data[2] = 1;
180 data[3] = 0;
181 data[4] = 0;
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800182 data[5] = 0;
183 data[6] = 0;
184 data[7] = 0xAAD40000; /* Default value for CFG0 for reading device id */
Dima Zavin03cf4312009-01-23 16:38:30 -0800185
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800186 /* Read NAND device id */
Dima Zavin03cf4312009-01-23 16:38:30 -0800187 cmd[0].cmd = 0 | CMD_OCB;
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800188 cmd[0].src = paddr(&data[7]);
189 cmd[0].dst = NAND_DEV0_CFG0;
Dima Zavin03cf4312009-01-23 16:38:30 -0800190 cmd[0].len = 4;
191
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800192 cmd[1].cmd = 0;
193 cmd[1].src = NAND_SFLASHC_BURST_CFG;
194 cmd[1].dst = paddr(&data[5]);
Dima Zavin03cf4312009-01-23 16:38:30 -0800195 cmd[1].len = 4;
196
197 cmd[2].cmd = 0;
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800198 cmd[2].src = paddr(&data[6]);
199 cmd[2].dst = NAND_SFLASHC_BURST_CFG;
Dima Zavin03cf4312009-01-23 16:38:30 -0800200 cmd[2].len = 4;
201
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800202 cmd[3].cmd = 0;
203 cmd[3].src = paddr(&data[0]);
204 cmd[3].dst = NAND_FLASH_CHIP_SELECT;
Dima Zavin03cf4312009-01-23 16:38:30 -0800205 cmd[3].len = 4;
206
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800207 cmd[4].cmd = DST_CRCI_NAND_CMD;
208 cmd[4].src = paddr(&data[1]);
209 cmd[4].dst = NAND_FLASH_CMD;
Dima Zavin03cf4312009-01-23 16:38:30 -0800210 cmd[4].len = 4;
211
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800212 cmd[5].cmd = 0;
213 cmd[5].src = paddr(&data[2]);
214 cmd[5].dst = NAND_EXEC_CMD;
215 cmd[5].len = 4;
216
217 cmd[6].cmd = SRC_CRCI_NAND_DATA;
218 cmd[6].src = NAND_FLASH_STATUS;
219 cmd[6].dst = paddr(&data[3]);
220 cmd[6].len = 4;
221
222 cmd[7].cmd = 0;
223 cmd[7].src = NAND_READ_ID;
224 cmd[7].dst = paddr(&data[4]);
225 cmd[7].len = 4;
226
227 cmd[8].cmd = CMD_OCU | CMD_LC;
228 cmd[8].src = paddr(&data[5]);
229 cmd[8].dst = NAND_SFLASHC_BURST_CFG;
230 cmd[8].len = 4;
231
Dima Zavin03cf4312009-01-23 16:38:30 -0800232 ptr[0] = (paddr(cmd) >> 3) | CMD_PTR_LP;
233
234 dmov_exec_cmdptr(DMOV_NAND_CHAN, ptr);
235
236#if VERBOSE
237 dprintf(INFO, "status: %x\n", data[3]);
238#endif
Dima Zavin03cf4312009-01-23 16:38:30 -0800239
Shashank Mittal83d16d02009-11-18 16:54:42 -0800240 flash_info.id = data[4];
Dima Zavinca337f52009-03-02 16:41:44 -0800241 flash_info.vendor = data[4] & 0xff;
242 flash_info.device = (data[4] >> 8) & 0xff;
Shashank Mittal83d16d02009-11-18 16:54:42 -0800243 return;
244}
Dima Zavinca337f52009-03-02 16:41:44 -0800245
Shashank Mittalad3d05c2009-11-19 15:53:57 -0800246static int flash_nand_block_isbad(dmov_s *cmdlist, unsigned *ptrlist,
247 unsigned page)
248{
249 dmov_s *cmd = cmdlist;
250 unsigned *ptr = ptrlist;
251 unsigned *data = ptrlist + 4;
252 char buf[4];
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800253 unsigned cwperpage;
254
255 cwperpage = (flash_pagesize >> 9);
Shashank Mittalad3d05c2009-11-19 15:53:57 -0800256
257 /* Check first page of this block */
Channagoud Kadabibeb17d52011-03-25 17:14:00 +0530258 if(page & num_pages_per_blk_mask)
259 page = page - (page & num_pages_per_blk_mask);
Shashank Mittalad3d05c2009-11-19 15:53:57 -0800260
261 /* Check bad block marker */
262 data[0] = NAND_CMD_PAGE_READ; /* command */
263
264 /* addr0 */
265 if (CFG1 & CFG1_WIDE_FLASH)
Channagoud Kadabi404a7062011-03-21 19:27:50 +0530266 data[1] = enable_bch_ecc ?
267 ((page << 16) | ((532*(cwperpage-1)) >> 1)):
268 ((page << 16) | ((528*(cwperpage-1)) >> 1));
269
Shashank Mittalad3d05c2009-11-19 15:53:57 -0800270 else
Channagoud Kadabi404a7062011-03-21 19:27:50 +0530271 data[1] = enable_bch_ecc ?
272 ((page << 16) | (532*(cwperpage-1))):
273 ((page << 16) | (528*(cwperpage-1)));
Shashank Mittalad3d05c2009-11-19 15:53:57 -0800274
275 data[2] = (page >> 16) & 0xff; /* addr1 */
276 data[3] = 0 | 4; /* chipsel */
277 data[4] = NAND_CFG0_RAW & ~(7U << 6); /* cfg0 */
278 data[5] = NAND_CFG1_RAW | (CFG1 & CFG1_WIDE_FLASH); /* cfg1 */
Channagoud Kadabi404a7062011-03-21 19:27:50 +0530279 if (enable_bch_ecc) {
280 data[6] = ECC_BCH_CFG; /* ECC CFG */
281 }
282 data[7] = 1;
283 data[8] = CLEAN_DATA_32; /* flash status */
284 data[9] = CLEAN_DATA_32; /* buf status */
Shashank Mittalad3d05c2009-11-19 15:53:57 -0800285
286 cmd[0].cmd = DST_CRCI_NAND_CMD | CMD_OCB;
287 cmd[0].src = paddr(&data[0]);
288 cmd[0].dst = NAND_FLASH_CMD;
289 cmd[0].len = 16;
290
291 cmd[1].cmd = 0;
292 cmd[1].src = paddr(&data[4]);
293 cmd[1].dst = NAND_DEV0_CFG0;
Channagoud Kadabi404a7062011-03-21 19:27:50 +0530294 if (enable_bch_ecc) {
295 cmd[1].len = 12;
296 } else {
297 cmd[1].len = 8;
298 }
Shashank Mittalad3d05c2009-11-19 15:53:57 -0800299
300 cmd[2].cmd = 0;
Channagoud Kadabi404a7062011-03-21 19:27:50 +0530301 cmd[2].src = paddr(&data[7]);
Shashank Mittalad3d05c2009-11-19 15:53:57 -0800302 cmd[2].dst = NAND_EXEC_CMD;
303 cmd[2].len = 4;
304
305 cmd[3].cmd = SRC_CRCI_NAND_DATA;
306 cmd[3].src = NAND_FLASH_STATUS;
Channagoud Kadabi404a7062011-03-21 19:27:50 +0530307 cmd[3].dst = paddr(&data[8]);
Shashank Mittalad3d05c2009-11-19 15:53:57 -0800308 cmd[3].len = 8;
309
310 cmd[4].cmd = CMD_OCU | CMD_LC;
Channagoud Kadabi404a7062011-03-21 19:27:50 +0530311 cmd[4].src = NAND_FLASH_BUFFER + (flash_pagesize - (enable_bch_ecc ?
312 (532*(cwperpage-1)):
313 (528*(cwperpage-1))));
Shashank Mittalad3d05c2009-11-19 15:53:57 -0800314 cmd[4].dst = paddr(&buf);
315 cmd[4].len = 4;
316
317 ptr[0] = (paddr(cmd) >> 3) | CMD_PTR_LP;
318
319 dmov_exec_cmdptr(DMOV_NAND_CHAN, ptr);
320
321#if VERBOSE
Channagoud Kadabi404a7062011-03-21 19:27:50 +0530322 dprintf(INFO, "status: %x\n", data[8]);
Shashank Mittalad3d05c2009-11-19 15:53:57 -0800323#endif
324
325 /* we fail if there was an operation error, a mpu error, or the
326 ** erase success bit was not set.
327 */
Channagoud Kadabi404a7062011-03-21 19:27:50 +0530328 if(data[8] & 0x110) return -1;
Shashank Mittalad3d05c2009-11-19 15:53:57 -0800329
330 /* Check for bad block marker byte */
331 if (CFG1 & CFG1_WIDE_FLASH) {
332 if (buf[0] != 0xFF || buf[1] != 0xFF)
333 return 1;
334 } else {
335 if (buf[0] != 0xFF)
336 return 1;
337 }
338
339 return 0;
340}
341
Murali Nalajalaa8c94c62010-03-05 20:24:30 +0530342static int flash_nand_block_isbad_interleave(dmov_s *cmdlist, unsigned *ptrlist,
343 unsigned page)
344{
345 dmov_s *cmd = cmdlist;
346 unsigned *ptr = ptrlist;
347 unsigned *data = ptrlist + 4;
348 char buf01[4];
349 char buf10[4];
350 unsigned cwperpage;
351
352 cwperpage = ((flash_pagesize >> 1)>> 9);
353
354 /* Check first page of this block */
355 if(page & 63)
356 page = page - (page & 63);
357
358 /* Check bad block marker */
359 data[0] = NAND_CMD_PAGE_READ; /* command */
360
361 /* addr0 */
362 if (CFG1 & CFG1_WIDE_FLASH)
363 data[1] = (page << 16) | ((528*(cwperpage-1)) >> 1);
364 else
365 data[1] = (page << 16) | (528*(cwperpage-1));
366
367 data[2] = (page >> 16) & 0xff; /* addr1 */
368 data[3] = 0 | 4; /* chipsel CS0 */
369 data[4] = 0 | 5; /* chipsel CS1 */
370 data[5] = NAND_CFG0_RAW & ~(7U << 6); /* cfg0 */
371 data[6] = NAND_CFG1_RAW | (CFG1 & CFG1_WIDE_FLASH); /* cfg1 */
372 data[7] = 1;
373 data[8] = CLEAN_DATA_32; /* NC01 flash status */
374 data[9] = CLEAN_DATA_32; /* NC01 buf01 status */
375 data[10] = CLEAN_DATA_32; /* NC10 flash status */
376 data[11] = CLEAN_DATA_32; /* NC10 buf10 status */
377 data[12] = 0x00000A3C; /* adm_mux_data_ack_req_nc01 */
378 data[13] = 0x0000053C; /* adm_mux_cmd_ack_req_nc01 */
379 data[14] = 0x00000F28; /* adm_mux_data_ack_req_nc10 */
380 data[15] = 0x00000F14; /* adm_mux_cmd_ack_req_nc10 */
381 data[16] = 0x00000FC0; /* adm_default_mux */
382 data[17] = 0x00000805; /* enable CS1 */
383 data[18] = 0x00000801; /* disable CS1 */
384
385 /* enable CS1 */
386 cmd[0].cmd = 0;
387 cmd[0].src = paddr(data[17]);
388 cmd[0].dst = EBI2_CHIP_SELECT_CFG0;
389 cmd[0].len = 4;
390
391 /* Reading last code word from NC01 */
392 /* 0xF14 */
393 cmd[1].cmd = 0;
394 cmd[1].src = paddr(data[15]);
395 cmd[1].dst = EBI2_NAND_ADM_MUX;
396 cmd[1].len = 4;
397
398 cmd[2].cmd = DST_CRCI_NAND_CMD;
399 cmd[2].src = paddr(&data[0]);
400 cmd[2].dst = NC01(NAND_FLASH_CMD);
401 cmd[2].len = 16;
402
403 cmd[3].cmd = 0;
404 cmd[3].src = paddr(&data[5]);
405 cmd[3].dst = NC01(NAND_DEV0_CFG0);
406 cmd[3].len = 8;
407
408 cmd[4].cmd = 0;
409 cmd[4].src = paddr(&data[7]);
410 cmd[4].dst = NC01(NAND_EXEC_CMD);
411 cmd[4].len = 4;
412
413 /* 0xF28 */
414 cmd[5].cmd = 0;
415 cmd[5].src = paddr(data[14]);
416 cmd[5].dst = EBI2_NAND_ADM_MUX;
417 cmd[5].len = 4;
418
419 cmd[6].cmd = SRC_CRCI_NAND_DATA;
420 cmd[6].src = NC01(NAND_FLASH_STATUS);
421 cmd[6].dst = paddr(&data[8]);
422 cmd[6].len = 8;
423
424 cmd[7].cmd = 0;
425 cmd[7].src = NC01(NAND_FLASH_BUFFER) + (flash_pagesize - (528*(cwperpage-1)));
426 cmd[7].dst = paddr(&buf01);
427 cmd[7].len = 4;
428
429 /* Reading last code word from NC10 */
430 /* 0x53C */
431 cmd[8].cmd = 0;
432 cmd[8].src = paddr(data[13]);
433 cmd[8].dst = EBI2_NAND_ADM_MUX;
434 cmd[8].len = 4;
435
436 cmd[9].cmd = DST_CRCI_NAND_CMD;
437 cmd[9].src = paddr(&data[0]);
438 cmd[9].dst = NC10(NAND_FLASH_CMD);
439 cmd[9].len = 12;
440
441 cmd[10].cmd = 0;
442 cmd[10].src = paddr(&data[4]);
443 cmd[10].dst = NC10(NAND_FLASH_CHIP_SELECT);
444 cmd[10].len = 4;
445
446 cmd[11].cmd = 0;
447 cmd[11].src = paddr(&data[5]);
448 cmd[11].dst = NC10(NAND_DEV1_CFG0);
449 cmd[11].len = 8;
450
451 cmd[12].cmd = 0;
452 cmd[12].src = paddr(&data[7]);
453 cmd[12].dst = NC10(NAND_EXEC_CMD);
454 cmd[12].len = 4;
455
456 /* 0xA3C */
457 cmd[13].cmd = 0;
458 cmd[13].src = paddr(data[12]);
459 cmd[13].dst = EBI2_NAND_ADM_MUX;
460 cmd[13].len = 4;
461
462 cmd[14].cmd = SRC_CRCI_NAND_DATA;
463 cmd[14].src = NC10(NAND_FLASH_STATUS);
464 cmd[14].dst = paddr(&data[10]);
465 cmd[14].len = 8;
466
467 cmd[15].cmd = 0;
468 cmd[15].src = NC10(NAND_FLASH_BUFFER) + (flash_pagesize - (528*(cwperpage-1)));
469 cmd[15].dst = paddr(&buf10);
470 cmd[15].len = 4;
471
472 cmd[16].cmd = 0;
473 cmd[16].src = paddr(&data[16]);
474 cmd[16].dst = EBI2_NAND_ADM_MUX;
475 cmd[16].len = 4;
476
477 /* setting default value */
478 cmd[17].cmd = CMD_OCU | CMD_LC;
479 cmd[17].src = paddr(&data[18]);
480 cmd[17].dst = EBI2_CHIP_SELECT_CFG0;
481 cmd[17].len = 4;
482
483 ptr[0] = (paddr(cmd) >> 3) | CMD_PTR_LP;
484
485 dmov_exec_cmdptr(DMOV_NAND_CHAN, ptr);
486
487#if VERBOSE
488 dprintf(INFO, "NC01 status: %x\n", data[8]);
489 dprintf(INFO, "NC10 status: %x\n", data[10]);
490#endif
491
492 /* we fail if there was an operation error, a mpu error, or the
493 ** erase success bit was not set.
494 */
495 if((data[8] & 0x110) || (data[10] & 0x110)) return -1;
496
497 /* Check for bad block marker byte */
498 if (CFG1 & CFG1_WIDE_FLASH) {
499 if ((buf01[0] != 0xFF || buf01[1] != 0xFF) ||
500 (buf10[0] != 0xFF || buf10[1] != 0xFF))
501 return 1;
502 } else {
503 if (buf01[0] != 0xFF || buf10[0] != 0xFF)
504 return 1;
505 }
506
507 return 0;
508}
509
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800510static int flash_nand_erase_block(dmov_s *cmdlist, unsigned *ptrlist,
511 unsigned page)
Dima Zavin03cf4312009-01-23 16:38:30 -0800512{
513 dmov_s *cmd = cmdlist;
514 unsigned *ptr = ptrlist;
515 unsigned *data = ptrlist + 4;
Shashank Mittalad3d05c2009-11-19 15:53:57 -0800516 int isbad = 0;
Dima Zavin03cf4312009-01-23 16:38:30 -0800517
518 /* only allow erasing on block boundaries */
Channagoud Kadabibeb17d52011-03-25 17:14:00 +0530519 if(page & num_pages_per_blk_mask) return -1;
Dima Zavin03cf4312009-01-23 16:38:30 -0800520
Shashank Mittalad3d05c2009-11-19 15:53:57 -0800521 /* Check for bad block and erase only if block is not marked bad */
522 isbad = flash_nand_block_isbad(cmdlist, ptrlist, page);
523
524 if (isbad) {
Channagoud Kadabibeb17d52011-03-25 17:14:00 +0530525 dprintf(INFO, "skipping @ %d (bad block)\n", page / num_pages_per_blk);
Shashank Mittalad3d05c2009-11-19 15:53:57 -0800526 return -1;
527 }
528
529 /* Erase block */
Dima Zavin03cf4312009-01-23 16:38:30 -0800530 data[0] = NAND_CMD_BLOCK_ERASE;
531 data[1] = page;
532 data[2] = 0;
533 data[3] = 0 | 4;
534 data[4] = 1;
535 data[5] = 0xeeeeeeee;
536 data[6] = CFG0 & (~(7 << 6)); /* CW_PER_PAGE = 0 */
537 data[7] = CFG1;
Channagoud Kadabi404a7062011-03-21 19:27:50 +0530538 data[8] = ECC_BCH_CFG;
539 data[9] = 0x00000020;
540 data[10] = 0x000000C0;
Dima Zavin03cf4312009-01-23 16:38:30 -0800541
542 cmd[0].cmd = DST_CRCI_NAND_CMD | CMD_OCB;
543 cmd[0].src = paddr(&data[0]);
544 cmd[0].dst = NAND_FLASH_CMD;
545 cmd[0].len = 16;
546
547 cmd[1].cmd = 0;
548 cmd[1].src = paddr(&data[6]);
549 cmd[1].dst = NAND_DEV0_CFG0;
Channagoud Kadabi404a7062011-03-21 19:27:50 +0530550 if (enable_bch_ecc) {
551 cmd[1].len = 12;
552 } else {
553 cmd[1].len = 8;
554 }
Dima Zavin03cf4312009-01-23 16:38:30 -0800555
556 cmd[2].cmd = 0;
557 cmd[2].src = paddr(&data[4]);
558 cmd[2].dst = NAND_EXEC_CMD;
559 cmd[2].len = 4;
560
Murali Palnatic54d13a2010-01-15 19:50:19 +0530561 cmd[3].cmd = SRC_CRCI_NAND_DATA;
Dima Zavin03cf4312009-01-23 16:38:30 -0800562 cmd[3].src = NAND_FLASH_STATUS;
563 cmd[3].dst = paddr(&data[5]);
564 cmd[3].len = 4;
565
Murali Palnatic54d13a2010-01-15 19:50:19 +0530566 cmd[4].cmd = 0;
Channagoud Kadabi404a7062011-03-21 19:27:50 +0530567 cmd[4].src = paddr(&data[9]);
Murali Palnatic54d13a2010-01-15 19:50:19 +0530568 cmd[4].dst = NAND_FLASH_STATUS;
569 cmd[4].len = 4;
570
571 cmd[5].cmd = CMD_OCU | CMD_LC;
Channagoud Kadabi404a7062011-03-21 19:27:50 +0530572 cmd[5].src = paddr(&data[10]);
Murali Palnatic54d13a2010-01-15 19:50:19 +0530573 cmd[5].dst = NAND_READ_STATUS;
574 cmd[5].len = 4;
575
Dima Zavin03cf4312009-01-23 16:38:30 -0800576 ptr[0] = (paddr(cmd) >> 3) | CMD_PTR_LP;
577
578 dmov_exec_cmdptr(DMOV_NAND_CHAN, ptr);
579
580#if VERBOSE
581 dprintf(INFO, "status: %x\n", data[5]);
582#endif
583
584 /* we fail if there was an operation error, a mpu error, or the
585 ** erase success bit was not set.
586 */
587 if(data[5] & 0x110) return -1;
588 if(!(data[5] & 0x80)) return -1;
589
590 return 0;
591}
592
Murali Nalajalaa8c94c62010-03-05 20:24:30 +0530593static int flash_nand_erase_block_interleave(dmov_s *cmdlist, unsigned *ptrlist,
594 unsigned page)
595{
596 dmov_s *cmd = cmdlist;
597 unsigned *ptr = ptrlist;
598 unsigned *data = ptrlist + 4;
599 int isbad = 0;
600
601 /* only allow erasing on block boundaries */
602 if(page & 63) return -1;
603
604 /* Check for bad block and erase only if block is not marked bad */
605 isbad = flash_nand_block_isbad(cmdlist, ptrlist, page);
606
607 if (isbad) {
608 dprintf(INFO, "skipping @ %d (bad block)\n", page >> 6);
609 return -1;
610 }
611
612 /* Erase block */
613 data[0] = NAND_CMD_BLOCK_ERASE;
614 data[1] = page;
615 data[2] = 0;
616 data[3] = 0 | 4; /* chipselect CS0 */
617 data[4] = 0 | 5; /* chipselect CS1 */
618 data[5] = 1;
619 data[6] = 0xeeeeeeee;
620 data[7] = 0xeeeeeeee;
621 data[8] = CFG0 & (~(7 << 6)); /* CW_PER_PAGE = 0 */
622 data[9] = CFG1;
623 data[10] = 0x00000A3C; /* adm_mux_data_ack_req_nc01 */
624 data[11] = 0x0000053C; /* adm_mux_cmd_ack_req_nc01 */
625 data[12] = 0x00000F28; /* adm_mux_data_ack_req_nc10 */
626 data[13] = 0x00000F14; /* adm_mux_cmd_ack_req_nc10 */
627 data[14] = 0x00000FC0; /* adm_default_mux */
628 data[15] = 0x00000805; /* enable CS1 */
629 data[16] = 0x00000801; /* disable CS1 */
630
631 /* enable CS1 */
632 cmd[0].cmd = 0 | CMD_OCB;
633 cmd[0].src = paddr(data[15]);
634 cmd[0].dst = EBI2_CHIP_SELECT_CFG0;
635 cmd[0].len = 4;
636
637 /* Reading last code word from NC01 */
638 /* 0xF14 */
639 cmd[1].cmd = 0;
640 cmd[1].src = paddr(data[13]);
641 cmd[1].dst = EBI2_NAND_ADM_MUX;
642 cmd[1].len = 4;
643
644 cmd[2].cmd = DST_CRCI_NAND_CMD;
645 cmd[2].src = paddr(&data[0]);
646 cmd[2].dst = NC01(NAND_FLASH_CMD);
647 cmd[2].len = 16;
648
649 cmd[3].cmd = 0;
650 cmd[3].src = paddr(&data[8]);
651 cmd[3].dst = NC01(NAND_DEV0_CFG0);
652 cmd[3].len = 8;
653
654 cmd[4].cmd = 0;
655 cmd[4].src = paddr(&data[5]);
656 cmd[4].dst = NC01(NAND_EXEC_CMD);
657 cmd[4].len = 4;
658
659 /* 0xF28 */
660 cmd[5].cmd = 0;
661 cmd[5].src = paddr(data[12]);
662 cmd[5].dst = EBI2_NAND_ADM_MUX;
663 cmd[5].len = 4;
664
665 cmd[6].cmd = SRC_CRCI_NAND_DATA;
666 cmd[6].src = NC01(NAND_FLASH_STATUS);
667 cmd[6].dst = paddr(&data[6]);
668 cmd[6].len = 4;
669
670 /* Reading last code word from NC10 */
671 /* 0x53C */
672 cmd[7].cmd = 0;
673 cmd[7].src = paddr(data[11]);
674 cmd[7].dst = EBI2_NAND_ADM_MUX;
675 cmd[7].len = 4;
676
677 cmd[8].cmd = DST_CRCI_NAND_CMD;
678 cmd[8].src = paddr(&data[0]);
679 cmd[8].dst = NC10(NAND_FLASH_CMD);
680 cmd[8].len = 12;
681
682 cmd[9].cmd = 0;
683 cmd[9].src = paddr(&data[4]);
684 cmd[9].dst = NC10(NAND_FLASH_CHIP_SELECT);
685 cmd[9].len = 4;
686
687 cmd[10].cmd = 0;
688 cmd[10].src = paddr(&data[8]);
689 cmd[10].dst = NC10(NAND_DEV1_CFG0);
690 cmd[10].len = 8;
691
692 cmd[11].cmd = 0;
693 cmd[11].src = paddr(&data[5]);
694 cmd[11].dst = NC10(NAND_EXEC_CMD);
695 cmd[11].len = 4;
696
697 /* 0xA3C */
698 cmd[12].cmd = 0;
699 cmd[12].src = paddr(data[10]);
700 cmd[12].dst = EBI2_NAND_ADM_MUX;
701 cmd[12].len = 4;
702
703 cmd[13].cmd = SRC_CRCI_NAND_DATA;
704 cmd[13].src = NC10(NAND_FLASH_STATUS);
705 cmd[13].dst = paddr(&data[7]);
706 cmd[13].len = 4;
707
708 /* adm default mux state */
709 /* 0xFCO */
710 cmd[14].cmd = 0;
711 cmd[14].src = paddr(data[14]);
712 cmd[14].dst = EBI2_NAND_ADM_MUX;
713 cmd[14].len = 4;
714
715 /* disable CS1 */
716 cmd[15].cmd = CMD_OCU | CMD_LC;
717 cmd[15].src = paddr(data[16]);
718 cmd[15].dst = EBI2_CHIP_SELECT_CFG0;
719 cmd[15].len = 4;
720
721 ptr[0] = (paddr(cmd) >> 3) | CMD_PTR_LP;
722
723 dmov_exec_cmdptr(DMOV_NAND_CHAN, ptr);
724
725#if VERBOSE
726 dprintf(INFO, "NC01 status: %x\n", data[6]);
727 dprintf(INFO, "NC10 status: %x\n", data[7]);
728#endif
729
730 /* we fail if there was an operation error, a mpu error, or the
731 ** erase success bit was not set.
732 */
733 if(data[6] & 0x110 || data[7] & 0x110) return -1;
734 if(!(data[6] & 0x80) || !(data[7] & 0x80)) return -1;
735
736 return 0;
737}
738
Dima Zavin03cf4312009-01-23 16:38:30 -0800739struct data_flash_io {
740 unsigned cmd;
741 unsigned addr0;
742 unsigned addr1;
743 unsigned chipsel;
744 unsigned cfg0;
745 unsigned cfg1;
Channagoud Kadabi404a7062011-03-21 19:27:50 +0530746 unsigned ecc_bch_cfg;
Dima Zavin03cf4312009-01-23 16:38:30 -0800747 unsigned exec;
748 unsigned ecc_cfg;
749 unsigned ecc_cfg_save;
Murali Palnatic54d13a2010-01-15 19:50:19 +0530750 unsigned clrfstatus;
751 unsigned clrrstatus;
Dima Zavin03cf4312009-01-23 16:38:30 -0800752 struct {
753 unsigned flash_status;
754 unsigned buffer_status;
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800755 } result[8];
Dima Zavin03cf4312009-01-23 16:38:30 -0800756};
757
Murali Nalajalaa8c94c62010-03-05 20:24:30 +0530758struct interleave_data_flash_io {
759 uint32_t cmd;
760 uint32_t addr0;
761 uint32_t addr1;
762 uint32_t chipsel_cs0;
763 uint32_t chipsel_cs1;
764 uint32_t cfg0;
765 uint32_t cfg1;
766 uint32_t exec;
767 uint32_t ecc_cfg;
768 uint32_t ecc_cfg_save;
769 uint32_t ebi2_chip_select_cfg0;
770 uint32_t adm_mux_data_ack_req_nc01;
771 uint32_t adm_mux_cmd_ack_req_nc01;
772 uint32_t adm_mux_data_ack_req_nc10;
773 uint32_t adm_mux_cmd_ack_req_nc10;
774 uint32_t adm_default_mux;
775 uint32_t default_ebi2_chip_select_cfg0;
776 struct {
777 uint32_t flash_status;
778 } result[16];
779};
780
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800781static int _flash_nand_read_page(dmov_s *cmdlist, unsigned *ptrlist,
782 unsigned page, void *_addr, void *_spareaddr)
Dima Zavin03cf4312009-01-23 16:38:30 -0800783{
784 dmov_s *cmd = cmdlist;
785 unsigned *ptr = ptrlist;
786 struct data_flash_io *data = (void*) (ptrlist + 4);
787 unsigned addr = (unsigned) _addr;
788 unsigned spareaddr = (unsigned) _spareaddr;
789 unsigned n;
Shashank Mittalad3d05c2009-11-19 15:53:57 -0800790 int isbad = 0;
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800791 unsigned cwperpage;
792 cwperpage = (flash_pagesize >> 9);
Shashank Mittalad3d05c2009-11-19 15:53:57 -0800793
794 /* Check for bad block and read only from a good block */
795 isbad = flash_nand_block_isbad(cmdlist, ptrlist, page);
796 if (isbad)
797 return -2;
Dima Zavin03cf4312009-01-23 16:38:30 -0800798
799 data->cmd = NAND_CMD_PAGE_READ_ECC;
800 data->addr0 = page << 16;
801 data->addr1 = (page >> 16) & 0xff;
802 data->chipsel = 0 | 4; /* flash0 + undoc bit */
803
804 /* GO bit for the EXEC register */
805 data->exec = 1;
806
807 data->cfg0 = CFG0;
808 data->cfg1 = CFG1;
809
Channagoud Kadabi404a7062011-03-21 19:27:50 +0530810 if (enable_bch_ecc) {
811 data->ecc_bch_cfg = ECC_BCH_CFG;
812 }
Dima Zavin03cf4312009-01-23 16:38:30 -0800813 data->ecc_cfg = 0x203;
814
815 /* save existing ecc config */
816 cmd->cmd = CMD_OCB;
817 cmd->src = NAND_EBI2_ECC_BUF_CFG;
818 cmd->dst = paddr(&data->ecc_cfg_save);
819 cmd->len = 4;
820 cmd++;
821
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800822 for(n = 0; n < cwperpage; n++) {
Dima Zavin03cf4312009-01-23 16:38:30 -0800823 /* write CMD / ADDR0 / ADDR1 / CHIPSEL regs in a burst */
824 cmd->cmd = DST_CRCI_NAND_CMD;
825 cmd->src = paddr(&data->cmd);
826 cmd->dst = NAND_FLASH_CMD;
827 cmd->len = ((n == 0) ? 16 : 4);
828 cmd++;
829
830 if (n == 0) {
831 /* block on cmd ready, set configuration */
832 cmd->cmd = 0;
833 cmd->src = paddr(&data->cfg0);
834 cmd->dst = NAND_DEV0_CFG0;
Channagoud Kadabi404a7062011-03-21 19:27:50 +0530835 if (enable_bch_ecc) {
836 cmd->len = 12;
837 } else {
838 cmd->len = 8;
839 }
Dima Zavin03cf4312009-01-23 16:38:30 -0800840 cmd++;
841
842 /* set our ecc config */
843 cmd->cmd = 0;
844 cmd->src = paddr(&data->ecc_cfg);
845 cmd->dst = NAND_EBI2_ECC_BUF_CFG;
846 cmd->len = 4;
847 cmd++;
848 }
849 /* kick the execute register */
850 cmd->cmd = 0;
851 cmd->src = paddr(&data->exec);
852 cmd->dst = NAND_EXEC_CMD;
853 cmd->len = 4;
854 cmd++;
855
856 /* block on data ready, then read the status register */
857 cmd->cmd = SRC_CRCI_NAND_DATA;
858 cmd->src = NAND_FLASH_STATUS;
859 cmd->dst = paddr(&data->result[n]);
860 cmd->len = 8;
861 cmd++;
862
863 /* read data block */
864 cmd->cmd = 0;
865 cmd->src = NAND_FLASH_BUFFER;
866 cmd->dst = addr + n * 516;
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800867 cmd->len = ((n < (cwperpage -1 )) ? 516 : (512 - ((cwperpage - 1) << 2)));
Dima Zavin03cf4312009-01-23 16:38:30 -0800868 cmd++;
869 }
870
871 /* read extra data */
872 cmd->cmd = 0;
Channagoud Kadabi404a7062011-03-21 19:27:50 +0530873 cmd->src = NAND_FLASH_BUFFER + (512 - ((cwperpage - 1) << 2));
Dima Zavin03cf4312009-01-23 16:38:30 -0800874 cmd->dst = spareaddr;
875 cmd->len = 16;
876 cmd++;
877
878 /* restore saved ecc config */
879 cmd->cmd = CMD_OCU | CMD_LC;
880 cmd->src = paddr(&data->ecc_cfg_save);
881 cmd->dst = NAND_EBI2_ECC_BUF_CFG;
882 cmd->len = 4;
883
884 ptr[0] = (paddr(cmdlist) >> 3) | CMD_PTR_LP;
885
886 dmov_exec_cmdptr(DMOV_NAND_CHAN, ptr);
887
888#if VERBOSE
889 dprintf(INFO, "read page %d: status: %x %x %x %x\n",
890 page, data[5], data[6], data[7], data[8]);
891 for(n = 0; n < 4; n++) {
892 ptr = (unsigned*)(addr + 512 * n);
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800893 dprintf(INFO, "data%d: %x %x %x %x\n", n, ptr[0], ptr[1], ptr[2], ptr[3]);
Dima Zavin03cf4312009-01-23 16:38:30 -0800894 ptr = (unsigned*)(spareaddr + 16 * n);
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800895 dprintf(INFO, "spare data%d %x %x %x %x\n", n, ptr[0], ptr[1], ptr[2], ptr[3]);
Dima Zavin03cf4312009-01-23 16:38:30 -0800896 }
897#endif
898
899 /* if any of the writes failed (0x10), or there was a
900 ** protection violation (0x100), we lose
901 */
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800902 for(n = 0; n < cwperpage; n++) {
Dima Zavin03cf4312009-01-23 16:38:30 -0800903 if (data->result[n].flash_status & 0x110) {
904 return -1;
905 }
906 }
907
908 return 0;
909}
910
Murali Nalajalaa8c94c62010-03-05 20:24:30 +0530911static int flash_nand_read_page_interleave(dmov_s *cmdlist, unsigned *ptrlist,
912 unsigned page, void *_addr, void *_spareaddr)
913{
914 dmov_s *cmd = cmdlist;
915 unsigned *ptr = ptrlist;
916 struct interleave_data_flash_io *data = (void*) (ptrlist + 4);
917 unsigned addr = (unsigned) _addr;
918 unsigned spareaddr = (unsigned) _spareaddr;
919 unsigned n;
920 int isbad = 0;
921 unsigned cwperpage;
922 cwperpage = (flash_pagesize >> 9);
923
924 /* Check for bad block and read only from a good block */
925 isbad = flash_nand_block_isbad(cmdlist, ptrlist, page);
926 if (isbad)
927 return -2;
928
929 data->cmd = NAND_CMD_PAGE_READ_ECC;
930 data->addr0 = page << 16;
931 data->addr1 = (page >> 16) & 0xff;
932 data->chipsel_cs0 = 0 | 4; /* flash0 + undoc bit */
933 data->chipsel_cs1 = 0 | 5; /* flash0 + undoc bit */
934 data->ebi2_chip_select_cfg0 = 0x00000805;
935 data->adm_mux_data_ack_req_nc01 = 0x00000A3C;
936 data->adm_mux_cmd_ack_req_nc01 = 0x0000053C;
937 data->adm_mux_data_ack_req_nc10 = 0x00000F28;
938 data->adm_mux_cmd_ack_req_nc10 = 0x00000F14;
939 data->adm_default_mux = 0x00000FC0;
940 data->default_ebi2_chip_select_cfg0 = 0x00000801;
941
942 /* GO bit for the EXEC register */
943 data->exec = 1;
944
945 data->cfg0 = CFG0;
946 data->cfg1 = CFG1;
947
948 data->ecc_cfg = 0x203;
949
950 for (n = 0; n < cwperpage; n++) {
951 /* flash + buffer status return words */
952 data->result[n].flash_status = 0xeeeeeeee;
953
954 if (n == 0) {
955 /* enable CS1 */
956 cmd->cmd = CMD_OCB;
957 cmd->src = paddr(&data->ebi2_chip_select_cfg0);
958 cmd->dst = EBI2_CHIP_SELECT_CFG0;
959 cmd->len = 4;
960 cmd++;
961
962 /* save existing ecc config */
963 cmd->cmd = 0;
964 cmd->src = NAND_EBI2_ECC_BUF_CFG;
965 cmd->dst = paddr(&data->ecc_cfg_save);
966 cmd->len = 4;
967 cmd++;
968
969 /* NC01, NC10 --> ADDR0/ADDR1 */
970 cmd->cmd = 0;
971 cmd->src = paddr(&data->addr0);
972 cmd->dst = NC11(NAND_ADDR0);
973 cmd->len = 8;
974 cmd++;
975
976 /* Select the CS0,
977 * for NC01!
978 */
979 cmd->cmd = 0;
980 cmd->src = paddr(&data->chipsel_cs0);
981 cmd->dst = NC01(NAND_FLASH_CHIP_SELECT);
982 cmd->len = 4;
983 cmd++;
984
985 /* Select the CS1,
986 * for NC10!
987 */
988 cmd->cmd = 0;
989 cmd->src = paddr(&data->chipsel_cs1);
990 cmd->dst = NC10(NAND_FLASH_CHIP_SELECT);
991 cmd->len = 4;
992 cmd++;
993
994 cmd->cmd = 0;
995 cmd->src = paddr(&data->cfg0);
996 cmd->dst = NC01(NAND_DEV0_CFG0);
997 cmd->len = 8;
998 cmd++;
999
1000 /* config DEV1 for CS1 */
1001 cmd->cmd = 0;
1002 cmd->src = paddr(&data->cfg0);
1003 cmd->dst = NC10(NAND_DEV1_CFG0);
1004 cmd->len = 8;
1005 cmd++;
1006
1007 cmd->cmd = 0;
1008 cmd->src = paddr(&data->ecc_cfg);
1009 cmd->dst = NC11(NAND_EBI2_ECC_BUF_CFG);
1010 cmd->len = 4;
1011 cmd++;
1012
1013 /* if 'only' the last code word */
1014 if (n == cwperpage - 1) {
1015 /* MASK CMD ACK/REQ --> NC01 (0x53C)*/
1016 cmd->cmd = 0;
1017 cmd->src = paddr(&data->adm_mux_cmd_ack_req_nc01);
1018 cmd->dst = EBI2_NAND_ADM_MUX;
1019 cmd->len = 4;
1020 cmd++;
1021
1022 /* CMD */
1023 cmd->cmd = DST_CRCI_NAND_CMD;
1024 cmd->src = paddr(&data->cmd);
1025 cmd->dst = NC10(NAND_FLASH_CMD);
1026 cmd->len = 4;
1027 cmd++;
1028
1029 /* kick the execute register for NC10 */
1030 cmd->cmd = 0;
1031 cmd->src = paddr(&data->exec);
1032 cmd->dst = NC10(NAND_EXEC_CMD);
1033 cmd->len = 4;
1034 cmd++;
1035
1036 /* MASK DATA ACK/REQ --> NC01 (0xA3C)*/
1037 cmd->cmd = 0;
1038 cmd->src = paddr(&data->adm_mux_data_ack_req_nc01);
1039 cmd->dst = EBI2_NAND_ADM_MUX;
1040 cmd->len = 4;
1041 cmd++;
1042
1043 /* block on data ready from NC10, then
1044 * read the status register
1045 */
1046 cmd->cmd = SRC_CRCI_NAND_DATA;
1047 cmd->src = NC10(NAND_FLASH_STATUS);
1048 cmd->dst = paddr(&data->result[n]);
1049 /* NAND_FLASH_STATUS +
1050 * NAND_BUFFER_STATUS
1051 */
1052 cmd->len = 4;
1053 cmd++;
1054 } else {
1055 /* MASK CMD ACK/REQ --> NC10 (0xF14)*/
1056 cmd->cmd = 0;
1057 cmd->src = paddr(&data->adm_mux_cmd_ack_req_nc10);
1058 cmd->dst = EBI2_NAND_ADM_MUX;
1059 cmd->len = 4;
1060 cmd++;
1061
1062 /* CMD */
1063 cmd->cmd = DST_CRCI_NAND_CMD;
1064 cmd->src = paddr(&data->cmd);
1065 cmd->dst = NC01(NAND_FLASH_CMD);
1066 cmd->len = 4;
1067 cmd++;
1068
1069 /* kick the execute register for NC01*/
1070 cmd->cmd = 0;
1071 cmd->src = paddr(&data->exec);
1072 cmd->dst = NC01(NAND_EXEC_CMD);
1073 cmd->len = 4;
1074 cmd++;
1075 }
1076 }
1077
1078
1079 if (n % 2 == 0) {
1080 /* MASK CMD ACK/REQ --> NC01 (0x53C)*/
1081 cmd->cmd = 0;
1082 cmd->src = paddr(&data->adm_mux_cmd_ack_req_nc01);
1083 cmd->dst = EBI2_NAND_ADM_MUX;
1084 cmd->len = 4;
1085 cmd++;
1086
1087 /* CMD */
1088 cmd->cmd = DST_CRCI_NAND_CMD;
1089 cmd->src = paddr(&data->cmd);
1090 cmd->dst = NC10(NAND_FLASH_CMD);
1091 cmd->len = 4;
1092 cmd++;
1093
1094 /* kick the execute register for NC10 */
1095 cmd->cmd = 0;
1096 cmd->src = paddr(&data->exec);
1097 cmd->dst = NC10(NAND_EXEC_CMD);
1098 cmd->len = 4;
1099 cmd++;
1100
1101 /* MASK DATA ACK/REQ --> NC10 (0xF28)*/
1102 cmd->cmd = 0;
1103 cmd->src = paddr(&data->adm_mux_data_ack_req_nc10);
1104 cmd->dst = EBI2_NAND_ADM_MUX;
1105 cmd->len = 4;
1106 cmd++;
1107
1108 /* block on data ready from NC01, then
1109 * read the status register
1110 */
1111 cmd->cmd = SRC_CRCI_NAND_DATA;
1112 cmd->src = NC01(NAND_FLASH_STATUS);
1113 cmd->dst = paddr(&data->result[n]);
1114 /* NAND_FLASH_STATUS +
1115 * NAND_BUFFER_STATUS
1116 */
1117 cmd->len = 4;
1118 cmd++;
1119
1120 /* read data block */
1121 cmd->cmd = 0;
1122 cmd->src = NC01(NAND_FLASH_BUFFER);
1123 cmd->dst = addr + n * 516;
1124 cmd->len = ((n < (cwperpage -1 )) ? 516 : (512 - ((cwperpage - 1) << 2)));
1125 cmd++;
1126 } else {
1127 if (n != cwperpage - 1) {
1128 /* MASK CMD ACK/REQ -->
1129 * NC10 (0xF14)
1130 */
1131 cmd->cmd = 0;
1132 cmd->src = paddr(&data->adm_mux_cmd_ack_req_nc10);
1133 cmd->dst = EBI2_NAND_ADM_MUX;
1134 cmd->len = 4;
1135 cmd++;
1136
1137 /* CMD */
1138 cmd->cmd = DST_CRCI_NAND_CMD;
1139 cmd->src = paddr(&data->cmd);
1140 cmd->dst = NC01(NAND_FLASH_CMD);
1141 cmd->len = 4;
1142 cmd++;
1143
1144 /* EXEC */
1145 cmd->cmd = 0;
1146 cmd->src = paddr(&data->exec);
1147 cmd->dst = NC01(NAND_EXEC_CMD);
1148 cmd->len = 4;
1149 cmd++;
1150
1151 /* MASK DATA ACK/REQ -->
1152 * NC01 (0xA3C)
1153 */
1154 cmd->cmd = 0;
1155 cmd->src = paddr(&data->adm_mux_data_ack_req_nc01);
1156 cmd->dst = EBI2_NAND_ADM_MUX;
1157 cmd->len = 4;
1158 cmd++;
1159
1160 /* block on data ready from NC10
1161 * then read the status register
1162 */
1163 cmd->cmd = SRC_CRCI_NAND_DATA;
1164 cmd->src = NC10(NAND_FLASH_STATUS);
1165 cmd->dst = paddr(&data->result[n]);
1166 /* NAND_FLASH_STATUS +
1167 * NAND_BUFFER_STATUS
1168 */
1169 cmd->len = 4;
1170 cmd++;
1171 } else {
1172 /* MASK DATA ACK/REQ ->
1173 * NC01 (0xA3C)
1174 */
1175 cmd->cmd = 0;
1176 cmd->src = paddr(&data->adm_mux_data_ack_req_nc01);
1177 cmd->dst = EBI2_NAND_ADM_MUX;
1178 cmd->len = 4;
1179 cmd++;
1180
1181 /* block on data ready from NC10
1182 * then read the status register
1183 */
1184 cmd->cmd = SRC_CRCI_NAND_DATA;
1185 cmd->src = NC10(NAND_FLASH_STATUS);
1186 cmd->dst = paddr(&data->result[n]);
1187 /* NAND_FLASH_STATUS +
1188 * NAND_BUFFER_STATUS
1189 */
1190 cmd->len = 4;
1191 cmd++;
1192 }
1193 /* read data block */
1194 cmd->cmd = 0;
1195 cmd->src = NC10(NAND_FLASH_BUFFER);
1196 cmd->dst = addr + n * 516;
1197 cmd->len = ((n < (cwperpage -1 )) ? 516 : (512 - ((cwperpage - 1) << 2)));
1198 cmd++;
1199
1200 if (n == (cwperpage - 1)) {
1201 /* Use NC10 for reading the
1202 * last codeword!!!
1203 */
1204 cmd->cmd = 0;
1205 cmd->src = NC10(NAND_FLASH_BUFFER) +
1206 (512 - ((cwperpage -1) << 2));
1207 cmd->dst = spareaddr;
1208 cmd->len = 16;
1209 cmd++;
1210 }
1211 }
1212 }
1213 /* restore saved ecc config */
1214 cmd->cmd = CMD_OCU | CMD_LC;
1215 cmd->src = paddr(&data->ecc_cfg_save);
1216 cmd->dst = NAND_EBI2_ECC_BUF_CFG;
1217 cmd->len = 4;
1218
1219 /* ADM --> Default mux state (0xFC0) */
1220 cmd->cmd = 0;
1221 cmd->src = paddr(&data->adm_default_mux);
1222 cmd->dst = EBI2_NAND_ADM_MUX;
1223 cmd->len = 4;
1224 cmd++;
1225
1226 /* disable CS1 */
1227 cmd->cmd = 0;
1228 cmd->src = paddr(&data->default_ebi2_chip_select_cfg0);
1229 cmd->dst = EBI2_CHIP_SELECT_CFG0;
1230 cmd->len = 4;
1231 cmd++;
1232
1233 ptr[0] = (paddr(cmdlist) >> 3) | CMD_PTR_LP;
1234
1235 dmov_exec_cmdptr(DMOV_NAND_CHAN, ptr);
1236
1237#if VERBOSE
1238 dprintf(INFO, "read page %d: status: %x %x %x %x %x %x %x %x \
1239 %x %x %x %x %x %x %x %x \n", page,
1240 data->result[0].flash_status[0],
1241 data->result[1].flash_status[1],
1242 data->result[2].flash_status[2],
1243 data->result[3].flash_status[3],
1244 data->result[4].flash_status[4],
1245 data->result[5].flash_status[5],
1246 data->result[6].flash_status[6],
1247 data->result[7].flash_status[7],
1248 data->result[8].flash_status[8],
1249 data->result[9].flash_status[9],
1250 data->result[10].flash_status[10],
1251 data->result[11].flash_status[11],
1252 data->result[12].flash_status[12],
1253 data->result[13].flash_status[13],
1254 data->result[14].flash_status[14],
1255 data->result[15].flash_status[15]);
1256
1257 for(n = 0; n < 4; n++) {
1258 ptr = (unsigned*)(addr + 512 * n);
1259 dprintf(INFO, "data%d: %x %x %x %x\n", n, ptr[0], ptr[1], ptr[2], ptr[3]);
1260 ptr = (unsigned*)(spareaddr + 16 * n);
1261 dprintf(INFO, "spare data%d %x %x %x %x\n", n, ptr[0], ptr[1], ptr[2], ptr[3]);
1262 }
1263#endif
1264
1265 /* if any of the writes failed (0x10), or there was a
1266 ** protection violation (0x100), we lose
1267 */
1268 for(n = 0; n < cwperpage; n++) {
1269 if (data->result[n].flash_status & 0x110) {
1270 return -1;
1271 }
1272 }
1273
1274 return 0;
1275}
1276
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001277static int _flash_nand_write_page(dmov_s *cmdlist, unsigned *ptrlist, unsigned page,
Shashank Mittald0c836d2009-11-20 10:31:18 -08001278 const void *_addr, const void *_spareaddr, unsigned raw_mode)
Dima Zavin03cf4312009-01-23 16:38:30 -08001279{
1280 dmov_s *cmd = cmdlist;
1281 unsigned *ptr = ptrlist;
1282 struct data_flash_io *data = (void*) (ptrlist + 4);
1283 unsigned addr = (unsigned) _addr;
1284 unsigned spareaddr = (unsigned) _spareaddr;
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001285 unsigned n;
Shashank Mittaldcc2e352009-11-19 19:11:16 -08001286 unsigned cwperpage;
1287 cwperpage = (flash_pagesize >> 9);
Shashank Mittal8e49dec2010-03-01 15:19:04 -08001288 unsigned modem_partition = 0;
1289 if (CFG0 == CFG0_M)
1290 {
1291 modem_partition = 1;
1292 }
Dima Zavin03cf4312009-01-23 16:38:30 -08001293
1294 data->cmd = NAND_CMD_PRG_PAGE;
1295 data->addr0 = page << 16;
1296 data->addr1 = (page >> 16) & 0xff;
1297 data->chipsel = 0 | 4; /* flash0 + undoc bit */
Murali Palnatic54d13a2010-01-15 19:50:19 +05301298 data->clrfstatus = 0x00000020;
1299 data->clrrstatus = 0x000000C0;
Dima Zavin03cf4312009-01-23 16:38:30 -08001300
Shashank Mittald0c836d2009-11-20 10:31:18 -08001301 if (!raw_mode){
1302 data->cfg0 = CFG0;
1303 data->cfg1 = CFG1;
Channagoud Kadabi404a7062011-03-21 19:27:50 +05301304 if (enable_bch_ecc) {
1305 data->ecc_bch_cfg = ECC_BCH_CFG;
1306 }
Shashank Mittald0c836d2009-11-20 10:31:18 -08001307 }else{
1308 data->cfg0 = (NAND_CFG0_RAW & ~(7 << 6)) |((cwperpage-1) << 6);
1309 data->cfg1 = NAND_CFG1_RAW | (CFG1 & CFG1_WIDE_FLASH);
1310 }
Dima Zavin03cf4312009-01-23 16:38:30 -08001311
1312 /* GO bit for the EXEC register */
1313 data->exec = 1;
1314
Shashank Mittal8e49dec2010-03-01 15:19:04 -08001315 if (modem_partition)
1316 data->ecc_cfg = 0x1FF;
1317 else
1318 data->ecc_cfg = 0x203;
Dima Zavin03cf4312009-01-23 16:38:30 -08001319
1320 /* save existing ecc config */
1321 cmd->cmd = CMD_OCB;
1322 cmd->src = NAND_EBI2_ECC_BUF_CFG;
1323 cmd->dst = paddr(&data->ecc_cfg_save);
1324 cmd->len = 4;
1325 cmd++;
1326
Shashank Mittaldcc2e352009-11-19 19:11:16 -08001327 for(n = 0; n < cwperpage; n++) {
1328 /* write CMD / ADDR0 / ADDR1 / CHIPSEL regs in a burst */
Dima Zavin03cf4312009-01-23 16:38:30 -08001329 cmd->cmd = DST_CRCI_NAND_CMD;
1330 cmd->src = paddr(&data->cmd);
1331 cmd->dst = NAND_FLASH_CMD;
1332 cmd->len = ((n == 0) ? 16 : 4);
1333 cmd++;
1334
1335 if (n == 0) {
1336 /* set configuration */
1337 cmd->cmd = 0;
1338 cmd->src = paddr(&data->cfg0);
1339 cmd->dst = NAND_DEV0_CFG0;
Channagoud Kadabi404a7062011-03-21 19:27:50 +05301340 if (enable_bch_ecc) {
1341 cmd->len = 12;
1342 } else {
1343 cmd->len = 8;
1344 }
1345
Dima Zavin03cf4312009-01-23 16:38:30 -08001346 cmd++;
1347
1348 /* set our ecc config */
1349 cmd->cmd = 0;
1350 cmd->src = paddr(&data->ecc_cfg);
1351 cmd->dst = NAND_EBI2_ECC_BUF_CFG;
1352 cmd->len = 4;
1353 cmd++;
1354 }
1355
1356 /* write data block */
1357 cmd->cmd = 0;
Dima Zavin03cf4312009-01-23 16:38:30 -08001358 cmd->dst = NAND_FLASH_BUFFER;
Shashank Mittald0c836d2009-11-20 10:31:18 -08001359 if (!raw_mode){
Shashank Mittal8e49dec2010-03-01 15:19:04 -08001360 if(modem_partition){
1361 cmd->src = addr + n * 512;
1362 cmd->len = 512;
1363 }else{
1364 cmd->src = addr + n * 516;
1365 cmd->len = ((n < (cwperpage - 1)) ? 516 : (512 - ((cwperpage - 1) << 2)));
1366 }
Shashank Mittald0c836d2009-11-20 10:31:18 -08001367 }else{
1368 cmd->src = addr;
1369 cmd->len = 528;
1370 }
Dima Zavin03cf4312009-01-23 16:38:30 -08001371 cmd++;
1372
Shashank Mittal8e49dec2010-03-01 15:19:04 -08001373 if ((n == (cwperpage - 1)) && (!raw_mode) && (!modem_partition)) {
Dima Zavin03cf4312009-01-23 16:38:30 -08001374 /* write extra data */
1375 cmd->cmd = 0;
1376 cmd->src = spareaddr;
Shashank Mittaldcc2e352009-11-19 19:11:16 -08001377 cmd->dst = NAND_FLASH_BUFFER + (512 - ((cwperpage - 1) << 2));
1378 cmd->len = (cwperpage << 2);
Dima Zavin03cf4312009-01-23 16:38:30 -08001379 cmd++;
1380 }
1381
1382 /* kick the execute register */
1383 cmd->cmd = 0;
1384 cmd->src = paddr(&data->exec);
1385 cmd->dst = NAND_EXEC_CMD;
1386 cmd->len = 4;
1387 cmd++;
1388
1389 /* block on data ready, then read the status register */
1390 cmd->cmd = SRC_CRCI_NAND_DATA;
1391 cmd->src = NAND_FLASH_STATUS;
1392 cmd->dst = paddr(&data->result[n]);
1393 cmd->len = 8;
1394 cmd++;
Murali Palnatic54d13a2010-01-15 19:50:19 +05301395
1396 cmd->cmd = 0;
1397 cmd->src = paddr(&data->clrfstatus);
1398 cmd->dst = NAND_FLASH_STATUS;
1399 cmd->len = 4;
1400 cmd++;
1401
1402 cmd->cmd = 0;
1403 cmd->src = paddr(&data->clrrstatus);
1404 cmd->dst = NAND_READ_STATUS;
1405 cmd->len = 4;
1406 cmd++;
Dima Zavin03cf4312009-01-23 16:38:30 -08001407 }
1408
1409 /* restore saved ecc config */
1410 cmd->cmd = CMD_OCU | CMD_LC;
1411 cmd->src = paddr(&data->ecc_cfg_save);
1412 cmd->dst = NAND_EBI2_ECC_BUF_CFG;
1413 cmd->len = 4;
1414
1415 ptr[0] = (paddr(cmdlist) >> 3) | CMD_PTR_LP;
1416
1417 dmov_exec_cmdptr(DMOV_NAND_CHAN, ptr);
1418
1419#if VERBOSE
1420 dprintf(INFO, "write page %d: status: %x %x %x %x\n",
1421 page, data[5], data[6], data[7], data[8]);
1422#endif
1423
1424 /* if any of the writes failed (0x10), or there was a
1425 ** protection violation (0x100), or the program success
1426 ** bit (0x80) is unset, we lose
1427 */
Shashank Mittaldcc2e352009-11-19 19:11:16 -08001428 for(n = 0; n < cwperpage; n++) {
Dima Zavin03cf4312009-01-23 16:38:30 -08001429 if(data->result[n].flash_status & 0x110) return -1;
1430 if(!(data->result[n].flash_status & 0x80)) return -1;
1431 }
1432
Dima Zavin5582c7d2009-03-03 15:17:59 -08001433#if VERIFY_WRITE
1434 n = _flash_read_page(cmdlist, ptrlist, page, flash_data,
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001435 flash_data + 2048);
Dima Zavin5582c7d2009-03-03 15:17:59 -08001436 if (n != 0)
1437 return -1;
1438 if (memcmp(flash_data, _addr, 2048) ||
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001439 memcmp(flash_data + 2048, _spareaddr, 16)) {
Dima Zavin5582c7d2009-03-03 15:17:59 -08001440 dprintf(CRITICAL, "verify error @ page %d\n", page);
1441 return -1;
1442 }
1443#endif
Dima Zavin03cf4312009-01-23 16:38:30 -08001444 return 0;
1445}
Murali Nalajalaa8c94c62010-03-05 20:24:30 +05301446
1447static int flash_nand_write_page_interleave(dmov_s *cmdlist, unsigned *ptrlist, unsigned page,
1448 const void *_addr, const void *_spareaddr, unsigned raw_mode)
1449{
1450 dmov_s *cmd = cmdlist;
1451 unsigned *ptr = ptrlist;
1452 struct interleave_data_flash_io *data = (void*) (ptrlist + 4);
1453 unsigned addr = (unsigned) _addr;
1454 unsigned spareaddr = (unsigned) _spareaddr;
1455 unsigned n;
1456 unsigned cwperpage, cwcount;
1457
1458 cwperpage = (flash_pagesize >> 9) * 2; /* double for interleave mode */
1459 cwcount = (cwperpage << 1);
1460
1461 data->cmd = NAND_CMD_PRG_PAGE;
1462 data->addr0 = page << 16;
1463 data->addr1 = (page >> 16) & 0xff;
1464 data->chipsel_cs0 = 0 | 4; /* flash0 + undoc bit */
1465 data->chipsel_cs1 = 0 | 5; /* flash0 + undoc bit */
1466 data->ebi2_chip_select_cfg0 = 0x00000805;
1467 data->adm_mux_data_ack_req_nc01 = 0x00000A3C;
1468 data->adm_mux_cmd_ack_req_nc01 = 0x0000053C;
1469 data->adm_mux_data_ack_req_nc10 = 0x00000F28;
1470 data->adm_mux_cmd_ack_req_nc10 = 0x00000F14;
1471 data->adm_default_mux = 0x00000FC0;
1472 data->default_ebi2_chip_select_cfg0 = 0x00000801;
1473
1474 if (!raw_mode){
1475 data->cfg0 = CFG0;
1476 data->cfg1 = CFG1;
1477 }else{
1478 data->cfg0 = (NAND_CFG0_RAW & ~(7 << 6)) |((cwcount-1) << 6);
1479 data->cfg1 = NAND_CFG1_RAW | (CFG1 & CFG1_WIDE_FLASH);
1480 }
1481
1482 /* GO bit for the EXEC register */
1483 data->exec = 1;
1484 data->ecc_cfg = 0x203;
1485
1486 for (n = 0; n < cwperpage; n++) {
1487 /* status return words */
1488 data->result[n].flash_status = 0xeeeeeeee;
1489
1490 if (n == 0) {
1491 /* enable CS1 */
1492 cmd->cmd = CMD_OCB;
1493 cmd->src = paddr(&data->ebi2_chip_select_cfg0);
1494 cmd->dst = EBI2_CHIP_SELECT_CFG0;
1495 cmd->len = 4;
1496 cmd++;
1497
1498 /* save existing ecc config */
1499 cmd->cmd = 0;
1500 cmd->src = NC11(NAND_EBI2_ECC_BUF_CFG);
1501 cmd->dst = paddr(&data->ecc_cfg_save);
1502 cmd->len = 4;
1503 cmd++;
1504
1505 cmd->cmd = 0;
1506 cmd->src = paddr(&data->ecc_cfg);
1507 cmd->dst = NC11(NAND_EBI2_ECC_BUF_CFG);
1508 cmd->len = 4;
1509 cmd++;
1510
1511 cmd->cmd = 0;
1512 cmd->src = paddr(&data->addr0);
1513 cmd->dst = NC11(NAND_ADDR0);
1514 cmd->len = 8;
1515 cmd++;
1516
1517 /* enable CS0 */
1518 cmd->cmd = 0;
1519 cmd->src = paddr(&data->chipsel_cs0);
1520 cmd->dst = NC01(NAND_FLASH_CHIP_SELECT);
1521 cmd->len = 4;
1522 cmd++;
1523
1524 /* enable CS1 */
1525 cmd->cmd = 0;
1526 cmd->src = paddr(&data->chipsel_cs1);
1527 cmd->dst = NC10(NAND_FLASH_CHIP_SELECT);
1528 cmd->len = 4;
1529 cmd++;
1530
1531 cmd->cmd = 0;
1532 cmd->src =paddr(&data->cfg0);
1533 cmd->dst = NC01(NAND_DEV0_CFG0);
1534 cmd->len = 8;
1535 cmd++;
1536
1537 /* config CFG1 for CS1 */
1538 cmd->cmd = 0;
1539 cmd->src =paddr(&data->cfg0);
1540 cmd->dst = NC10(NAND_DEV1_CFG0);
1541 cmd->len = 8;
1542 cmd++;
1543 }
1544
1545 if (n % 2 == 0) {
1546 /* MASK CMD ACK/REQ --> NC10 (0xF14)*/
1547 cmd->cmd = 0;
1548 cmd->src = paddr(&data->adm_mux_cmd_ack_req_nc10);
1549 cmd->dst = EBI2_NAND_ADM_MUX;
1550 cmd->len = 4;
1551 cmd++;
1552
1553 /* CMD */
1554 cmd->cmd = DST_CRCI_NAND_CMD;
1555 cmd->src = paddr(&data->cmd);
1556 cmd->dst = NC01(NAND_FLASH_CMD);
1557 cmd->len = 4;
1558 cmd++;
1559 } else {
1560 /* MASK CMD ACK/REQ --> NC01 (0x53C)*/
1561 cmd->cmd = 0;
1562 cmd->src = paddr(&data->adm_mux_cmd_ack_req_nc01);
1563 cmd->dst = EBI2_NAND_ADM_MUX;
1564 cmd->len = 4;
1565 cmd++;
1566
1567 /* CMD */
1568 cmd->cmd = DST_CRCI_NAND_CMD;
1569 cmd->src = paddr(&data->cmd);
1570 cmd->dst = NC10(NAND_FLASH_CMD);
1571 cmd->len = 4;
1572 cmd++;
1573 }
1574
1575 cmd->cmd = 0;
1576 if (!raw_mode){
1577 cmd->src = addr + n * 516;
1578 cmd->len = ((n < (cwperpage - 1)) ? 516 : (512 - ((cwperpage - 1) << 2)));
1579 }else{
1580 cmd->src = addr;
1581 cmd->len = 528;
1582 }
1583
1584 if (n % 2 == 0)
1585 cmd->dst = NC01(NAND_FLASH_BUFFER);
1586 else
1587 cmd->dst = NC10(NAND_FLASH_BUFFER);
1588 cmd++;
1589
1590 if ((n == (cwperpage - 1)) && (!raw_mode)) {
1591 /* write extra data */
1592 cmd->cmd = 0;
1593 cmd->src = spareaddr;
1594 cmd->dst = NC10(NAND_FLASH_BUFFER) + (512 - ((cwperpage - 1) << 2));
1595 cmd->len = (cwperpage << 2);
1596 cmd++;
1597 }
1598
1599 if (n % 2 == 0) {
1600 /* kick the NC01 execute register */
1601 cmd->cmd = 0;
1602 cmd->src = paddr(&data->exec);
1603 cmd->dst = NC01(NAND_EXEC_CMD);
1604 cmd->len = 4;
1605 cmd++;
1606 if (n != 0) {
1607 /* MASK DATA ACK/REQ --> NC01 (0xA3C)*/
1608 cmd->cmd = 0;
1609 cmd->src = paddr(&data->adm_mux_data_ack_req_nc01);
1610 cmd->dst = EBI2_NAND_ADM_MUX;
1611 cmd->len = 4;
1612 cmd++;
1613
1614 /* block on data ready from NC10, then
1615 * read the status register
1616 */
1617 cmd->cmd = SRC_CRCI_NAND_DATA;
1618 cmd->src = NC10(NAND_FLASH_STATUS);
1619 cmd->dst = paddr(&data->result[n-1]);
1620 cmd->len = 4;
1621 cmd++;
1622 }
1623 } else {
1624 /* kick the execute register */
1625 cmd->cmd = 0;
1626 cmd->src = paddr(&data->exec);
1627 cmd->dst = NC10(NAND_EXEC_CMD);
1628 cmd->len = 4;
1629 cmd++;
1630
1631 /* MASK DATA ACK/REQ --> NC10 (0xF28)*/
1632 cmd->cmd = 0;
1633 cmd->src = paddr(&data->adm_mux_data_ack_req_nc10);
1634 cmd->dst = EBI2_NAND_ADM_MUX;
1635 cmd->len = 4;
1636 cmd++;
1637
1638 /* block on data ready from NC01, then
1639 * read the status register
1640 */
1641 cmd->cmd = SRC_CRCI_NAND_DATA;
1642 cmd->src = NC01(NAND_FLASH_STATUS);
1643 cmd->dst = paddr(&data->result[n-1]);
1644 cmd->len = 4;
1645 cmd++;
1646 }
1647 }
1648
1649 /* MASK DATA ACK/REQ --> NC01 (0xA3C)*/
1650 cmd->cmd = 0;
1651 cmd->src = paddr(&data->adm_mux_data_ack_req_nc01);
1652 cmd->dst = EBI2_NAND_ADM_MUX;
1653 cmd->len = 4;
1654 cmd++;
1655
1656 /* we should process outstanding request */
1657 /* block on data ready, then
1658 * read the status register
1659 */
1660 cmd->cmd = SRC_CRCI_NAND_DATA;
1661 cmd->src = NC10(NAND_FLASH_STATUS);
1662 cmd->dst = paddr(&data->result[n-1]);
1663 cmd->len = 4;
1664 cmd++;
1665
1666 /* restore saved ecc config */
1667 cmd->cmd = 0;
1668 cmd->src = paddr(&data->ecc_cfg_save);
1669 cmd->dst = NAND_EBI2_ECC_BUF_CFG;
1670 cmd->len = 4;
1671
1672 /* MASK DATA ACK/REQ --> NC01 (0xFC0)*/
1673 cmd->cmd = 0;
1674 cmd->src = paddr(&data->adm_default_mux);
1675 cmd->dst = EBI2_NAND_ADM_MUX;
1676 cmd->len = 4;
1677 cmd++;
1678
1679 /* disable CS1 */
1680 cmd->cmd = CMD_OCU | CMD_LC;
1681 cmd->src = paddr(&data->default_ebi2_chip_select_cfg0);
1682 cmd->dst = EBI2_CHIP_SELECT_CFG0;
1683 cmd->len = 4;
1684 cmd++;
1685
1686 ptr[0] = (paddr(cmdlist) >> 3) | CMD_PTR_LP;
1687
1688 dmov_exec_cmdptr(DMOV_NAND_CHAN, ptr);
1689
1690#if VERBOSE
1691dprintf(INFO, "write page %d: status: %x %x %x %x %x %x %x %x \
1692 %x %x %x %x %x %x %x %x \n", page,
1693 data->result[0].flash_status[0],
1694 data->result[1].flash_status[1],
1695 data->result[2].flash_status[2],
1696 data->result[3].flash_status[3],
1697 data->result[4].flash_status[4],
1698 data->result[5].flash_status[5],
1699 data->result[6].flash_status[6],
1700 data->result[7].flash_status[7],
1701 data->result[8].flash_status[8],
1702 data->result[9].flash_status[9],
1703 data->result[10].flash_status[10],
1704 data->result[11].flash_status[11],
1705 data->result[12].flash_status[12],
1706 data->result[13].flash_status[13],
1707 data->result[14].flash_status[14],
1708 data->result[15].flash_status[15]);
1709#endif
1710
1711 /* if any of the writes failed (0x10), or there was a
1712 ** protection violation (0x100), or the program success
1713 ** bit (0x80) is unset, we lose
1714 */
1715 for(n = 0; n < cwperpage; n++) {
1716 if(data->result[n].flash_status & 0x110) return -1;
1717 if(!(data->result[n].flash_status & 0x80)) return -1;
1718 }
1719
1720#if VERIFY_WRITE
1721 n = _flash_read_page(cmdlist, ptrlist, page, flash_data,
1722 flash_data + 2048);
1723 if (n != 0)
1724 return -1;
1725 if (memcmp(flash_data, _addr, 2048) ||
1726 memcmp(flash_data + 2048, _spareaddr, 16)) {
1727 dprintf(CRITICAL, "verify error @ page %d\n", page);
1728 return -1;
1729 }
1730#endif
1731 return 0;
1732}
1733
Shashank Mittald0c836d2009-11-20 10:31:18 -08001734char empty_buf[528];
1735static int flash_nand_mark_badblock(dmov_s *cmdlist, unsigned *ptrlist, unsigned page)
1736{
1737 memset(empty_buf,0,528);
1738 /* Going to first page of the block */
Channagoud Kadabibeb17d52011-03-25 17:14:00 +05301739 if(page & num_pages_per_blk_mask)
1740 page = page - (page & num_pages_per_blk_mask);
Shashank Mittald0c836d2009-11-20 10:31:18 -08001741 return _flash_nand_write_page(cmdlist, ptrlist, page, empty_buf, 0, 1);
1742}
Dima Zavin03cf4312009-01-23 16:38:30 -08001743
Shashank Mittal83d16d02009-11-18 16:54:42 -08001744unsigned nand_cfg0;
1745unsigned nand_cfg1;
1746
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001747static int flash_nand_read_config(dmov_s *cmdlist, unsigned *ptrlist)
Dima Zavin03cf4312009-01-23 16:38:30 -08001748{
Shashank Mittal8e49dec2010-03-01 15:19:04 -08001749 static unsigned CFG0_TMP, CFG1_TMP;
Dima Zavin03cf4312009-01-23 16:38:30 -08001750 cmdlist[0].cmd = CMD_OCB;
1751 cmdlist[0].src = NAND_DEV0_CFG0;
Shashank Mittal8e49dec2010-03-01 15:19:04 -08001752 cmdlist[0].dst = paddr(&CFG0_TMP);
Dima Zavin03cf4312009-01-23 16:38:30 -08001753 cmdlist[0].len = 4;
1754
1755 cmdlist[1].cmd = CMD_OCU | CMD_LC;
1756 cmdlist[1].src = NAND_DEV0_CFG1;
Shashank Mittal8e49dec2010-03-01 15:19:04 -08001757 cmdlist[1].dst = paddr(&CFG1_TMP);
Dima Zavin03cf4312009-01-23 16:38:30 -08001758 cmdlist[1].len = 4;
1759
1760 *ptrlist = (paddr(cmdlist) >> 3) | CMD_PTR_LP;
1761
1762 dmov_exec_cmdptr(DMOV_NAND_CHAN, ptrlist);
1763
Shashank Mittal8e49dec2010-03-01 15:19:04 -08001764 if((CFG0_TMP == 0) || (CFG1_TMP == 0)) {
Dima Zavin03cf4312009-01-23 16:38:30 -08001765 return -1;
1766 }
1767
Shashank Mittal8e49dec2010-03-01 15:19:04 -08001768 CFG0_A = CFG0_TMP;
1769 CFG1_A = CFG1_TMP;
Shashank Mittal83d16d02009-11-18 16:54:42 -08001770 if (flash_info.type == FLASH_16BIT_NAND_DEVICE) {
1771 nand_cfg1 |= CFG1_WIDE_FLASH;
1772 }
Dima Zavin03cf4312009-01-23 16:38:30 -08001773 dprintf(INFO, "nandcfg: %x %x (initial)\n", CFG0, CFG1);
1774
Shashank Mittal8e49dec2010-03-01 15:19:04 -08001775 CFG0_A = (((flash_pagesize >> 9) - 1) << 6) /* 4/8 cw/pg for 2/4k */
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001776 | (516 << 9) /* 516 user data bytes */
1777 | (10 << 19) /* 10 parity bytes */
1778 | (5 << 27) /* 5 address cycles */
Murali Palnatic54d13a2010-01-15 19:50:19 +05301779 | (0 << 30) /* Do not read status before data */
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001780 | (1 << 31) /* Send read cmd */
1781 /* 0 spare bytes for 16 bit nand or 1 spare bytes for 8 bit */
Channagoud Kadabi404a7062011-03-21 19:27:50 +05301782 | ((nand_cfg1 & CFG1_WIDE_FLASH) ? (0 << 23) :
1783 (enable_bch_ecc ? (2 << 23) : (1 << 23))); /* 2 spare bytes for 8 bit bch ecc */
Shashank Mittal8e49dec2010-03-01 15:19:04 -08001784 CFG1_A = (0 << 0) /* Enable ecc */
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001785 | (7 << 2) /* 8 recovery cycles */
1786 | (0 << 5) /* Allow CS deassertion */
Channagoud Kadabi404a7062011-03-21 19:27:50 +05301787 | ((flash_pagesize - ((enable_bch_ecc ? 532 : 528) *
1788 ((flash_pagesize >> 9) - 1)) + 1) << 6) /* Bad block marker location */
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001789 | (0 << 16) /* Bad block in user data area */
1790 | (2 << 17) /* 6 cycle tWB/tRB */
1791 | (nand_cfg1 & CFG1_WIDE_FLASH); /* preserve wide flash flag */
Dima Zavin03cf4312009-01-23 16:38:30 -08001792
Channagoud Kadabi404a7062011-03-21 19:27:50 +05301793 NAND_CFG0_RAW = CFG0_RAW;
1794 NAND_CFG1_RAW = CFG1_RAW;
1795
1796 if (enable_bch_ecc) {
1797 CFG1_A |= (1 << 27); /* Enable BCH engine */
1798 ECC_BCH_CFG = (0 << 0) /* Enable ECC*/
1799 | (0 << 1) /* Enable/Disable SW reset of ECC engine */
1800 | (1 << 4) /* 8bit ecc*/
1801 | ((nand_cfg1 & CFG1_WIDE_FLASH) ? (14 << 8) : (13 << 8))/*parity bytes*/
1802 | (516 << 16) /* 516 user data bytes */
1803 | (1 << 30); /* Turn on ECC engine clocks always */
1804 NAND_CFG0_RAW = CFG0_RAW_BCHECC; /* CW size is increased to 532B */
1805 }
1806
Shashank Mittal8e49dec2010-03-01 15:19:04 -08001807 dprintf(INFO, "nandcfg(Apps): %x %x (used)\n", CFG0_A, CFG1_A);
Dima Zavin03cf4312009-01-23 16:38:30 -08001808
Shashank Mittal8e49dec2010-03-01 15:19:04 -08001809 CFG0_M = CFG0_TMP;
1810 CFG1_M = CFG1_TMP;
1811 if (flash_info.type == FLASH_16BIT_NAND_DEVICE) {
1812 nand_cfg1 |= CFG1_WIDE_FLASH;
1813 }
1814 CFG0_M = (((flash_pagesize >> 9) - 1) << 6) /* 4/8 cw/pg for 2/4k */
1815 | (512 << 9) /* 512 user data bytes */
1816 | (10 << 19) /* 10 parity bytes */
1817 | (5 << 27) /* 5 address cycles */
1818 | (0 << 30) /* Do not read status before data */
1819 | (1 << 31) /* Send read cmd */
1820 | ((nand_cfg1 & CFG1_WIDE_FLASH) ? (4 << 23) : (5 << 23));
1821 CFG1_M = (0 << 0) /* Enable ecc */
1822 | (7 << 2) /* 8 recovery cycles */
1823 | (0 << 5) /* Allow CS deassertion */
1824 | ((flash_pagesize - (528 * ((flash_pagesize >> 9) - 1)) + 1) << 6) /* Bad block marker location */
1825 | (0 << 16) /* Bad block in user data area */
1826 | (2 << 17) /* 6 cycle tWB/tRB */
1827 | (nand_cfg1 & CFG1_WIDE_FLASH); /* preserve wide flash flag */
1828 dprintf(INFO, "nandcfg(Modem): %x %x (used)\n", CFG0_M, CFG1_M);
Dima Zavin03cf4312009-01-23 16:38:30 -08001829 return 0;
1830}
1831
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001832/* OneNAND programming functions */
1833
1834static void flash_onenand_read_id(dmov_s *cmdlist, unsigned *ptrlist)
1835{
1836 dmov_s *cmd = cmdlist;
1837 unsigned *ptr = ptrlist;
1838 unsigned *data = ptrlist + 4;
1839
1840 data[0] = SFLASH_BCFG;
1841 data[1] = SFLASH_PREPCMD(8, 0, 0, NAND_SFCMD_DATXS, NAND_SFCMD_ASYNC, NAND_SFCMD_REGRD);
1842 data[2] = (ONENAND_DEVICE_ID << 16) | (ONENAND_MANUFACTURER_ID);
1843 data[3] = (ONENAND_DATA_BUFFER_SIZE << 16) | (ONENAND_VERSION_ID);
1844 data[4] = (ONENAND_AMOUNT_OF_BUFFERS << 16) | (ONENAND_BOOT_BUFFER_SIZE);
1845 data[5] = (CLEAN_DATA_16 << 16) | (ONENAND_TECHNOLOGY);
1846 data[6] = CLEAN_DATA_32; //status
1847 data[7] = CLEAN_DATA_32; //register read
1848 data[8] = CLEAN_DATA_32; //register read
1849 data[9] = CLEAN_DATA_32; //register read
1850 data[10] = CLEAN_DATA_32; //register read
1851 data[11] = 1;
1852 data[12] = 0 | 4;
1853
1854 /* Setup controller in SFLASH mode */
1855 cmd[0].cmd = 0 | CMD_OCB;
1856 cmd[0].src = paddr(&data[0]);
1857 cmd[0].dst = NAND_SFLASHC_BURST_CFG;
1858 cmd[0].len = 4;
1859
1860 /* Enable data mover for controller */
1861 cmd[1].cmd = 0;
1862 cmd[1].src = paddr(&data[12]);
1863 cmd[1].dst = NAND_FLASH_CHIP_SELECT;
1864 cmd[1].len = 4;
1865
1866 /* Setup SFLASHC_CMD with xfers in async mode */
1867 cmd[2].cmd = DST_CRCI_NAND_CMD;
1868 cmd[2].src = paddr(&data[1]);
1869 cmd[2].dst = NAND_SFLASHC_CMD;
1870 cmd[2].len = 4;
1871
1872 /* Setup to read device information */
1873 cmd[3].cmd = 0;
1874 cmd[3].src = paddr(&data[2]);
1875 cmd[3].dst = NAND_ADDR0;
1876 cmd[3].len = 8;
1877
1878 cmd[4].cmd = 0;
1879 cmd[4].src = paddr(&data[4]);
1880 cmd[4].dst = NAND_ADDR2;
1881 cmd[4].len = 8;
1882
1883 /* Set execute bit */
1884 cmd[5].cmd = 0;
1885 cmd[5].src = paddr(&data[11]);
1886 cmd[5].dst = NAND_SFLASHC_EXEC_CMD;
1887 cmd[5].len = 4;
1888
1889 /* Check status */
1890 cmd[6].cmd = SRC_CRCI_NAND_DATA;
1891 cmd[6].src = NAND_SFLASHC_STATUS;
1892 cmd[6].dst = paddr(&data[6]);
1893 cmd[6].len = 4;
1894
1895 /* Read result device registers */
1896 cmd[7].cmd = 0 | CMD_OCU | CMD_LC;
1897 cmd[7].src = NAND_GENP_REG0;
1898 cmd[7].dst = paddr(&data[7]);
1899 cmd[7].len = 16;
1900
1901 ptr[0] = (paddr(cmd) >> 3) | CMD_PTR_LP;
1902
1903 dmov_exec_cmdptr(DMOV_NAND_CHAN, ptr);
1904
1905#if VERBOSE
1906 dprintf(INFO, "status: %x\n", data[6]);
1907#endif
1908
1909 flash_info.id = data[7];
1910 flash_info.vendor = data[7] & CLEAN_DATA_16;
1911 flash_info.device = (data[7] >> 16) & CLEAN_DATA_16;
1912 return;
1913}
1914
1915
1916struct data_onenand_erase {
1917 unsigned sfbcfg;
1918 unsigned sfcmd[4];
1919 unsigned sfexec;
1920 unsigned sfstat[4];
1921 unsigned addr0;
1922 unsigned addr1;
1923 unsigned addr2;
1924 unsigned addr3;
1925 unsigned addr4;
1926 unsigned addr5;
1927 unsigned addr6;
1928 unsigned data0;
1929 unsigned data1;
1930 unsigned data2;
1931 unsigned data3;
1932 unsigned data4;
1933 unsigned data5;
1934 unsigned data6;
1935};
1936
Shashank Mittalad3d05c2009-11-19 15:53:57 -08001937
1938static int _flash_onenand_read_page(dmov_s *cmdlist, unsigned *ptrlist,
1939 unsigned page, void *_addr,
1940 void *_spareaddr, unsigned raw_mode);
1941
1942
1943static int flash_onenand_block_isbad(dmov_s *cmdlist, unsigned *ptrlist,
1944 unsigned page)
1945{
1946 unsigned char page_data[2112];
1947 unsigned char *oobptr = &(page_data[2048]);
1948
1949 /* Going to first page of the block */
Channagoud Kadabibeb17d52011-03-25 17:14:00 +05301950 if(page & num_pages_per_blk_mask)
1951 page = page - (page & num_pages_per_blk_mask);
Shashank Mittalad3d05c2009-11-19 15:53:57 -08001952
1953 /* Reading page in raw mode */
1954 if (_flash_onenand_read_page(cmdlist, ptrlist,page, page_data, 0, 1))
1955 return 1;
1956
1957 /* Checking if block is bad */
1958 if ((oobptr[0] != 0xFF) || (oobptr[1] != 0xFF) ||
1959 (oobptr[16] != 0xFF) || (oobptr[17] != 0xFF) ||
1960 (oobptr[32] != 0xFF) || (oobptr[33] != 0xFF) ||
1961 (oobptr[48] != 0xFF) || (oobptr[49] != 0xFF)
1962 )
1963 {
1964 return 1;
1965 }
1966 return 0;
1967}
1968
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001969static int flash_onenand_erase_block(dmov_s *cmdlist, unsigned *ptrlist,
1970 unsigned page)
1971{
1972 dmov_s *cmd = cmdlist;
1973 unsigned *ptr = ptrlist;
1974 struct data_onenand_erase *data = (void *)ptrlist + 4;
Shashank Mittalad3d05c2009-11-19 15:53:57 -08001975 int isbad = 0;
Channagoud Kadabibeb17d52011-03-25 17:14:00 +05301976 unsigned erasesize = (flash_pagesize * num_pages_per_blk);
Shashank Mittaldcc2e352009-11-19 19:11:16 -08001977 unsigned onenand_startaddr1 = DEVICE_FLASHCORE_0 | (page * flash_pagesize)/erasesize;
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001978 unsigned onenand_startaddr8 = 0x0000;
1979 unsigned onenand_startaddr2 = DEVICE_BUFFERRAM_0 << 15;
1980 unsigned onenand_startbuffer = DATARAM0_0 << 8;
1981
1982 unsigned controller_status;
1983 unsigned interrupt_status;
1984 unsigned ecc_status;
1985
Shashank Mittaldcc2e352009-11-19 19:11:16 -08001986 if((page * flash_pagesize) & (erasesize-1)) return -1;
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001987
Shashank Mittalad3d05c2009-11-19 15:53:57 -08001988 /* Check for bad block and erase only if block is not marked bad */
1989 isbad = flash_onenand_block_isbad(cmdlist, ptrlist, page);
1990 if (isbad)
1991 {
Channagoud Kadabibeb17d52011-03-25 17:14:00 +05301992 dprintf(INFO, "skipping @ %d (bad block)\n", page / num_pages_per_blk);
Shashank Mittalad3d05c2009-11-19 15:53:57 -08001993 return -1;
1994 }
1995
1996 /*Erase block*/
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001997 onenand_startaddr1 = DEVICE_FLASHCORE_0 |
Shashank Mittaldcc2e352009-11-19 19:11:16 -08001998 ((page * flash_pagesize) / (erasesize));
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001999 onenand_startaddr8 = 0x0000;
2000 onenand_startaddr2 = DEVICE_BUFFERRAM_0 << 15;
2001 onenand_startbuffer = DATARAM0_0 << 8;
2002
2003
2004 data->sfbcfg = SFLASH_BCFG;
2005 data->sfcmd[0] = SFLASH_PREPCMD(7, 0, 0,
2006 NAND_SFCMD_CMDXS,
2007 NAND_SFCMD_ASYNC,
2008 NAND_SFCMD_REGWR);
2009 data->sfcmd[1] = SFLASH_PREPCMD(0, 0, 32,
2010 NAND_SFCMD_CMDXS,
2011 NAND_SFCMD_ASYNC,
2012 NAND_SFCMD_INTHI);
2013 data->sfcmd[2] = SFLASH_PREPCMD(3, 7, 0,
2014 NAND_SFCMD_DATXS,
2015 NAND_SFCMD_ASYNC,
2016 NAND_SFCMD_REGRD);
2017 data->sfcmd[3] = SFLASH_PREPCMD(4, 10, 0,
2018 NAND_SFCMD_CMDXS,
2019 NAND_SFCMD_ASYNC,
2020 NAND_SFCMD_REGWR);
2021 data->sfexec = 1;
2022 data->sfstat[0] = CLEAN_DATA_32;
2023 data->sfstat[1] = CLEAN_DATA_32;
2024 data->sfstat[2] = CLEAN_DATA_32;
2025 data->sfstat[3] = CLEAN_DATA_32;
2026 data->addr0 = (ONENAND_INTERRUPT_STATUS << 16) |
2027 (ONENAND_SYSTEM_CONFIG_1);
2028 data->addr1 = (ONENAND_START_ADDRESS_8 << 16) |
2029 (ONENAND_START_ADDRESS_1);
2030 data->addr2 = (ONENAND_START_BUFFER << 16) |
2031 (ONENAND_START_ADDRESS_2);
2032 data->addr3 = (ONENAND_ECC_STATUS << 16) |
2033 (ONENAND_COMMAND);
2034 data->addr4 = (ONENAND_CONTROLLER_STATUS << 16) |
2035 (ONENAND_INTERRUPT_STATUS);
2036 data->addr5 = (ONENAND_INTERRUPT_STATUS << 16) |
2037 (ONENAND_SYSTEM_CONFIG_1);
2038 data->addr6 = (ONENAND_START_ADDRESS_3 << 16) |
2039 (ONENAND_START_ADDRESS_1);
2040 data->data0 = (ONENAND_CLRINTR << 16) |
2041 (ONENAND_SYSCFG1_ECCENA);
2042 data->data1 = (onenand_startaddr8 << 16) |
2043 (onenand_startaddr1);
2044 data->data2 = (onenand_startbuffer << 16) |
2045 (onenand_startaddr2);
2046 data->data3 = (CLEAN_DATA_16 << 16) |
2047 (ONENAND_CMDERAS);
2048 data->data4 = (CLEAN_DATA_16 << 16) |
2049 (CLEAN_DATA_16);
2050 data->data5 = (ONENAND_CLRINTR << 16) |
2051 (ONENAND_SYSCFG1_ECCENA);
2052 data->data6 = (ONENAND_STARTADDR3_RES << 16) |
2053 (ONENAND_STARTADDR1_RES);
2054
2055 /***************************************************************/
2056 /* Write the necessary address registers in the onenand device */
2057 /***************************************************************/
2058
2059 /* Enable and configure the SFlash controller */
2060 cmd->cmd = 0 | CMD_OCB;
2061 cmd->src = paddr(&data->sfbcfg);
2062 cmd->dst = NAND_SFLASHC_BURST_CFG;
2063 cmd->len = 4;
2064 cmd++;
2065
2066 /* Block on cmd ready and write CMD register */
2067 cmd->cmd = DST_CRCI_NAND_CMD;
2068 cmd->src = paddr(&data->sfcmd[0]);
2069 cmd->dst = NAND_SFLASHC_CMD;
2070 cmd->len = 4;
2071 cmd++;
2072
2073 /* Write the ADDR0 and ADDR1 registers */
2074 cmd->cmd = 0;
2075 cmd->src = paddr(&data->addr0);
2076 cmd->dst = NAND_ADDR0;
2077 cmd->len = 8;
2078 cmd++;
2079
2080 /* Write the ADDR2 ADDR3 ADDR4 ADDR5 registers */
2081 cmd->cmd = 0;
2082 cmd->src = paddr(&data->addr2);
2083 cmd->dst = NAND_ADDR2;
2084 cmd->len = 16;
2085 cmd++;
2086
2087 /* Write the ADDR6 registers */
2088 cmd->cmd = 0;
2089 cmd->src = paddr(&data->addr6);
2090 cmd->dst = NAND_ADDR6;
2091 cmd->len = 4;
2092 cmd++;
2093
2094 /* Write the GENP0, GENP1, GENP2, GENP3, GENP4 registers */
2095 cmd->cmd = 0;
2096 cmd->src = paddr(&data->data0);
2097 cmd->dst = NAND_GENP_REG0;
2098 cmd->len = 16;
2099 cmd++;
2100
2101 /* Write the FLASH_DEV_CMD4,5,6 registers */
2102 cmd->cmd = 0;
2103 cmd->src = paddr(&data->data4);
2104 cmd->dst = NAND_DEV_CMD4;
2105 cmd->len = 12;
2106 cmd++;
2107
2108 /* Kick the execute command */
2109 cmd->cmd = 0;
2110 cmd->src = paddr(&data->sfexec);
2111 cmd->dst = NAND_SFLASHC_EXEC_CMD;
2112 cmd->len = 4;
2113 cmd++;
2114
2115 /* Block on data ready, and read the status register */
2116 cmd->cmd = SRC_CRCI_NAND_DATA;
2117 cmd->src = NAND_SFLASHC_STATUS;
2118 cmd->dst = paddr(&data->sfstat[0]);
2119 cmd->len = 4;
2120 cmd++;
2121
2122 /***************************************************************/
2123 /* Wait for the interrupt from the Onenand device controller */
2124 /***************************************************************/
2125
2126 /* Block on cmd ready and write CMD register */
2127 cmd->cmd = DST_CRCI_NAND_CMD;
2128 cmd->src = paddr(&data->sfcmd[1]);
2129 cmd->dst = NAND_SFLASHC_CMD;
2130 cmd->len = 4;
2131 cmd++;
2132
2133 /* Kick the execute command */
2134 cmd->cmd = 0;
2135 cmd->src = paddr(&data->sfexec);
2136 cmd->dst = NAND_SFLASHC_EXEC_CMD;
2137 cmd->len = 4;
2138 cmd++;
2139
2140 /* Block on data ready, and read the status register */
2141 cmd->cmd = SRC_CRCI_NAND_DATA;
2142 cmd->src = NAND_SFLASHC_STATUS;
2143 cmd->dst = paddr(&data->sfstat[1]);
2144 cmd->len = 4;
2145 cmd++;
2146
2147 /***************************************************************/
2148 /* Read the necessary status registers from the onenand device */
2149 /***************************************************************/
2150
2151 /* Block on cmd ready and write CMD register */
2152 cmd->cmd = DST_CRCI_NAND_CMD;
2153 cmd->src = paddr(&data->sfcmd[2]);
2154 cmd->dst = NAND_SFLASHC_CMD;
2155 cmd->len = 4;
2156 cmd++;
2157
2158 /* Kick the execute command */
2159 cmd->cmd = 0;
2160 cmd->src = paddr(&data->sfexec);
2161 cmd->dst = NAND_SFLASHC_EXEC_CMD;
2162 cmd->len = 4;
2163 cmd++;
2164
2165 /* Block on data ready, and read the status register */
2166 cmd->cmd = SRC_CRCI_NAND_DATA;
2167 cmd->src = NAND_SFLASHC_STATUS;
2168 cmd->dst = paddr(&data->sfstat[2]);
2169 cmd->len = 4;
2170 cmd++;
2171
2172 /* Read the GENP3 register */
2173 cmd->cmd = 0;
2174 cmd->src = NAND_GENP_REG3;
2175 cmd->dst = paddr(&data->data3);
2176 cmd->len = 4;
2177 cmd++;
2178
2179 /* Read the DEVCMD4 register */
2180 cmd->cmd = 0;
2181 cmd->src = NAND_DEV_CMD4;
2182 cmd->dst = paddr(&data->data4);
2183 cmd->len = 4;
2184 cmd++;
2185
2186 /***************************************************************/
2187 /* Restore the necessary registers to proper values */
2188 /***************************************************************/
2189
2190 /* Block on cmd ready and write CMD register */
2191 cmd->cmd = DST_CRCI_NAND_CMD;
2192 cmd->src = paddr(&data->sfcmd[3]);
2193 cmd->dst = NAND_SFLASHC_CMD;
2194 cmd->len = 4;
2195 cmd++;
2196
2197 /* Kick the execute command */
2198 cmd->cmd = 0;
2199 cmd->src = paddr(&data->sfexec);
2200 cmd->dst = NAND_SFLASHC_EXEC_CMD;
2201 cmd->len = 4;
2202 cmd++;
2203
2204 /* Block on data ready, and read the status register */
2205 cmd->cmd = SRC_CRCI_NAND_DATA | CMD_OCU | CMD_LC;
2206 cmd->src = NAND_SFLASHC_STATUS;
2207 cmd->dst = paddr(&data->sfstat[3]);
2208 cmd->len = 4;
2209 cmd++;
2210
2211 ptr[0] = (paddr(cmdlist) >> 3) | CMD_PTR_LP;
2212
2213 dmov_exec_cmdptr(DMOV_NAND_CHAN, ptr);
2214
2215 ecc_status = (data->data3 >> 16) & 0x0000FFFF;
2216 interrupt_status = (data->data4 >> 0) & 0x0000FFFF;
2217 controller_status = (data->data4 >> 16) & 0x0000FFFF;
2218
2219#if VERBOSE
2220 dprintf(INFO, "\n%s: sflash status %x %x %x %x\n", __func__,
2221 data->sfstat[0],
2222 data->sfstat[1],
2223 data->sfstat[2],
2224 data->sfstat[3]);
2225
2226 dprintf(INFO, "%s: controller_status = %x\n", __func__,
2227 controller_status);
2228 dprintf(INFO, "%s: interrupt_status = %x\n", __func__,
2229 interrupt_status);
2230 dprintf(INFO, "%s: ecc_status = %x\n", __func__,
2231 ecc_status);
2232#endif
2233 /* Check for errors, protection violations etc */
2234 if ((controller_status != 0)
2235 || (data->sfstat[0] & 0x110)
2236 || (data->sfstat[1] & 0x110)
2237 || (data->sfstat[2] & 0x110)
2238 || (data->sfstat[3] & 0x110)) {
2239 dprintf(CRITICAL, "%s: ECC/MPU/OP error\n", __func__);
2240 return -1;
2241 }
2242
2243
2244#if VERBOSE
2245 dprintf(INFO, "status: %x\n", data[5]);
2246#endif
2247
2248 return 0;
2249}
2250
2251
2252struct data_onenand_read {
2253 unsigned sfbcfg;
2254 unsigned sfcmd[9];
2255 unsigned sfexec;
2256 unsigned sfstat[9];
2257 unsigned addr0;
2258 unsigned addr1;
2259 unsigned addr2;
2260 unsigned addr3;
2261 unsigned addr4;
2262 unsigned addr5;
2263 unsigned addr6;
2264 unsigned data0;
2265 unsigned data1;
2266 unsigned data2;
2267 unsigned data3;
2268 unsigned data4;
2269 unsigned data5;
2270 unsigned data6;
2271 unsigned macro[5];
2272};
2273
2274
2275static int _flash_onenand_read_page(dmov_s *cmdlist, unsigned *ptrlist,
Shashank Mittalad3d05c2009-11-19 15:53:57 -08002276 unsigned page, void *_addr, void *_spareaddr,
2277 unsigned raw_mode)
Shashank Mittalc20b5a12009-11-18 19:35:30 -08002278{
2279 dmov_s *cmd = cmdlist;
2280 unsigned *ptr = ptrlist;
2281 struct data_onenand_read *data = (void*) (ptrlist + 4);
2282 unsigned addr = (unsigned) _addr;
2283 unsigned curr_addr = (unsigned) _addr;
2284 unsigned spareaddr = (unsigned) _spareaddr;
2285 unsigned i;
Channagoud Kadabibeb17d52011-03-25 17:14:00 +05302286 unsigned erasesize = (flash_pagesize * num_pages_per_blk);
Shashank Mittaldcc2e352009-11-19 19:11:16 -08002287 unsigned writesize = flash_pagesize;
Shashank Mittalc20b5a12009-11-18 19:35:30 -08002288
2289 unsigned onenand_startaddr1 = DEVICE_FLASHCORE_0 |
Shashank Mittaldcc2e352009-11-19 19:11:16 -08002290 ((unsigned)(page * flash_pagesize) / erasesize);
2291 unsigned onenand_startaddr8 = (((unsigned)(page * flash_pagesize) &
Shashank Mittalc20b5a12009-11-18 19:35:30 -08002292 (erasesize - 1)) / writesize) << 2;
2293 unsigned onenand_startaddr2 = DEVICE_BUFFERRAM_0 << 15;
2294 unsigned onenand_startbuffer = DATARAM0_0 << 8;
Shashank Mittalad3d05c2009-11-19 15:53:57 -08002295 unsigned onenand_sysconfig1 = (raw_mode == 1) ? ONENAND_SYSCFG1_ECCDIS :\
2296 ONENAND_SYSCFG1_ECCENA;
Shashank Mittalc20b5a12009-11-18 19:35:30 -08002297
2298 unsigned controller_status;
2299 unsigned interrupt_status;
2300 unsigned ecc_status;
Shashank Mittalad3d05c2009-11-19 15:53:57 -08002301 if (raw_mode != 1)
2302 {
2303 int isbad = 0;
2304 isbad = flash_onenand_block_isbad(cmdlist, ptrlist, page);
2305 if (isbad)
2306 return -2;
2307 }
Shashank Mittalc20b5a12009-11-18 19:35:30 -08002308
2309 //static int oobfree_offset[8] = {2, 14, 18, 30, 34, 46, 50, 62};
2310 //static int oobfree_length[8] = {3, 2, 3, 2, 3, 2, 3, 2};
2311
2312 data->sfbcfg = SFLASH_BCFG;
2313 data->sfcmd[0] = SFLASH_PREPCMD(7, 0, 0,
2314 NAND_SFCMD_CMDXS,
2315 NAND_SFCMD_ASYNC,
2316 NAND_SFCMD_REGWR);
2317 data->sfcmd[1] = SFLASH_PREPCMD(0, 0, 32,
2318 NAND_SFCMD_CMDXS,
2319 NAND_SFCMD_ASYNC,
2320 NAND_SFCMD_INTHI);
2321 data->sfcmd[2] = SFLASH_PREPCMD(3, 7, 0,
2322 NAND_SFCMD_DATXS,
2323 NAND_SFCMD_ASYNC,
2324 NAND_SFCMD_REGRD);
2325 data->sfcmd[3] = SFLASH_PREPCMD(256, 0, 0,
2326 NAND_SFCMD_DATXS,
2327 NAND_SFCMD_ASYNC,
2328 NAND_SFCMD_DATRD);
2329 data->sfcmd[4] = SFLASH_PREPCMD(256, 0, 0,
2330 NAND_SFCMD_DATXS,
2331 NAND_SFCMD_ASYNC,
2332 NAND_SFCMD_DATRD);
2333 data->sfcmd[5] = SFLASH_PREPCMD(256, 0, 0,
2334 NAND_SFCMD_DATXS,
2335 NAND_SFCMD_ASYNC,
2336 NAND_SFCMD_DATRD);
2337 data->sfcmd[6] = SFLASH_PREPCMD(256, 0, 0,
2338 NAND_SFCMD_DATXS,
2339 NAND_SFCMD_ASYNC,
2340 NAND_SFCMD_DATRD);
2341 data->sfcmd[7] = SFLASH_PREPCMD(32, 0, 0,
2342 NAND_SFCMD_DATXS,
2343 NAND_SFCMD_ASYNC,
2344 NAND_SFCMD_DATRD);
2345 data->sfcmd[8] = SFLASH_PREPCMD(4, 10, 0,
2346 NAND_SFCMD_CMDXS,
2347 NAND_SFCMD_ASYNC,
2348 NAND_SFCMD_REGWR);
2349 data->sfexec = 1;
2350 data->sfstat[0] = CLEAN_DATA_32;
2351 data->sfstat[1] = CLEAN_DATA_32;
2352 data->sfstat[2] = CLEAN_DATA_32;
2353 data->sfstat[3] = CLEAN_DATA_32;
2354 data->sfstat[4] = CLEAN_DATA_32;
2355 data->sfstat[5] = CLEAN_DATA_32;
2356 data->sfstat[6] = CLEAN_DATA_32;
2357 data->sfstat[7] = CLEAN_DATA_32;
2358 data->sfstat[8] = CLEAN_DATA_32;
2359
2360 data->addr0 = (ONENAND_INTERRUPT_STATUS << 16) |
2361 (ONENAND_SYSTEM_CONFIG_1);
2362 data->addr1 = (ONENAND_START_ADDRESS_8 << 16) |
2363 (ONENAND_START_ADDRESS_1);
2364 data->addr2 = (ONENAND_START_BUFFER << 16) |
2365 (ONENAND_START_ADDRESS_2);
2366 data->addr3 = (ONENAND_ECC_STATUS << 16) |
2367 (ONENAND_COMMAND);
2368 data->addr4 = (ONENAND_CONTROLLER_STATUS << 16) |
2369 (ONENAND_INTERRUPT_STATUS);
2370 data->addr5 = (ONENAND_INTERRUPT_STATUS << 16) |
2371 (ONENAND_SYSTEM_CONFIG_1);
2372 data->addr6 = (ONENAND_START_ADDRESS_3 << 16) |
2373 (ONENAND_START_ADDRESS_1);
2374 data->data0 = (ONENAND_CLRINTR << 16) |
2375 (onenand_sysconfig1);
2376 data->data1 = (onenand_startaddr8 << 16) |
2377 (onenand_startaddr1);
2378 data->data2 = (onenand_startbuffer << 16) |
2379 (onenand_startaddr2);
2380 data->data3 = (CLEAN_DATA_16 << 16) |
2381 (ONENAND_CMDLOADSPARE);
2382 data->data4 = (CLEAN_DATA_16 << 16) |
2383 (CLEAN_DATA_16);
2384 data->data5 = (ONENAND_CLRINTR << 16) |
2385 (ONENAND_SYSCFG1_ECCENA);
2386 data->data6 = (ONENAND_STARTADDR3_RES << 16) |
2387 (ONENAND_STARTADDR1_RES);
2388 data->macro[0] = 0x0200;
2389 data->macro[1] = 0x0300;
2390 data->macro[2] = 0x0400;
2391 data->macro[3] = 0x0500;
2392 data->macro[4] = 0x8010;
2393
2394 /*************************************************************/
2395 /* Write necessary address registers in the onenand device */
2396 /*************************************************************/
2397
2398 /* Enable and configure the SFlash controller */
2399 cmd->cmd = 0 | CMD_OCB;
2400 cmd->src = paddr(&data->sfbcfg);
2401 cmd->dst = NAND_SFLASHC_BURST_CFG;
2402 cmd->len = 4;
2403 cmd++;
2404
2405 /* Block on cmd ready and write CMD register */
2406 cmd->cmd = DST_CRCI_NAND_CMD;
2407 cmd->src = paddr(&data->sfcmd[0]);
2408 cmd->dst = NAND_SFLASHC_CMD;
2409 cmd->len = 4;
2410 cmd++;
2411
2412 /* Write the ADDR0 and ADDR1 registers */
2413 cmd->cmd = 0;
2414 cmd->src = paddr(&data->addr0);
2415 cmd->dst = NAND_ADDR0;
2416 cmd->len = 8;
2417 cmd++;
2418
2419 /* Write the ADDR2 ADDR3 ADDR4 ADDR5 registers */
2420 cmd->cmd = 0;
2421 cmd->src = paddr(&data->addr2);
2422 cmd->dst = NAND_ADDR2;
2423 cmd->len = 16;
2424 cmd++;
2425
2426 /* Write the ADDR6 registers */
2427 cmd->cmd = 0;
2428 cmd->src = paddr(&data->addr6);
2429 cmd->dst = NAND_ADDR6;
2430 cmd->len = 4;
2431 cmd++;
2432
2433 /* Write the GENP0, GENP1, GENP2, GENP3 registers */
2434 cmd->cmd = 0;
2435 cmd->src = paddr(&data->data0);
2436 cmd->dst = NAND_GENP_REG0;
2437 cmd->len = 16;
2438 cmd++;
2439
2440 /* Write the FLASH_DEV_CMD4,5,6 registers */
2441 cmd->cmd = 0;
2442 cmd->src = paddr(&data->data4);
2443 cmd->dst = NAND_DEV_CMD4;
2444 cmd->len = 12;
2445 cmd++;
2446
2447 /* Kick the execute command */
2448 cmd->cmd = 0;
2449 cmd->src = paddr(&data->sfexec);
2450 cmd->dst = NAND_SFLASHC_EXEC_CMD;
2451 cmd->len = 4;
2452 cmd++;
2453
2454 /* Block on data ready, and read the status register */
2455 cmd->cmd = SRC_CRCI_NAND_DATA;
2456 cmd->src = NAND_SFLASHC_STATUS;
2457 cmd->dst = paddr(&data->sfstat[0]);
2458 cmd->len = 4;
2459 cmd++;
2460
2461 /*************************************************************/
2462 /* Wait for the interrupt from the Onenand device controller */
2463 /*************************************************************/
2464
2465 /* Block on cmd ready and write CMD register */
2466 cmd->cmd = DST_CRCI_NAND_CMD;
2467 cmd->src = paddr(&data->sfcmd[1]);
2468 cmd->dst = NAND_SFLASHC_CMD;
2469 cmd->len = 4;
2470 cmd++;
2471
2472 /* Kick the execute command */
2473 cmd->cmd = 0;
2474 cmd->src = paddr(&data->sfexec);
2475 cmd->dst = NAND_SFLASHC_EXEC_CMD;
2476 cmd->len = 4;
2477 cmd++;
2478
2479 /* Block on data ready, and read the status register */
2480 cmd->cmd = SRC_CRCI_NAND_DATA;
2481 cmd->src = NAND_SFLASHC_STATUS;
2482 cmd->dst = paddr(&data->sfstat[1]);
2483 cmd->len = 4;
2484 cmd++;
2485
2486
2487 /*************************************************************/
2488 /* Read necessary status registers from the onenand device */
2489 /*************************************************************/
2490
2491 /* Block on cmd ready and write CMD register */
2492 cmd->cmd = DST_CRCI_NAND_CMD;
2493 cmd->src = paddr(&data->sfcmd[2]);
2494 cmd->dst = NAND_SFLASHC_CMD;
2495 cmd->len = 4;
2496 cmd++;
2497
2498 /* Kick the execute command */
2499 cmd->cmd = 0;
2500 cmd->src = paddr(&data->sfexec);
2501 cmd->dst = NAND_SFLASHC_EXEC_CMD;
2502 cmd->len = 4;
2503 cmd++;
2504
2505 /* Block on data ready, and read the status register */
2506 cmd->cmd = SRC_CRCI_NAND_DATA;
2507 cmd->src = NAND_SFLASHC_STATUS;
2508 cmd->dst = paddr(&data->sfstat[2]);
2509 cmd->len = 4;
2510 cmd++;
2511
2512 /* Read the GENP3 register */
2513 cmd->cmd = 0;
2514 cmd->src = NAND_GENP_REG3;
2515 cmd->dst = paddr(&data->data3);
2516 cmd->len = 4;
2517 cmd++;
2518
2519 /* Read the DEVCMD4 register */
2520 cmd->cmd = 0;
2521 cmd->src = NAND_DEV_CMD4;
2522 cmd->dst = paddr(&data->data4);
2523 cmd->len = 4;
2524 cmd++;
2525
2526
2527 /*************************************************************/
2528 /* Read the data ram area from the onenand buffer ram */
2529 /*************************************************************/
2530
2531 if (addr) {
2532
2533 data->data3 = (CLEAN_DATA_16 << 16) |
2534 (ONENAND_CMDLOAD);
2535
2536 for (i = 0; i < 4; i++) {
2537
2538 /* Block on cmd ready and write CMD register */
2539 cmd->cmd = DST_CRCI_NAND_CMD;
2540 cmd->src = paddr(&data->sfcmd[3+i]);
2541 cmd->dst = NAND_SFLASHC_CMD;
2542 cmd->len = 4;
2543 cmd++;
2544
2545 /* Write the MACRO1 register */
2546 cmd->cmd = 0;
2547 cmd->src = paddr(&data->macro[i]);
2548 cmd->dst = NAND_MACRO1_REG;
2549 cmd->len = 4;
2550 cmd++;
2551
2552 /* Kick the execute command */
2553 cmd->cmd = 0;
2554 cmd->src = paddr(&data->sfexec);
2555 cmd->dst = NAND_SFLASHC_EXEC_CMD;
2556 cmd->len = 4;
2557 cmd++;
2558
2559 /* Block on data rdy, & read status register */
2560 cmd->cmd = SRC_CRCI_NAND_DATA;
2561 cmd->src = NAND_SFLASHC_STATUS;
2562 cmd->dst = paddr(&data->sfstat[3+i]);
2563 cmd->len = 4;
2564 cmd++;
2565
2566 /* Transfer nand ctlr buf contents to usr buf */
2567 cmd->cmd = 0;
2568 cmd->src = NAND_FLASH_BUFFER;
2569 cmd->dst = curr_addr;
2570 cmd->len = 512;
2571 curr_addr += 512;
2572 cmd++;
2573 }
2574 }
2575
Shashank Mittalad3d05c2009-11-19 15:53:57 -08002576 /* Read oob bytes in Raw Mode */
2577 if (raw_mode == 1)
2578 {
2579 /* Block on cmd ready and write CMD register */
2580 cmd->cmd = DST_CRCI_NAND_CMD;
2581 cmd->src = paddr(&data->sfcmd[7]);
2582 cmd->dst = NAND_SFLASHC_CMD;
2583 cmd->len = 4;
2584 cmd++;
2585
2586 /* Write the MACRO1 register */
2587 cmd->cmd = 0;
2588 cmd->src = paddr(&data->macro[4]);
2589 cmd->dst = NAND_MACRO1_REG;
2590 cmd->len = 4;
2591 cmd++;
2592
2593 /* Kick the execute command */
2594 cmd->cmd = 0;
2595 cmd->src = paddr(&data->sfexec);
2596 cmd->dst = NAND_SFLASHC_EXEC_CMD;
2597 cmd->len = 4;
2598 cmd++;
2599
2600 /* Block on data rdy, & read status register */
2601 cmd->cmd = SRC_CRCI_NAND_DATA;
2602 cmd->src = NAND_SFLASHC_STATUS;
2603 cmd->dst = paddr(&data->sfstat[7]);
2604 cmd->len = 4;
2605 cmd++;
2606
2607 /* Transfer nand ctlr buf contents to usr buf */
2608 cmd->cmd = 0;
2609 cmd->src = NAND_FLASH_BUFFER;
2610 cmd->dst = curr_addr;
2611 cmd->len = 64;
2612 curr_addr += 64;
2613 cmd++;
2614 }
2615
Shashank Mittalc20b5a12009-11-18 19:35:30 -08002616 /*************************************************************/
2617 /* Restore the necessary registers to proper values */
2618 /*************************************************************/
2619
2620 /* Block on cmd ready and write CMD register */
2621 cmd->cmd = DST_CRCI_NAND_CMD;
2622 cmd->src = paddr(&data->sfcmd[8]);
2623 cmd->dst = NAND_SFLASHC_CMD;
2624 cmd->len = 4;
2625 cmd++;
2626
2627 /* Kick the execute command */
2628 cmd->cmd = 0;
2629 cmd->src = paddr(&data->sfexec);
2630 cmd->dst = NAND_SFLASHC_EXEC_CMD;
2631 cmd->len = 4;
2632 cmd++;
2633
2634 /* Block on data ready, and read the status register */
2635 cmd->cmd = SRC_CRCI_NAND_DATA | CMD_OCU | CMD_LC;
2636 cmd->src = NAND_SFLASHC_STATUS;
2637 cmd->dst = paddr(&data->sfstat[8]);
2638 cmd->len = 4;
2639 cmd++;
2640
2641
2642 ptr[0] = (paddr(cmdlist) >> 3) | CMD_PTR_LP;
2643
2644 dmov_exec_cmdptr(DMOV_NAND_CHAN, ptr);
2645
2646
2647 ecc_status = (data->data3 >> 16) &
2648 0x0000FFFF;
2649 interrupt_status = (data->data4 >> 0) &
2650 0x0000FFFF;
2651 controller_status = (data->data4 >> 16) &
2652 0x0000FFFF;
2653
2654#if VERBOSE
2655 dprintf(INFO, "\n%s: sflash status %x %x %x %x %x %x %x"
2656 "%x %x\n", __func__,
2657 data->sfstat[0],
2658 data->sfstat[1],
2659 data->sfstat[2],
2660 data->sfstat[3],
2661 data->sfstat[4],
2662 data->sfstat[5],
2663 data->sfstat[6],
2664 data->sfstat[7]);
2665
2666 dprintf(INFO, "%s: controller_status = %x\n", __func__,
2667 controller_status);
2668 dprintf(INFO, "%s: interrupt_status = %x\n", __func__,
2669 interrupt_status);
2670 dprintf(INFO, "%s: ecc_status = %x\n", __func__,
2671 ecc_status);
2672#endif
2673 /* Check for errors, protection violations etc */
2674 if ((controller_status != 0)
2675 || (data->sfstat[0] & 0x110)
2676 || (data->sfstat[1] & 0x110)
2677 || (data->sfstat[2] & 0x110)
2678 || ((data->sfstat[3] & 0x110) &&
2679 (addr))
2680 || ((data->sfstat[4] & 0x110) &&
2681 (addr))
2682 || ((data->sfstat[5] & 0x110) &&
2683 (addr))
2684 || ((data->sfstat[6] & 0x110) &&
2685 (addr))) {
2686 dprintf(INFO, "%s: ECC/MPU/OP error\n", __func__);
2687 return -1;
2688 }
2689
2690#if VERBOSE
2691 dprintf(INFO, "read page %d: status: %x %x %x %x\n",
2692 page, data[5], data[6], data[7], data[8]);
2693 for(n = 0; n < 4; n++) {
2694 ptr = (unsigned*)(addr + 512 * n);
2695 dprintf(INFO, "data%d: %x %x %x %x\n", n, ptr[0], ptr[1], ptr[2], ptr[3]);
2696 ptr = (unsigned*)(spareaddr + 16 * n);
2697 dprintf(INFO, "spare data%d %x %x %x %x\n", n, ptr[0], ptr[1], ptr[2], ptr[3]);
2698 }
2699#endif
2700
2701 return 0;
2702}
2703
2704
2705struct data_onenand_write {
2706 unsigned sfbcfg;
2707 unsigned sfcmd[9];
2708 unsigned sfexec;
2709 unsigned sfstat[9];
2710 unsigned addr0;
2711 unsigned addr1;
2712 unsigned addr2;
2713 unsigned addr3;
2714 unsigned addr4;
2715 unsigned addr5;
2716 unsigned addr6;
2717 unsigned data0;
2718 unsigned data1;
2719 unsigned data2;
2720 unsigned data3;
2721 unsigned data4;
2722 unsigned data5;
2723 unsigned data6;
2724 unsigned macro[5];
2725};
2726
2727static int _flash_onenand_write_page(dmov_s *cmdlist, unsigned *ptrlist,
2728 unsigned page, const void *_addr,
Shashank Mittald0c836d2009-11-20 10:31:18 -08002729 const void *_spareaddr, unsigned raw_mode)
Shashank Mittalc20b5a12009-11-18 19:35:30 -08002730{
2731 dmov_s *cmd = cmdlist;
2732 unsigned *ptr = ptrlist;
2733 struct data_onenand_write *data = (void*) (ptrlist + 4);
2734 unsigned addr = (unsigned) _addr;
2735 unsigned addr_curr = (unsigned) _addr;
2736 char * spareaddr = (char *) _spareaddr;
2737 unsigned i, j, k;
2738
Channagoud Kadabibeb17d52011-03-25 17:14:00 +05302739 unsigned erasesize = (flash_pagesize * num_pages_per_blk);
Shashank Mittaldcc2e352009-11-19 19:11:16 -08002740 unsigned writesize = flash_pagesize;
Shashank Mittalc20b5a12009-11-18 19:35:30 -08002741
Shashank Mittaldcc2e352009-11-19 19:11:16 -08002742 unsigned onenand_startaddr1 = (page * flash_pagesize) / erasesize;
2743 unsigned onenand_startaddr8 = (((unsigned)(page * flash_pagesize) &
Shashank Mittalc20b5a12009-11-18 19:35:30 -08002744 (erasesize-1)) / writesize) << 2;
2745 unsigned onenand_startaddr2 = DEVICE_BUFFERRAM_0 << 15;
2746 unsigned onenand_startbuffer = DATARAM0_0 << 8;
Shashank Mittald0c836d2009-11-20 10:31:18 -08002747 unsigned onenand_sysconfig1 = (raw_mode == 1) ? ONENAND_SYSCFG1_ECCDIS :\
2748 ONENAND_SYSCFG1_ECCENA;
Shashank Mittalc20b5a12009-11-18 19:35:30 -08002749
2750 unsigned controller_status;
2751 unsigned interrupt_status;
2752 unsigned ecc_status;
2753
2754 char flash_oob[64];
2755
2756 unsigned oobfree_offset[8] = {2, 14, 18, 30, 34, 46, 50, 62};
2757 unsigned oobfree_length[8] = {3, 2, 3, 2, 3, 2, 3, 2};
2758
2759 for (i = 0; i < 64; i++)
2760 flash_oob[i] = 0xFF;
2761
2762 data->sfbcfg = SFLASH_BCFG;
2763 data->sfcmd[0] = SFLASH_PREPCMD(256, 0, 0,
2764 NAND_SFCMD_CMDXS,
2765 NAND_SFCMD_ASYNC,
2766 NAND_SFCMD_DATWR);
2767 data->sfcmd[1] = SFLASH_PREPCMD(256, 0, 0,
2768 NAND_SFCMD_CMDXS,
2769 NAND_SFCMD_ASYNC,
2770 NAND_SFCMD_DATWR);
2771 data->sfcmd[2] = SFLASH_PREPCMD(256, 0, 0,
2772 NAND_SFCMD_CMDXS,
2773 NAND_SFCMD_ASYNC,
2774 NAND_SFCMD_DATWR);
2775 data->sfcmd[3] = SFLASH_PREPCMD(256, 0, 0,
2776 NAND_SFCMD_CMDXS,
2777 NAND_SFCMD_ASYNC,
2778 NAND_SFCMD_DATWR);
2779 data->sfcmd[4] = SFLASH_PREPCMD(32, 0, 0,
2780 NAND_SFCMD_CMDXS,
2781 NAND_SFCMD_ASYNC,
2782 NAND_SFCMD_DATWR);
2783 data->sfcmd[5] = SFLASH_PREPCMD(7, 0, 0,
2784 NAND_SFCMD_CMDXS,
2785 NAND_SFCMD_ASYNC,
2786 NAND_SFCMD_REGWR);
2787 data->sfcmd[6] = SFLASH_PREPCMD(0, 0, 32,
2788 NAND_SFCMD_CMDXS,
2789 NAND_SFCMD_ASYNC,
2790 NAND_SFCMD_INTHI);
2791 data->sfcmd[7] = SFLASH_PREPCMD(3, 7, 0,
2792 NAND_SFCMD_DATXS,
2793 NAND_SFCMD_ASYNC,
2794 NAND_SFCMD_REGRD);
2795 data->sfcmd[8] = SFLASH_PREPCMD(4, 10, 0,
2796 NAND_SFCMD_CMDXS,
2797 NAND_SFCMD_ASYNC,
2798 NAND_SFCMD_REGWR);
2799 data->sfexec = 1;
2800
2801 data->sfstat[0] = CLEAN_DATA_32;
2802 data->sfstat[1] = CLEAN_DATA_32;
2803 data->sfstat[2] = CLEAN_DATA_32;
2804 data->sfstat[3] = CLEAN_DATA_32;
2805 data->sfstat[4] = CLEAN_DATA_32;
2806 data->sfstat[5] = CLEAN_DATA_32;
2807 data->sfstat[6] = CLEAN_DATA_32;
2808 data->sfstat[7] = CLEAN_DATA_32;
2809 data->sfstat[8] = CLEAN_DATA_32;
2810 data->addr0 = (ONENAND_INTERRUPT_STATUS << 16) |
2811 (ONENAND_SYSTEM_CONFIG_1);
2812 data->addr1 = (ONENAND_START_ADDRESS_8 << 16) |
2813 (ONENAND_START_ADDRESS_1);
2814 data->addr2 = (ONENAND_START_BUFFER << 16) |
2815 (ONENAND_START_ADDRESS_2);
2816 data->addr3 = (ONENAND_ECC_STATUS << 16) |
2817 (ONENAND_COMMAND);
2818 data->addr4 = (ONENAND_CONTROLLER_STATUS << 16) |
2819 (ONENAND_INTERRUPT_STATUS);
2820 data->addr5 = (ONENAND_INTERRUPT_STATUS << 16) |
2821 (ONENAND_SYSTEM_CONFIG_1);
2822 data->addr6 = (ONENAND_START_ADDRESS_3 << 16) |
2823 (ONENAND_START_ADDRESS_1);
2824 data->data0 = (ONENAND_CLRINTR << 16) |
2825 (onenand_sysconfig1);
2826 data->data1 = (onenand_startaddr8 << 16) |
2827 (onenand_startaddr1);
2828 data->data2 = (onenand_startbuffer << 16) |
2829 (onenand_startaddr2);
2830 data->data3 = (CLEAN_DATA_16 << 16) |
2831 (ONENAND_CMDPROGSPARE);
2832 data->data3 = (CLEAN_DATA_16 << 16) |
2833 (ONENAND_CMDPROGSPARE);
2834 data->data4 = (CLEAN_DATA_16 << 16) |
2835 (CLEAN_DATA_16);
2836 data->data5 = (ONENAND_CLRINTR << 16) |
2837 (ONENAND_SYSCFG1_ECCENA);
2838 data->data6 = (ONENAND_STARTADDR3_RES << 16) |
2839 (ONENAND_STARTADDR1_RES);
2840 data->macro[0] = 0x0200;
2841 data->macro[1] = 0x0300;
2842 data->macro[2] = 0x0400;
2843 data->macro[3] = 0x0500;
2844 data->macro[4] = 0x8010;
2845
2846
2847 /*************************************************************/
2848 /* Write the data ram area in the onenand buffer ram */
2849 /*************************************************************/
2850
2851 /* Enable and configure the SFlash controller */
2852 cmd->cmd = 0 | CMD_OCB;
2853 cmd->src = paddr(&data->sfbcfg);
2854 cmd->dst = NAND_SFLASHC_BURST_CFG;
2855 cmd->len = 4;
2856 cmd++;
2857
2858 if (addr) {
2859 data->data3 = (CLEAN_DATA_16 << 16) |
2860 (ONENAND_CMDPROG);
2861
2862 for (i = 0; i < 4; i++) {
2863
2864 /* Block on cmd ready and write CMD register */
2865 cmd->cmd = DST_CRCI_NAND_CMD;
2866 cmd->src = paddr(&data->sfcmd[i]);
2867 cmd->dst = NAND_SFLASHC_CMD;
2868 cmd->len = 4;
2869 cmd++;
2870
2871 /* Trnsfr usr buf contents to nand ctlr buf */
2872 cmd->cmd = 0;
2873 cmd->src = paddr(addr_curr);
2874 cmd->dst = NAND_FLASH_BUFFER;
2875 cmd->len = 512;
Shashank Mittald0c836d2009-11-20 10:31:18 -08002876 if(!raw_mode)
2877 addr_curr += 512;
Shashank Mittalc20b5a12009-11-18 19:35:30 -08002878 cmd++;
2879
2880 /* Write the MACRO1 register */
2881 cmd->cmd = 0;
2882 cmd->src = paddr(&data->macro[i]);
2883 cmd->dst = NAND_MACRO1_REG;
2884 cmd->len = 4;
2885 cmd++;
2886
2887 /* Kick the execute command */
2888 cmd->cmd = 0;
2889 cmd->src = paddr(&data->sfexec);
2890 cmd->dst = NAND_SFLASHC_EXEC_CMD;
2891 cmd->len = 4;
2892 cmd++;
2893
2894 /* Block on data rdy, & read status register */
2895 cmd->cmd = SRC_CRCI_NAND_DATA;
2896 cmd->src = NAND_SFLASHC_STATUS;
2897 cmd->dst = paddr(&data->sfstat[i]);
2898 cmd->len = 4;
2899 cmd++;
2900
2901 }
2902 }
2903
2904 /* Block on cmd ready and write CMD register */
2905 cmd->cmd = DST_CRCI_NAND_CMD;
2906 cmd->src = paddr(&data->sfcmd[4]);
2907 cmd->dst = NAND_SFLASHC_CMD;
2908 cmd->len = 4;
2909 cmd++;
2910
2911 if (spareaddr)
2912 {
2913 // Auto mode
2914 for (i = 0, k = 0; i < 8; i++) {
2915 for (j = 0; j < oobfree_length[i]; j++) {
2916 flash_oob[j+oobfree_offset[i]] = spareaddr[k];
2917 k++;
2918 }
2919 }
2920
2921 cmd->cmd = 0;
2922 cmd->src = paddr(&flash_oob);
2923 cmd->dst = NAND_FLASH_BUFFER;
2924 cmd->len = 64;
2925 cmd++;
2926 }
2927
Shashank Mittald0c836d2009-11-20 10:31:18 -08002928 if (raw_mode){
2929 cmd->cmd = 0;
2930 cmd->src = paddr(addr_curr);
2931 cmd->dst = NAND_FLASH_BUFFER;
2932 cmd->len = 64;
2933 cmd++;
2934 }
2935
Shashank Mittalc20b5a12009-11-18 19:35:30 -08002936 /* Write the MACRO1 register */
2937 cmd->cmd = 0;
2938 cmd->src = paddr(&data->macro[4]);
2939 cmd->dst = NAND_MACRO1_REG;
2940 cmd->len = 4;
2941 cmd++;
2942
2943 /* Kick the execute command */
2944 cmd->cmd = 0;
2945 cmd->src = paddr(&data->sfexec);
2946 cmd->dst = NAND_SFLASHC_EXEC_CMD;
2947 cmd->len = 4;
2948 cmd++;
2949
2950 /* Block on data ready, and read the status register */
2951 cmd->cmd = SRC_CRCI_NAND_DATA;
2952 cmd->src = NAND_SFLASHC_STATUS;
2953 cmd->dst = paddr(&data->sfstat[4]);
2954 cmd->len = 4;
2955 cmd++;
2956
2957 /*************************************************************/
2958 /* Write necessary address registers in the onenand device */
2959 /*************************************************************/
2960
2961 /* Block on cmd ready and write CMD register */
2962 cmd->cmd = DST_CRCI_NAND_CMD;
2963 cmd->src = paddr(&data->sfcmd[5]);
2964 cmd->dst = NAND_SFLASHC_CMD;
2965 cmd->len = 4;
2966 cmd++;
2967
2968 /* Write the ADDR0 and ADDR1 registers */
2969 cmd->cmd = 0;
2970 cmd->src = paddr(&data->addr0);
2971 cmd->dst = NAND_ADDR0;
2972 cmd->len = 8;
2973 cmd++;
2974
2975 /* Write the ADDR2 ADDR3 ADDR4 ADDR5 registers */
2976 cmd->cmd = 0;
2977 cmd->src = paddr(&data->addr2);
2978 cmd->dst = NAND_ADDR2;
2979 cmd->len = 16;
2980 cmd++;
2981
2982 /* Write the ADDR6 registers */
2983 cmd->cmd = 0;
2984 cmd->src = paddr(&data->addr6);
2985 cmd->dst = NAND_ADDR6;
2986 cmd->len = 4;
2987 cmd++;
2988
2989 /* Write the GENP0, GENP1, GENP2, GENP3 registers */
2990 cmd->cmd = 0;
2991 cmd->src = paddr(&data->data0);
2992 cmd->dst = NAND_GENP_REG0;
2993 cmd->len = 16;
2994 cmd++;
2995
2996 /* Write the FLASH_DEV_CMD4,5,6 registers */
2997 cmd->cmd = 0;
2998 cmd->src = paddr(&data->data4);
2999 cmd->dst = NAND_DEV_CMD4;
3000 cmd->len = 12;
3001 cmd++;
3002
3003 /* Kick the execute command */
3004 cmd->cmd = 0;
3005 cmd->src = paddr(&data->sfexec);
3006 cmd->dst = NAND_SFLASHC_EXEC_CMD;
3007 cmd->len = 4;
3008 cmd++;
3009
3010 /* Block on data ready, and read the status register */
3011 cmd->cmd = SRC_CRCI_NAND_DATA;
3012 cmd->src = NAND_SFLASHC_STATUS;
3013 cmd->dst = paddr(&data->sfstat[5]);
3014 cmd->len = 4;
3015 cmd++;
3016
3017 /*************************************************************/
3018 /* Wait for the interrupt from the Onenand device controller */
3019 /*************************************************************/
3020
3021 /* Block on cmd ready and write CMD register */
3022 cmd->cmd = DST_CRCI_NAND_CMD;
3023 cmd->src = paddr(&data->sfcmd[6]);
3024 cmd->dst = NAND_SFLASHC_CMD;
3025 cmd->len = 4;
3026 cmd++;
3027
3028 /* Kick the execute command */
3029 cmd->cmd = 0;
3030 cmd->src = paddr(&data->sfexec);
3031 cmd->dst = NAND_SFLASHC_EXEC_CMD;
3032 cmd->len = 4;
3033 cmd++;
3034
3035 /* Block on data ready, and read the status register */
3036 cmd->cmd = SRC_CRCI_NAND_DATA;
3037 cmd->src = NAND_SFLASHC_STATUS;
3038 cmd->dst = paddr(&data->sfstat[6]);
3039 cmd->len = 4;
3040 cmd++;
3041
3042 /*************************************************************/
3043 /* Read necessary status registers from the onenand device */
3044 /*************************************************************/
3045
3046 /* Block on cmd ready and write CMD register */
3047 cmd->cmd = DST_CRCI_NAND_CMD;
3048 cmd->src = paddr(&data->sfcmd[7]);
3049 cmd->dst = NAND_SFLASHC_CMD;
3050 cmd->len = 4;
3051 cmd++;
3052
3053 /* Kick the execute command */
3054 cmd->cmd = 0;
3055 cmd->src = paddr(&data->sfexec);
3056 cmd->dst = NAND_SFLASHC_EXEC_CMD;
3057 cmd->len = 4;
3058 cmd++;
3059
3060 /* Block on data ready, and read the status register */
3061 cmd->cmd = SRC_CRCI_NAND_DATA;
3062 cmd->src = NAND_SFLASHC_STATUS;
3063 cmd->dst = paddr(&data->sfstat[7]);
3064 cmd->len = 4;
3065 cmd++;
3066
3067 /* Read the GENP3 register */
3068 cmd->cmd = 0;
3069 cmd->src = NAND_GENP_REG3;
3070 cmd->dst = paddr(&data->data3);
3071 cmd->len = 4;
3072 cmd++;
3073
3074 /* Read the DEVCMD4 register */
3075 cmd->cmd = 0;
3076 cmd->src = NAND_DEV_CMD4;
3077 cmd->dst = paddr(&data->data4);
3078 cmd->len = 4;
3079 cmd++;
3080
3081
3082 /*************************************************************/
3083 /* Restore the necessary registers to proper values */
3084 /*************************************************************/
3085
3086 /* Block on cmd ready and write CMD register */
3087 cmd->cmd = DST_CRCI_NAND_CMD;
3088 cmd->src = paddr(&data->sfcmd[8]);
3089 cmd->dst = NAND_SFLASHC_CMD;
3090 cmd->len = 4;
3091 cmd++;
3092
3093 /* Kick the execute command */
3094 cmd->cmd = 0;
3095 cmd->src = paddr(&data->sfexec);
3096 cmd->dst = NAND_SFLASHC_EXEC_CMD;
3097 cmd->len = 4;
3098 cmd++;
3099
3100 /* Block on data ready, and read the status register */
3101 cmd->cmd = SRC_CRCI_NAND_DATA | CMD_OCU | CMD_LC;
3102 cmd->src = NAND_SFLASHC_STATUS;
3103 cmd->dst = paddr(&data->sfstat[8]);
3104 cmd->len = 4;
3105 cmd++;
3106
3107
3108 ptr[0] = (paddr(cmdlist) >> 3) | CMD_PTR_LP;
3109
3110 dmov_exec_cmdptr(DMOV_NAND_CHAN, ptr);
3111
3112 ecc_status = (data->data3 >> 16) & 0x0000FFFF;
3113 interrupt_status = (data->data4 >> 0)&0x0000FFFF;
3114 controller_status = (data->data4 >> 16)&0x0000FFFF;
3115
3116#if VERBOSE
3117 dprintf(INFO, "\n%s: sflash status %x %x %x %x %x %x %x %x %x\n", __func__,
3118 data->sfstat[0],
3119 data->sfstat[1],
3120 data->sfstat[2],
3121 data->sfstat[3],
3122 data->sfstat[4],
3123 data->sfstat[5],
3124 data->sfstat[6],
3125 data->sfstat[7],
3126 data->sfstat[8]);
3127
3128 dprintf(INFO, "%s: controller_status = %x\n", __func__,
3129 controller_status);
3130 dprintf(INFO, "%s: interrupt_status = %x\n", __func__,
3131 interrupt_status);
3132 dprintf(INFO, "%s: ecc_status = %x\n", __func__,
3133 ecc_status);
3134#endif
3135 /* Check for errors, protection violations etc */
3136 if ((controller_status != 0)
3137 || (data->sfstat[5] & 0x110)
3138 || (data->sfstat[6] & 0x110)
3139 || (data->sfstat[7] & 0x110)
3140 || (data->sfstat[8] & 0x110)
3141 || ((data->sfstat[0] & 0x110) &&
3142 (addr))
3143 || ((data->sfstat[1] & 0x110) &&
3144 (addr))
3145 || ((data->sfstat[2] & 0x110) &&
3146 (addr))
3147 || ((data->sfstat[3] & 0x110) &&
3148 (addr))) {
3149 dprintf(CRITICAL, "%s: ECC/MPU/OP error\n", __func__);
3150 return -1;
3151 }
3152
3153
3154 return 0;
3155}
Shashank Mittald0c836d2009-11-20 10:31:18 -08003156
3157static int flash_onenand_mark_badblock(dmov_s *cmdlist, unsigned *ptrlist, unsigned page)
3158{
3159 memset(empty_buf,0,528);
3160 /* Going to first page of the block */
Channagoud Kadabibeb17d52011-03-25 17:14:00 +05303161 if(page & num_pages_per_blk_mask)
3162 page = page - (page & num_pages_per_blk_mask);
Shashank Mittald0c836d2009-11-20 10:31:18 -08003163 return _flash_onenand_write_page(cmdlist, ptrlist, page, empty_buf, 0, 1);
3164}
3165
3166static int flash_mark_badblock(dmov_s *cmdlist, unsigned *ptrlist, unsigned page)
3167{
3168 switch(flash_info.type) {
3169 case FLASH_8BIT_NAND_DEVICE:
3170 case FLASH_16BIT_NAND_DEVICE:
3171 return flash_nand_mark_badblock(cmdlist, ptrlist, page);
3172 case FLASH_ONENAND_DEVICE:
3173 return flash_onenand_mark_badblock(cmdlist, ptrlist, page);
3174 default:
3175 return -1;
3176 }
3177}
3178
3179
Channagoud Kadabi404a7062011-03-21 19:27:50 +05303180unsigned flash_ctrl_hwinfo(dmov_s *cmdlist, unsigned *ptrlist)
3181{
3182 dmov_s *cmd = cmdlist;
3183 unsigned *ptr = ptrlist;
3184 unsigned *data = ptrlist + 4;
3185
3186 unsigned rv;
3187
3188 data[0] = 0xeeeeeeee;
3189 data[1] = 1;
3190
3191 cmd[0].cmd = CMD_OCB;
3192 cmd[0].src = NAND_HW_INFO;
3193 cmd[0].dst = paddr(&data[0]);
3194 cmd[0].len = 4;
3195
3196 cmd[1].cmd = CMD_OCU | CMD_LC;
3197 cmd[1].src = paddr(&data[1]);
3198 cmd[1].dst = NAND_EXEC_CMD;
3199 cmd[1].len = 4;
3200
3201 ptr[0] = (paddr(cmd) >> 3) | CMD_PTR_LP;
3202 dmov_exec_cmdptr(DMOV_NAND_CHAN, ptr);
3203 rv = data[0];
3204
3205 return rv;
3206}
3207
Shashank Mittalc20b5a12009-11-18 19:35:30 -08003208/* Wrapper functions */
3209static void flash_read_id(dmov_s *cmdlist, unsigned *ptrlist)
3210{
3211 int dev_found = 0;
3212 unsigned index;
3213
3214 // Try to read id
3215 flash_nand_read_id(cmdlist, ptrlist);
3216 // Check if we support the device
3217 for (index=1;
3218 index < (sizeof(supported_flash)/sizeof(struct flash_identification));
3219 index++)
3220 {
3221 if ((flash_info.id & supported_flash[index].mask) ==
3222 (supported_flash[index].flash_id &
3223 (supported_flash[index].mask))) {
3224 dev_found = 1;
3225 break;
3226 }
3227 }
3228
3229 if(!dev_found) {
3230 flash_onenand_read_id(cmdlist, ptrlist);
3231 for (index=1;
3232 index < (sizeof(supported_flash)/sizeof(struct flash_identification));
3233 index++)
3234 {
3235 if ((flash_info.id & supported_flash[index].mask) ==
3236 (supported_flash[index].flash_id &
3237 (supported_flash[index].mask))) {
3238 dev_found = 1;
3239 break;
3240 }
3241 }
3242 }
3243
3244
3245
3246 if(dev_found) {
3247 if (supported_flash[index].widebus)
3248 flash_info.type = FLASH_16BIT_NAND_DEVICE;
3249 else
3250 flash_info.type = FLASH_8BIT_NAND_DEVICE;
3251 if (supported_flash[index].onenand)
3252 flash_info.type = FLASH_ONENAND_DEVICE;
3253 flash_info.page_size = supported_flash[index].pagesize;
Shashank Mittaldcc2e352009-11-19 19:11:16 -08003254 flash_pagesize = flash_info.page_size;
Shashank Mittalc20b5a12009-11-18 19:35:30 -08003255 flash_info.block_size = supported_flash[index].blksize;
3256 flash_info.spare_size = supported_flash[index].oobsize;
3257 if (flash_info.block_size && flash_info.page_size)
3258 {
3259 flash_info.num_blocks = supported_flash[index].density;
Chandan Uddaraju40605112010-08-09 14:25:08 -07003260 flash_info.num_blocks /= (flash_info.block_size);
Shashank Mittalc20b5a12009-11-18 19:35:30 -08003261 }
3262 else
3263 {
3264 flash_info.num_blocks = 0;
3265 }
3266 ASSERT(flash_info.num_blocks);
Channagoud Kadabibeb17d52011-03-25 17:14:00 +05303267 // Use this for getting the next/current blocks
3268 num_pages_per_blk = flash_info.block_size / flash_pagesize;
3269 num_pages_per_blk_mask = num_pages_per_blk - 1;
Channagoud Kadabi404a7062011-03-21 19:27:50 +05303270 //Look for 8bit BCH ECC Nand, TODO: ECC Correctability >= 8
3271 if((flash_ctrl_hwinfo(cmdlist,ptrlist) == 0x307) && flash_info.id == 0x2600482c) {
3272 enable_bch_ecc = 1;
3273 }
Shashank Mittalc20b5a12009-11-18 19:35:30 -08003274 return;
3275 }
3276
3277 // Assume 8 bit nand device for backward compatability
3278 if (dev_found == 0) {
3279 dprintf(INFO, "Device not supported. Assuming 8 bit NAND device\n");
3280 flash_info.type = FLASH_8BIT_NAND_DEVICE;
3281 }
3282 dprintf(INFO, "nandid: 0x%x maker=0x%02x device=0x%02x page_size=%d\n",
3283 flash_info.id, flash_info.vendor, flash_info.device,
3284 flash_info.page_size);
3285 dprintf(INFO, " spare_size=%d block_size=%d num_blocks=%d\n",
3286 flash_info.spare_size, flash_info.block_size,
3287 flash_info.num_blocks);
3288}
3289
3290static int flash_erase_block(dmov_s *cmdlist, unsigned *ptrlist, unsigned page)
3291{
3292 switch(flash_info.type) {
3293 case FLASH_8BIT_NAND_DEVICE:
3294 case FLASH_16BIT_NAND_DEVICE:
3295 return flash_nand_erase_block(cmdlist, ptrlist, page);
3296 case FLASH_ONENAND_DEVICE:
3297 return flash_onenand_erase_block(cmdlist, ptrlist, page);
3298 default:
3299 return -1;
3300 }
3301}
3302
3303static int _flash_read_page(dmov_s *cmdlist, unsigned *ptrlist,
3304 unsigned page, void *_addr, void *_spareaddr)
3305{
3306 switch(flash_info.type) {
3307 case FLASH_8BIT_NAND_DEVICE:
3308 case FLASH_16BIT_NAND_DEVICE:
Chandan Uddaraju14e57eb2010-06-28 12:11:06 -07003309 if(interleaved_mode)
3310 return flash_nand_read_page_interleave(cmdlist, ptrlist, page, _addr, _spareaddr);
3311 else
Shashank Mittalc20b5a12009-11-18 19:35:30 -08003312 return _flash_nand_read_page(cmdlist, ptrlist, page, _addr, _spareaddr);
3313 case FLASH_ONENAND_DEVICE:
Shashank Mittalad3d05c2009-11-19 15:53:57 -08003314 return _flash_onenand_read_page(cmdlist, ptrlist, page, _addr, _spareaddr, 0);
Shashank Mittalc20b5a12009-11-18 19:35:30 -08003315 default:
3316 return -1;
3317 }
3318}
3319
Shashank Mittalad3d05c2009-11-19 15:53:57 -08003320static int _flash_block_isbad(dmov_s *cmdlist, unsigned *ptrlist, unsigned page)
3321{
3322 switch(flash_info.type) {
3323 case FLASH_8BIT_NAND_DEVICE:
3324 case FLASH_16BIT_NAND_DEVICE:
3325 return flash_nand_block_isbad(cmdlist, ptrlist, page);
3326 case FLASH_ONENAND_DEVICE:
3327 return flash_onenand_block_isbad(cmdlist, ptrlist, page);
3328 default:
3329 return -1;
3330 }
3331}
Shashank Mittalc20b5a12009-11-18 19:35:30 -08003332
3333static int _flash_write_page(dmov_s *cmdlist, unsigned *ptrlist,
3334 unsigned page, const void *_addr,
3335 const void *_spareaddr)
3336{
3337 switch(flash_info.type) {
3338 case FLASH_8BIT_NAND_DEVICE:
3339 case FLASH_16BIT_NAND_DEVICE:
Chandan Uddaraju14e57eb2010-06-28 12:11:06 -07003340 if(interleaved_mode)
3341 return flash_nand_write_page_interleave(cmdlist, ptrlist, page, _addr, _spareaddr, 0);
3342 else
Shashank Mittald0c836d2009-11-20 10:31:18 -08003343 return _flash_nand_write_page(cmdlist, ptrlist, page, _addr, _spareaddr, 0);
Shashank Mittalc20b5a12009-11-18 19:35:30 -08003344 case FLASH_ONENAND_DEVICE:
Shashank Mittald0c836d2009-11-20 10:31:18 -08003345 return _flash_onenand_write_page(cmdlist, ptrlist, page, _addr, _spareaddr, 0);
Shashank Mittalc20b5a12009-11-18 19:35:30 -08003346 default:
3347 return -1;
3348 }
3349}
3350
Dima Zavin03cf4312009-01-23 16:38:30 -08003351static unsigned *flash_ptrlist;
3352static dmov_s *flash_cmdlist;
Dima Zavin03cf4312009-01-23 16:38:30 -08003353
3354static struct ptable *flash_ptable = NULL;
3355
Dima Zavine5f64352009-03-02 16:04:20 -08003356void flash_init(void)
Dima Zavin03cf4312009-01-23 16:38:30 -08003357{
Dima Zavine5f64352009-03-02 16:04:20 -08003358 ASSERT(flash_ptable == NULL);
Dima Zavin03cf4312009-01-23 16:38:30 -08003359
3360 flash_ptrlist = memalign(32, 1024);
3361 flash_cmdlist = memalign(32, 1024);
Ajay Dudani232ce812009-12-02 00:14:11 -08003362 flash_data = memalign(32, 4096 + 128);
3363 flash_spare = memalign(32, 128);
Dima Zavin03cf4312009-01-23 16:38:30 -08003364
Dima Zavin03cf4312009-01-23 16:38:30 -08003365 flash_read_id(flash_cmdlist, flash_ptrlist);
Shashank Mittal83d16d02009-11-18 16:54:42 -08003366 if((FLASH_8BIT_NAND_DEVICE == flash_info.type)
3367 ||(FLASH_16BIT_NAND_DEVICE == flash_info.type)) {
Shashank Mittalc20b5a12009-11-18 19:35:30 -08003368 if(flash_nand_read_config(flash_cmdlist, flash_ptrlist)) {
Shashank Mittal83d16d02009-11-18 16:54:42 -08003369 dprintf(CRITICAL, "ERROR: could not read CFG0/CFG1 state\n");
3370 ASSERT(0);
3371 }
3372 }
Dima Zavin03cf4312009-01-23 16:38:30 -08003373}
3374
3375struct ptable *flash_get_ptable(void)
3376{
3377 return flash_ptable;
3378}
3379
Dima Zavine5f64352009-03-02 16:04:20 -08003380void flash_set_ptable(struct ptable *new_ptable)
3381{
3382 ASSERT(flash_ptable == NULL && new_ptable != NULL);
3383 flash_ptable = new_ptable;
3384}
3385
Dima Zavinca337f52009-03-02 16:41:44 -08003386struct flash_info *flash_get_info(void)
3387{
3388 return &flash_info;
3389}
3390
Dima Zavin03cf4312009-01-23 16:38:30 -08003391int flash_erase(struct ptentry *ptn)
3392{
3393 unsigned block = ptn->start;
3394 unsigned count = ptn->length;
3395
Shashank Mittal8e49dec2010-03-01 15:19:04 -08003396 set_nand_configuration(ptn->type);
Dima Zavin03cf4312009-01-23 16:38:30 -08003397 while(count-- > 0) {
Channagoud Kadabibeb17d52011-03-25 17:14:00 +05303398 if(flash_erase_block(flash_cmdlist, flash_ptrlist, block * num_pages_per_blk)) {
Dima Zavin03cf4312009-01-23 16:38:30 -08003399 dprintf(INFO, "cannot erase @ %d (bad block?)\n", block);
3400 }
3401 block++;
3402 }
3403 return 0;
3404}
3405
3406int flash_read_ext(struct ptentry *ptn, unsigned extra_per_page,
Shashank Mittalc20b5a12009-11-18 19:35:30 -08003407 unsigned offset, void *data, unsigned bytes)
Dima Zavin03cf4312009-01-23 16:38:30 -08003408{
Channagoud Kadabibeb17d52011-03-25 17:14:00 +05303409 unsigned page = (ptn->start * num_pages_per_blk) + (offset / flash_pagesize);
3410 unsigned lastpage = (ptn->start + ptn->length) * num_pages_per_blk;
Shashank Mittaldcc2e352009-11-19 19:11:16 -08003411 unsigned count = (bytes + flash_pagesize - 1 + extra_per_page) / (flash_pagesize + extra_per_page);
Dima Zavin03cf4312009-01-23 16:38:30 -08003412 unsigned *spare = (unsigned*) flash_spare;
3413 unsigned errors = 0;
3414 unsigned char *image = data;
Channagoud Kadabibeb17d52011-03-25 17:14:00 +05303415 unsigned current_block = (page - (page & num_pages_per_blk_mask)) / num_pages_per_blk;
Shashank Mittalad3d05c2009-11-19 15:53:57 -08003416 unsigned start_block = ptn->start;
3417 int result = 0;
3418 int isbad = 0;
Shashank Mittalfd1f04f2010-08-03 17:38:48 -07003419 int start_block_count = 0;
Dima Zavin03cf4312009-01-23 16:38:30 -08003420
Shashank Mittal8e49dec2010-03-01 15:19:04 -08003421 ASSERT(ptn->type == TYPE_APPS_PARTITION);
3422 set_nand_configuration(TYPE_APPS_PARTITION);
3423
Shashank Mittaldcc2e352009-11-19 19:11:16 -08003424 if(offset & (flash_pagesize - 1))
Dima Zavin03cf4312009-01-23 16:38:30 -08003425 return -1;
3426
Shashank Mittalfd1f04f2010-08-03 17:38:48 -07003427// Adjust page offset based on number of bad blocks from start to current page
3428 if (start_block < current_block)
3429 {
3430 start_block_count = (current_block - start_block);
3431 while (start_block_count && (start_block < (ptn->start + ptn->length))) {
Channagoud Kadabibeb17d52011-03-25 17:14:00 +05303432 isbad = _flash_block_isbad(flash_cmdlist, flash_ptrlist, start_block*num_pages_per_blk);
Shashank Mittalfd1f04f2010-08-03 17:38:48 -07003433 if (isbad)
Channagoud Kadabibeb17d52011-03-25 17:14:00 +05303434 page += num_pages_per_blk;
Shashank Mittalfd1f04f2010-08-03 17:38:48 -07003435 else
3436 start_block_count--;
3437 start_block++;
3438 }
Shashank Mittalad3d05c2009-11-19 15:53:57 -08003439 }
3440
Shashank Mittalfd1f04f2010-08-03 17:38:48 -07003441 while((page < lastpage) && !start_block_count) {
Dima Zavin03cf4312009-01-23 16:38:30 -08003442 if(count == 0) {
3443 dprintf(INFO, "flash_read_image: success (%d errors)\n", errors);
3444 return 0;
3445 }
3446
Shashank Mittalad3d05c2009-11-19 15:53:57 -08003447 result = _flash_read_page(flash_cmdlist, flash_ptrlist, page, image, spare);
3448
3449 if (result == -1) {
3450 // bad page, go to next page
3451 page++;
Dima Zavin03cf4312009-01-23 16:38:30 -08003452 errors++;
3453 continue;
3454 }
Shashank Mittalad3d05c2009-11-19 15:53:57 -08003455 else if (result == -2) {
3456 // bad block, go to next block same offset
Channagoud Kadabibeb17d52011-03-25 17:14:00 +05303457 page += num_pages_per_blk;
Shashank Mittalad3d05c2009-11-19 15:53:57 -08003458 errors++;
3459 continue;
3460 }
3461
3462 page++;
Shashank Mittaldcc2e352009-11-19 19:11:16 -08003463 image += flash_pagesize;
Dima Zavin03cf4312009-01-23 16:38:30 -08003464 memcpy(image, spare, extra_per_page);
3465 image += extra_per_page;
3466 count -= 1;
3467 }
3468
3469 /* could not find enough valid pages before we hit the end */
3470 dprintf(INFO, "flash_read_image: failed (%d errors)\n", errors);
3471 return 0xffffffff;
3472}
3473
3474int flash_write(struct ptentry *ptn, unsigned extra_per_page, const void *data,
3475 unsigned bytes)
3476{
Channagoud Kadabibeb17d52011-03-25 17:14:00 +05303477 unsigned page = ptn->start * num_pages_per_blk;
3478 unsigned lastpage = (ptn->start + ptn->length) * num_pages_per_blk;
Dima Zavin03cf4312009-01-23 16:38:30 -08003479 unsigned *spare = (unsigned*) flash_spare;
3480 const unsigned char *image = data;
Shashank Mittaldcc2e352009-11-19 19:11:16 -08003481 unsigned wsize = flash_pagesize + extra_per_page;
Dima Zavin03cf4312009-01-23 16:38:30 -08003482 unsigned n;
3483 int r;
3484
Shashank Mittal8e49dec2010-03-01 15:19:04 -08003485 if ((flash_info.type == FLASH_ONENAND_DEVICE) && (ptn->type == TYPE_MODEM_PARTITION))
3486 {
3487 dprintf(CRITICAL, "flash_write_image: feature not supported\n");
3488 return -1;
3489 }
3490
3491 set_nand_configuration(ptn->type);
Dima Zavin03cf4312009-01-23 16:38:30 -08003492 for(n = 0; n < 16; n++) spare[n] = 0xffffffff;
3493
3494 while(bytes > 0) {
3495 if(bytes < wsize) {
3496 dprintf(CRITICAL, "flash_write_image: image undersized (%d < %d)\n", bytes, wsize);
3497 return -1;
3498 }
3499 if(page >= lastpage) {
3500 dprintf(CRITICAL, "flash_write_image: out of space\n");
3501 return -1;
3502 }
3503
Channagoud Kadabibeb17d52011-03-25 17:14:00 +05303504 if((page & num_pages_per_blk_mask) == 0) {
Dima Zavin03cf4312009-01-23 16:38:30 -08003505 if(flash_erase_block(flash_cmdlist, flash_ptrlist, page)) {
Channagoud Kadabibeb17d52011-03-25 17:14:00 +05303506 dprintf(INFO, "flash_write_image: bad block @ %d\n", page / num_pages_per_blk);
3507 page += num_pages_per_blk;
Dima Zavin03cf4312009-01-23 16:38:30 -08003508 continue;
3509 }
3510 }
3511
3512 if(extra_per_page) {
Shashank Mittald0c836d2009-11-20 10:31:18 -08003513 r = _flash_write_page(flash_cmdlist, flash_ptrlist, page, image, image + flash_pagesize);
Dima Zavin03cf4312009-01-23 16:38:30 -08003514 } else {
Shashank Mittald0c836d2009-11-20 10:31:18 -08003515 r = _flash_write_page(flash_cmdlist, flash_ptrlist, page, image, spare);
Dima Zavin03cf4312009-01-23 16:38:30 -08003516 }
3517 if(r) {
3518 dprintf(INFO, "flash_write_image: write failure @ page %d (src %d)\n", page, image - (const unsigned char *)data);
Channagoud Kadabibeb17d52011-03-25 17:14:00 +05303519 image -= (page & num_pages_per_blk_mask) * wsize;
3520 bytes += (page & num_pages_per_blk_mask) * wsize;
3521 page &= ~num_pages_per_blk_mask;
Dima Zavin03cf4312009-01-23 16:38:30 -08003522 if(flash_erase_block(flash_cmdlist, flash_ptrlist, page)) {
3523 dprintf(INFO, "flash_write_image: erase failure @ page %d\n", page);
3524 }
Shashank Mittal8e49dec2010-03-01 15:19:04 -08003525 if (ptn->type != TYPE_MODEM_PARTITION) {
3526 flash_mark_badblock(flash_cmdlist, flash_ptrlist, page);
3527 }
Dima Zavin03cf4312009-01-23 16:38:30 -08003528 dprintf(INFO, "flash_write_image: restart write @ page %d (src %d)\n", page, image - (const unsigned char *)data);
Channagoud Kadabibeb17d52011-03-25 17:14:00 +05303529 page += num_pages_per_blk;
Dima Zavin03cf4312009-01-23 16:38:30 -08003530 continue;
3531 }
Shashank Mittald0c836d2009-11-20 10:31:18 -08003532 page++;
Dima Zavin03cf4312009-01-23 16:38:30 -08003533 image += wsize;
3534 bytes -= wsize;
3535 }
3536
3537 /* erase any remaining pages in the partition */
Channagoud Kadabibeb17d52011-03-25 17:14:00 +05303538 page = (page + num_pages_per_blk_mask) & (~num_pages_per_blk_mask);
Dima Zavin03cf4312009-01-23 16:38:30 -08003539 while(page < lastpage){
3540 if(flash_erase_block(flash_cmdlist, flash_ptrlist, page)) {
Channagoud Kadabibeb17d52011-03-25 17:14:00 +05303541 dprintf(INFO, "flash_write_image: bad block @ %d\n", page / num_pages_per_blk);
Dima Zavin03cf4312009-01-23 16:38:30 -08003542 }
Channagoud Kadabibeb17d52011-03-25 17:14:00 +05303543 page += num_pages_per_blk;
Dima Zavin03cf4312009-01-23 16:38:30 -08003544 }
3545
3546 dprintf(INFO, "flash_write_image: success\n");
3547 return 0;
3548}
3549
3550#if 0
3551static int flash_read_page(unsigned page, void *data, void *extra)
3552{
3553 return _flash_read_page(flash_cmdlist, flash_ptrlist,
3554 page, data, extra);
3555}
3556#endif
Shashank Mittaldcc2e352009-11-19 19:11:16 -08003557
3558unsigned flash_page_size(void)
3559{
3560 return flash_pagesize;
3561}
Chandan Uddaraju14e57eb2010-06-28 12:11:06 -07003562
3563void enable_interleave_mode(int status)
3564{
3565 interleaved_mode = status;
3566 if(status)
3567 {
3568 flash_pagesize *= 2;
3569 platform_config_interleaved_mode_gpios();
3570 }
3571 return;
3572}
Channagoud Kadabi404a7062011-03-21 19:27:50 +05303573
3574int flash_ecc_bch_enabled()
3575{
3576 return enable_bch_ecc;
3577}