blob: e69fa24156eb0fa122480071abd5989498da1b06 [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
Shashank Mittalad3d05c2009-11-19 15:53:57 -080069#define NAND_CFG0_RAW 0xA80420C0
70#define NAND_CFG1_RAW 0x5045D
71
Dima Zavin03cf4312009-01-23 16:38:30 -080072static unsigned CFG0, CFG1;
Shashank Mittal8e49dec2010-03-01 15:19:04 -080073static unsigned CFG0_M, CFG1_M;
74static unsigned CFG0_A, CFG1_A;
Dima Zavin03cf4312009-01-23 16:38:30 -080075
76#define CFG1_WIDE_FLASH (1U << 1)
77
78#define paddr(n) ((unsigned) (n))
79
80static int dmov_exec_cmdptr(unsigned id, unsigned *ptr)
81{
82 dmov_ch ch;
83 unsigned n;
84
85 dmov_prep_ch(&ch, id);
86
87 writel(DMOV_CMD_PTR_LIST | DMOV_CMD_ADDR(paddr(ptr)), ch.cmd);
88
89 while(!(readl(ch.status) & DMOV_STATUS_RSLT_VALID)) ;
90
91 n = readl(ch.status);
92 while(DMOV_STATUS_RSLT_COUNT(n)) {
93 n = readl(ch.result);
94 if(n != 0x80000002) {
95 dprintf(CRITICAL, "ERROR: result: %x\n", n);
96 dprintf(CRITICAL, "ERROR: flush: %x %x %x %x\n",
97 readl(DMOV_FLUSH0(DMOV_NAND_CHAN)),
98 readl(DMOV_FLUSH1(DMOV_NAND_CHAN)),
99 readl(DMOV_FLUSH2(DMOV_NAND_CHAN)),
100 readl(DMOV_FLUSH3(DMOV_NAND_CHAN)));
101 }
102 n = readl(ch.status);
103 }
104
105 return 0;
106}
107
Dima Zavinca337f52009-03-02 16:41:44 -0800108static struct flash_info flash_info;
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800109static unsigned flash_pagesize = 0;
Chandan Uddaraju14e57eb2010-06-28 12:11:06 -0700110static int interleaved_mode = 0;
Channagoud Kadabibeb17d52011-03-25 17:14:00 +0530111static unsigned num_pages_per_blk = 0;
112static unsigned num_pages_per_blk_mask = 0;
Dima Zavin03cf4312009-01-23 16:38:30 -0800113
Shashank Mittal83d16d02009-11-18 16:54:42 -0800114struct flash_identification {
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800115 unsigned flash_id;
116 unsigned mask;
117 unsigned density;
118 unsigned widebus;
119 unsigned pagesize;
120 unsigned blksize;
121 unsigned oobsize;
122 unsigned onenand;
Shashank Mittal83d16d02009-11-18 16:54:42 -0800123};
124
125static struct flash_identification supported_flash[] =
126{
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800127 /* Flash ID ID Mask Density(MB) Wid Pgsz Blksz oobsz onenand Manuf */
128 {0x00000000, 0xFFFFFFFF, 0, 0, 0, 0, 0, 0}, /*ONFI*/
129 {0x1500aaec, 0xFF00FFFF, (256<<20), 0, 2048, (2048<<6), 64, 0}, /*Sams*/
130 {0x5500baec, 0xFF00FFFF, (256<<20), 1, 2048, (2048<<6), 64, 0}, /*Sams*/
131 {0x1500aa98, 0xFFFFFFFF, (256<<20), 0, 2048, (2048<<6), 64, 0}, /*Tosh*/
132 {0x5500ba98, 0xFFFFFFFF, (256<<20), 1, 2048, (2048<<6), 64, 0}, /*Tosh*/
Ajay Dudani86e1b422009-12-04 20:49:50 -0800133 {0xd580b12c, 0xFFFFFFFF, (256<<20), 1, 2048, (2048<<6), 64, 0}, /*Micr*/
Chandan Uddaraju40605112010-08-09 14:25:08 -0700134 {0x5590bc2c, 0xFFFFFFFF, (512<<20), 1, 2048, (2048<<6), 64, 0}, /*Micr*/
Chandan Uddaraju0ec234c2009-11-24 22:34:50 -0800135 {0x1580aa2c, 0xFFFFFFFF, (256<<20), 0, 2048, (2048<<6), 64, 0}, /*Micr*/
Shashank Mittalab958e52010-12-03 17:57:22 -0800136 {0x1590aa2c, 0xFFFFFFFF, (256<<20), 0, 2048, (2048<<6), 64, 0}, /*Micr*/
Ajay Dudani513fb742010-05-24 20:39:26 -0700137 {0x1590ac2c, 0xFFFFFFFF, (512<<20), 0, 2048, (2048<<6), 64, 0}, /*Micr*/
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800138 {0x5580baad, 0xFFFFFFFF, (256<<20), 1, 2048, (2048<<6), 64, 0}, /*Hynx*/
139 {0x5510baad, 0xFFFFFFFF, (256<<20), 1, 2048, (2048<<6), 64, 0}, /*Hynx*/
140 {0x004000ec, 0xFFFFFFFF, (256<<20), 0, 2048, (2048<<6), 64, 1}, /*Sams*/
141 {0x005c00ec, 0xFFFFFFFF, (256<<20), 0, 2048, (2048<<6), 64, 1}, /*Sams*/
142 {0x005800ec, 0xFFFFFFFF, (256<<20), 0, 2048, (2048<<6), 64, 1}, /*Sams*/
Chandan Uddaraju40605112010-08-09 14:25:08 -0700143 {0x6600bcec, 0xFF00FFFF, (512<<20), 1, 4096, (4096<<6), 128, 0}, /*Sams*/
Shashank Mittal246f8d02011-01-21 17:12:27 -0800144 {0x5580ba2c, 0xFFFFFFFF, (256<<20), 1, 2048, (2048<<6), 64, 0}, /*Hynx*/
Shashank Mittalef325412011-04-01 13:48:26 -0700145 {0x6600b3ec, 0xFFFFFFFF, (512<<20), 1, 4096, (4096<<6), 128, 0}, /*Sams*/
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800146 /* Note: Width flag is 0 for 8 bit Flash and 1 for 16 bit flash */
147 /* Note: Onenand flag is 0 for NAND Flash and 1 for OneNAND flash */
148 /* Note: The First row will be filled at runtime during ONFI probe */
Shashank Mittal83d16d02009-11-18 16:54:42 -0800149};
Shashank Mittal8e49dec2010-03-01 15:19:04 -0800150static void set_nand_configuration(char type)
151{
152 if(type == TYPE_MODEM_PARTITION)
153 {
154 CFG0 = CFG0_M;
155 CFG1 = CFG1_M;
156 }
157 else
158 {
159 CFG0 = CFG0_A;
160 CFG1 = CFG1_A;
161 }
162}
Shashank Mittal83d16d02009-11-18 16:54:42 -0800163
164static void flash_nand_read_id(dmov_s *cmdlist, unsigned *ptrlist)
Dima Zavin03cf4312009-01-23 16:38:30 -0800165{
166 dmov_s *cmd = cmdlist;
167 unsigned *ptr = ptrlist;
168 unsigned *data = ptrlist + 4;
169
170 data[0] = 0 | 4;
171 data[1] = NAND_CMD_FETCH_ID;
172 data[2] = 1;
173 data[3] = 0;
174 data[4] = 0;
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800175 data[5] = 0;
176 data[6] = 0;
177 data[7] = 0xAAD40000; /* Default value for CFG0 for reading device id */
Dima Zavin03cf4312009-01-23 16:38:30 -0800178
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800179 /* Read NAND device id */
Dima Zavin03cf4312009-01-23 16:38:30 -0800180 cmd[0].cmd = 0 | CMD_OCB;
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800181 cmd[0].src = paddr(&data[7]);
182 cmd[0].dst = NAND_DEV0_CFG0;
Dima Zavin03cf4312009-01-23 16:38:30 -0800183 cmd[0].len = 4;
184
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800185 cmd[1].cmd = 0;
186 cmd[1].src = NAND_SFLASHC_BURST_CFG;
187 cmd[1].dst = paddr(&data[5]);
Dima Zavin03cf4312009-01-23 16:38:30 -0800188 cmd[1].len = 4;
189
190 cmd[2].cmd = 0;
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800191 cmd[2].src = paddr(&data[6]);
192 cmd[2].dst = NAND_SFLASHC_BURST_CFG;
Dima Zavin03cf4312009-01-23 16:38:30 -0800193 cmd[2].len = 4;
194
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800195 cmd[3].cmd = 0;
196 cmd[3].src = paddr(&data[0]);
197 cmd[3].dst = NAND_FLASH_CHIP_SELECT;
Dima Zavin03cf4312009-01-23 16:38:30 -0800198 cmd[3].len = 4;
199
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800200 cmd[4].cmd = DST_CRCI_NAND_CMD;
201 cmd[4].src = paddr(&data[1]);
202 cmd[4].dst = NAND_FLASH_CMD;
Dima Zavin03cf4312009-01-23 16:38:30 -0800203 cmd[4].len = 4;
204
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800205 cmd[5].cmd = 0;
206 cmd[5].src = paddr(&data[2]);
207 cmd[5].dst = NAND_EXEC_CMD;
208 cmd[5].len = 4;
209
210 cmd[6].cmd = SRC_CRCI_NAND_DATA;
211 cmd[6].src = NAND_FLASH_STATUS;
212 cmd[6].dst = paddr(&data[3]);
213 cmd[6].len = 4;
214
215 cmd[7].cmd = 0;
216 cmd[7].src = NAND_READ_ID;
217 cmd[7].dst = paddr(&data[4]);
218 cmd[7].len = 4;
219
220 cmd[8].cmd = CMD_OCU | CMD_LC;
221 cmd[8].src = paddr(&data[5]);
222 cmd[8].dst = NAND_SFLASHC_BURST_CFG;
223 cmd[8].len = 4;
224
Dima Zavin03cf4312009-01-23 16:38:30 -0800225 ptr[0] = (paddr(cmd) >> 3) | CMD_PTR_LP;
226
227 dmov_exec_cmdptr(DMOV_NAND_CHAN, ptr);
228
229#if VERBOSE
230 dprintf(INFO, "status: %x\n", data[3]);
231#endif
Dima Zavin03cf4312009-01-23 16:38:30 -0800232
Shashank Mittal83d16d02009-11-18 16:54:42 -0800233 flash_info.id = data[4];
Dima Zavinca337f52009-03-02 16:41:44 -0800234 flash_info.vendor = data[4] & 0xff;
235 flash_info.device = (data[4] >> 8) & 0xff;
Shashank Mittal83d16d02009-11-18 16:54:42 -0800236 return;
237}
Dima Zavinca337f52009-03-02 16:41:44 -0800238
Shashank Mittalad3d05c2009-11-19 15:53:57 -0800239static int flash_nand_block_isbad(dmov_s *cmdlist, unsigned *ptrlist,
240 unsigned page)
241{
242 dmov_s *cmd = cmdlist;
243 unsigned *ptr = ptrlist;
244 unsigned *data = ptrlist + 4;
245 char buf[4];
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800246 unsigned cwperpage;
247
248 cwperpage = (flash_pagesize >> 9);
Shashank Mittalad3d05c2009-11-19 15:53:57 -0800249
250 /* Check first page of this block */
Channagoud Kadabibeb17d52011-03-25 17:14:00 +0530251 if(page & num_pages_per_blk_mask)
252 page = page - (page & num_pages_per_blk_mask);
Shashank Mittalad3d05c2009-11-19 15:53:57 -0800253
254 /* Check bad block marker */
255 data[0] = NAND_CMD_PAGE_READ; /* command */
256
257 /* addr0 */
258 if (CFG1 & CFG1_WIDE_FLASH)
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800259 data[1] = (page << 16) | ((528*(cwperpage-1)) >> 1);
Shashank Mittalad3d05c2009-11-19 15:53:57 -0800260 else
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800261 data[1] = (page << 16) | (528*(cwperpage-1));
Shashank Mittalad3d05c2009-11-19 15:53:57 -0800262
263 data[2] = (page >> 16) & 0xff; /* addr1 */
264 data[3] = 0 | 4; /* chipsel */
265 data[4] = NAND_CFG0_RAW & ~(7U << 6); /* cfg0 */
266 data[5] = NAND_CFG1_RAW | (CFG1 & CFG1_WIDE_FLASH); /* cfg1 */
267 data[6] = 1;
268 data[7] = CLEAN_DATA_32; /* flash status */
269 data[8] = CLEAN_DATA_32; /* buf status */
270
271 cmd[0].cmd = DST_CRCI_NAND_CMD | CMD_OCB;
272 cmd[0].src = paddr(&data[0]);
273 cmd[0].dst = NAND_FLASH_CMD;
274 cmd[0].len = 16;
275
276 cmd[1].cmd = 0;
277 cmd[1].src = paddr(&data[4]);
278 cmd[1].dst = NAND_DEV0_CFG0;
279 cmd[1].len = 8;
280
281 cmd[2].cmd = 0;
282 cmd[2].src = paddr(&data[6]);
283 cmd[2].dst = NAND_EXEC_CMD;
284 cmd[2].len = 4;
285
286 cmd[3].cmd = SRC_CRCI_NAND_DATA;
287 cmd[3].src = NAND_FLASH_STATUS;
288 cmd[3].dst = paddr(&data[7]);
289 cmd[3].len = 8;
290
291 cmd[4].cmd = CMD_OCU | CMD_LC;
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800292 cmd[4].src = NAND_FLASH_BUFFER + (flash_pagesize - (528*(cwperpage-1)));
Shashank Mittalad3d05c2009-11-19 15:53:57 -0800293 cmd[4].dst = paddr(&buf);
294 cmd[4].len = 4;
295
296 ptr[0] = (paddr(cmd) >> 3) | CMD_PTR_LP;
297
298 dmov_exec_cmdptr(DMOV_NAND_CHAN, ptr);
299
300#if VERBOSE
301 dprintf(INFO, "status: %x\n", data[7]);
302#endif
303
304 /* we fail if there was an operation error, a mpu error, or the
305 ** erase success bit was not set.
306 */
307 if(data[7] & 0x110) return -1;
308
309 /* Check for bad block marker byte */
310 if (CFG1 & CFG1_WIDE_FLASH) {
311 if (buf[0] != 0xFF || buf[1] != 0xFF)
312 return 1;
313 } else {
314 if (buf[0] != 0xFF)
315 return 1;
316 }
317
318 return 0;
319}
320
Murali Nalajalaa8c94c62010-03-05 20:24:30 +0530321static int flash_nand_block_isbad_interleave(dmov_s *cmdlist, unsigned *ptrlist,
322 unsigned page)
323{
324 dmov_s *cmd = cmdlist;
325 unsigned *ptr = ptrlist;
326 unsigned *data = ptrlist + 4;
327 char buf01[4];
328 char buf10[4];
329 unsigned cwperpage;
330
331 cwperpage = ((flash_pagesize >> 1)>> 9);
332
333 /* Check first page of this block */
334 if(page & 63)
335 page = page - (page & 63);
336
337 /* Check bad block marker */
338 data[0] = NAND_CMD_PAGE_READ; /* command */
339
340 /* addr0 */
341 if (CFG1 & CFG1_WIDE_FLASH)
342 data[1] = (page << 16) | ((528*(cwperpage-1)) >> 1);
343 else
344 data[1] = (page << 16) | (528*(cwperpage-1));
345
346 data[2] = (page >> 16) & 0xff; /* addr1 */
347 data[3] = 0 | 4; /* chipsel CS0 */
348 data[4] = 0 | 5; /* chipsel CS1 */
349 data[5] = NAND_CFG0_RAW & ~(7U << 6); /* cfg0 */
350 data[6] = NAND_CFG1_RAW | (CFG1 & CFG1_WIDE_FLASH); /* cfg1 */
351 data[7] = 1;
352 data[8] = CLEAN_DATA_32; /* NC01 flash status */
353 data[9] = CLEAN_DATA_32; /* NC01 buf01 status */
354 data[10] = CLEAN_DATA_32; /* NC10 flash status */
355 data[11] = CLEAN_DATA_32; /* NC10 buf10 status */
356 data[12] = 0x00000A3C; /* adm_mux_data_ack_req_nc01 */
357 data[13] = 0x0000053C; /* adm_mux_cmd_ack_req_nc01 */
358 data[14] = 0x00000F28; /* adm_mux_data_ack_req_nc10 */
359 data[15] = 0x00000F14; /* adm_mux_cmd_ack_req_nc10 */
360 data[16] = 0x00000FC0; /* adm_default_mux */
361 data[17] = 0x00000805; /* enable CS1 */
362 data[18] = 0x00000801; /* disable CS1 */
363
364 /* enable CS1 */
365 cmd[0].cmd = 0;
366 cmd[0].src = paddr(data[17]);
367 cmd[0].dst = EBI2_CHIP_SELECT_CFG0;
368 cmd[0].len = 4;
369
370 /* Reading last code word from NC01 */
371 /* 0xF14 */
372 cmd[1].cmd = 0;
373 cmd[1].src = paddr(data[15]);
374 cmd[1].dst = EBI2_NAND_ADM_MUX;
375 cmd[1].len = 4;
376
377 cmd[2].cmd = DST_CRCI_NAND_CMD;
378 cmd[2].src = paddr(&data[0]);
379 cmd[2].dst = NC01(NAND_FLASH_CMD);
380 cmd[2].len = 16;
381
382 cmd[3].cmd = 0;
383 cmd[3].src = paddr(&data[5]);
384 cmd[3].dst = NC01(NAND_DEV0_CFG0);
385 cmd[3].len = 8;
386
387 cmd[4].cmd = 0;
388 cmd[4].src = paddr(&data[7]);
389 cmd[4].dst = NC01(NAND_EXEC_CMD);
390 cmd[4].len = 4;
391
392 /* 0xF28 */
393 cmd[5].cmd = 0;
394 cmd[5].src = paddr(data[14]);
395 cmd[5].dst = EBI2_NAND_ADM_MUX;
396 cmd[5].len = 4;
397
398 cmd[6].cmd = SRC_CRCI_NAND_DATA;
399 cmd[6].src = NC01(NAND_FLASH_STATUS);
400 cmd[6].dst = paddr(&data[8]);
401 cmd[6].len = 8;
402
403 cmd[7].cmd = 0;
404 cmd[7].src = NC01(NAND_FLASH_BUFFER) + (flash_pagesize - (528*(cwperpage-1)));
405 cmd[7].dst = paddr(&buf01);
406 cmd[7].len = 4;
407
408 /* Reading last code word from NC10 */
409 /* 0x53C */
410 cmd[8].cmd = 0;
411 cmd[8].src = paddr(data[13]);
412 cmd[8].dst = EBI2_NAND_ADM_MUX;
413 cmd[8].len = 4;
414
415 cmd[9].cmd = DST_CRCI_NAND_CMD;
416 cmd[9].src = paddr(&data[0]);
417 cmd[9].dst = NC10(NAND_FLASH_CMD);
418 cmd[9].len = 12;
419
420 cmd[10].cmd = 0;
421 cmd[10].src = paddr(&data[4]);
422 cmd[10].dst = NC10(NAND_FLASH_CHIP_SELECT);
423 cmd[10].len = 4;
424
425 cmd[11].cmd = 0;
426 cmd[11].src = paddr(&data[5]);
427 cmd[11].dst = NC10(NAND_DEV1_CFG0);
428 cmd[11].len = 8;
429
430 cmd[12].cmd = 0;
431 cmd[12].src = paddr(&data[7]);
432 cmd[12].dst = NC10(NAND_EXEC_CMD);
433 cmd[12].len = 4;
434
435 /* 0xA3C */
436 cmd[13].cmd = 0;
437 cmd[13].src = paddr(data[12]);
438 cmd[13].dst = EBI2_NAND_ADM_MUX;
439 cmd[13].len = 4;
440
441 cmd[14].cmd = SRC_CRCI_NAND_DATA;
442 cmd[14].src = NC10(NAND_FLASH_STATUS);
443 cmd[14].dst = paddr(&data[10]);
444 cmd[14].len = 8;
445
446 cmd[15].cmd = 0;
447 cmd[15].src = NC10(NAND_FLASH_BUFFER) + (flash_pagesize - (528*(cwperpage-1)));
448 cmd[15].dst = paddr(&buf10);
449 cmd[15].len = 4;
450
451 cmd[16].cmd = 0;
452 cmd[16].src = paddr(&data[16]);
453 cmd[16].dst = EBI2_NAND_ADM_MUX;
454 cmd[16].len = 4;
455
456 /* setting default value */
457 cmd[17].cmd = CMD_OCU | CMD_LC;
458 cmd[17].src = paddr(&data[18]);
459 cmd[17].dst = EBI2_CHIP_SELECT_CFG0;
460 cmd[17].len = 4;
461
462 ptr[0] = (paddr(cmd) >> 3) | CMD_PTR_LP;
463
464 dmov_exec_cmdptr(DMOV_NAND_CHAN, ptr);
465
466#if VERBOSE
467 dprintf(INFO, "NC01 status: %x\n", data[8]);
468 dprintf(INFO, "NC10 status: %x\n", data[10]);
469#endif
470
471 /* we fail if there was an operation error, a mpu error, or the
472 ** erase success bit was not set.
473 */
474 if((data[8] & 0x110) || (data[10] & 0x110)) return -1;
475
476 /* Check for bad block marker byte */
477 if (CFG1 & CFG1_WIDE_FLASH) {
478 if ((buf01[0] != 0xFF || buf01[1] != 0xFF) ||
479 (buf10[0] != 0xFF || buf10[1] != 0xFF))
480 return 1;
481 } else {
482 if (buf01[0] != 0xFF || buf10[0] != 0xFF)
483 return 1;
484 }
485
486 return 0;
487}
488
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800489static int flash_nand_erase_block(dmov_s *cmdlist, unsigned *ptrlist,
490 unsigned page)
Dima Zavin03cf4312009-01-23 16:38:30 -0800491{
492 dmov_s *cmd = cmdlist;
493 unsigned *ptr = ptrlist;
494 unsigned *data = ptrlist + 4;
Shashank Mittalad3d05c2009-11-19 15:53:57 -0800495 int isbad = 0;
Dima Zavin03cf4312009-01-23 16:38:30 -0800496
497 /* only allow erasing on block boundaries */
Channagoud Kadabibeb17d52011-03-25 17:14:00 +0530498 if(page & num_pages_per_blk_mask) return -1;
Dima Zavin03cf4312009-01-23 16:38:30 -0800499
Shashank Mittalad3d05c2009-11-19 15:53:57 -0800500 /* Check for bad block and erase only if block is not marked bad */
501 isbad = flash_nand_block_isbad(cmdlist, ptrlist, page);
502
503 if (isbad) {
Channagoud Kadabibeb17d52011-03-25 17:14:00 +0530504 dprintf(INFO, "skipping @ %d (bad block)\n", page / num_pages_per_blk);
Shashank Mittalad3d05c2009-11-19 15:53:57 -0800505 return -1;
506 }
507
508 /* Erase block */
Dima Zavin03cf4312009-01-23 16:38:30 -0800509 data[0] = NAND_CMD_BLOCK_ERASE;
510 data[1] = page;
511 data[2] = 0;
512 data[3] = 0 | 4;
513 data[4] = 1;
514 data[5] = 0xeeeeeeee;
515 data[6] = CFG0 & (~(7 << 6)); /* CW_PER_PAGE = 0 */
516 data[7] = CFG1;
Murali Palnatic54d13a2010-01-15 19:50:19 +0530517 data[8] = 0x00000020;
518 data[9] = 0x000000C0;
Dima Zavin03cf4312009-01-23 16:38:30 -0800519
520 cmd[0].cmd = DST_CRCI_NAND_CMD | CMD_OCB;
521 cmd[0].src = paddr(&data[0]);
522 cmd[0].dst = NAND_FLASH_CMD;
523 cmd[0].len = 16;
524
525 cmd[1].cmd = 0;
526 cmd[1].src = paddr(&data[6]);
527 cmd[1].dst = NAND_DEV0_CFG0;
528 cmd[1].len = 8;
529
530 cmd[2].cmd = 0;
531 cmd[2].src = paddr(&data[4]);
532 cmd[2].dst = NAND_EXEC_CMD;
533 cmd[2].len = 4;
534
Murali Palnatic54d13a2010-01-15 19:50:19 +0530535 cmd[3].cmd = SRC_CRCI_NAND_DATA;
Dima Zavin03cf4312009-01-23 16:38:30 -0800536 cmd[3].src = NAND_FLASH_STATUS;
537 cmd[3].dst = paddr(&data[5]);
538 cmd[3].len = 4;
539
Murali Palnatic54d13a2010-01-15 19:50:19 +0530540 cmd[4].cmd = 0;
541 cmd[4].src = paddr(&data[8]);
542 cmd[4].dst = NAND_FLASH_STATUS;
543 cmd[4].len = 4;
544
545 cmd[5].cmd = CMD_OCU | CMD_LC;
546 cmd[5].src = paddr(&data[9]);
547 cmd[5].dst = NAND_READ_STATUS;
548 cmd[5].len = 4;
549
Dima Zavin03cf4312009-01-23 16:38:30 -0800550 ptr[0] = (paddr(cmd) >> 3) | CMD_PTR_LP;
551
552 dmov_exec_cmdptr(DMOV_NAND_CHAN, ptr);
553
554#if VERBOSE
555 dprintf(INFO, "status: %x\n", data[5]);
556#endif
557
558 /* we fail if there was an operation error, a mpu error, or the
559 ** erase success bit was not set.
560 */
561 if(data[5] & 0x110) return -1;
562 if(!(data[5] & 0x80)) return -1;
563
564 return 0;
565}
566
Murali Nalajalaa8c94c62010-03-05 20:24:30 +0530567static int flash_nand_erase_block_interleave(dmov_s *cmdlist, unsigned *ptrlist,
568 unsigned page)
569{
570 dmov_s *cmd = cmdlist;
571 unsigned *ptr = ptrlist;
572 unsigned *data = ptrlist + 4;
573 int isbad = 0;
574
575 /* only allow erasing on block boundaries */
576 if(page & 63) return -1;
577
578 /* Check for bad block and erase only if block is not marked bad */
579 isbad = flash_nand_block_isbad(cmdlist, ptrlist, page);
580
581 if (isbad) {
582 dprintf(INFO, "skipping @ %d (bad block)\n", page >> 6);
583 return -1;
584 }
585
586 /* Erase block */
587 data[0] = NAND_CMD_BLOCK_ERASE;
588 data[1] = page;
589 data[2] = 0;
590 data[3] = 0 | 4; /* chipselect CS0 */
591 data[4] = 0 | 5; /* chipselect CS1 */
592 data[5] = 1;
593 data[6] = 0xeeeeeeee;
594 data[7] = 0xeeeeeeee;
595 data[8] = CFG0 & (~(7 << 6)); /* CW_PER_PAGE = 0 */
596 data[9] = CFG1;
597 data[10] = 0x00000A3C; /* adm_mux_data_ack_req_nc01 */
598 data[11] = 0x0000053C; /* adm_mux_cmd_ack_req_nc01 */
599 data[12] = 0x00000F28; /* adm_mux_data_ack_req_nc10 */
600 data[13] = 0x00000F14; /* adm_mux_cmd_ack_req_nc10 */
601 data[14] = 0x00000FC0; /* adm_default_mux */
602 data[15] = 0x00000805; /* enable CS1 */
603 data[16] = 0x00000801; /* disable CS1 */
604
605 /* enable CS1 */
606 cmd[0].cmd = 0 | CMD_OCB;
607 cmd[0].src = paddr(data[15]);
608 cmd[0].dst = EBI2_CHIP_SELECT_CFG0;
609 cmd[0].len = 4;
610
611 /* Reading last code word from NC01 */
612 /* 0xF14 */
613 cmd[1].cmd = 0;
614 cmd[1].src = paddr(data[13]);
615 cmd[1].dst = EBI2_NAND_ADM_MUX;
616 cmd[1].len = 4;
617
618 cmd[2].cmd = DST_CRCI_NAND_CMD;
619 cmd[2].src = paddr(&data[0]);
620 cmd[2].dst = NC01(NAND_FLASH_CMD);
621 cmd[2].len = 16;
622
623 cmd[3].cmd = 0;
624 cmd[3].src = paddr(&data[8]);
625 cmd[3].dst = NC01(NAND_DEV0_CFG0);
626 cmd[3].len = 8;
627
628 cmd[4].cmd = 0;
629 cmd[4].src = paddr(&data[5]);
630 cmd[4].dst = NC01(NAND_EXEC_CMD);
631 cmd[4].len = 4;
632
633 /* 0xF28 */
634 cmd[5].cmd = 0;
635 cmd[5].src = paddr(data[12]);
636 cmd[5].dst = EBI2_NAND_ADM_MUX;
637 cmd[5].len = 4;
638
639 cmd[6].cmd = SRC_CRCI_NAND_DATA;
640 cmd[6].src = NC01(NAND_FLASH_STATUS);
641 cmd[6].dst = paddr(&data[6]);
642 cmd[6].len = 4;
643
644 /* Reading last code word from NC10 */
645 /* 0x53C */
646 cmd[7].cmd = 0;
647 cmd[7].src = paddr(data[11]);
648 cmd[7].dst = EBI2_NAND_ADM_MUX;
649 cmd[7].len = 4;
650
651 cmd[8].cmd = DST_CRCI_NAND_CMD;
652 cmd[8].src = paddr(&data[0]);
653 cmd[8].dst = NC10(NAND_FLASH_CMD);
654 cmd[8].len = 12;
655
656 cmd[9].cmd = 0;
657 cmd[9].src = paddr(&data[4]);
658 cmd[9].dst = NC10(NAND_FLASH_CHIP_SELECT);
659 cmd[9].len = 4;
660
661 cmd[10].cmd = 0;
662 cmd[10].src = paddr(&data[8]);
663 cmd[10].dst = NC10(NAND_DEV1_CFG0);
664 cmd[10].len = 8;
665
666 cmd[11].cmd = 0;
667 cmd[11].src = paddr(&data[5]);
668 cmd[11].dst = NC10(NAND_EXEC_CMD);
669 cmd[11].len = 4;
670
671 /* 0xA3C */
672 cmd[12].cmd = 0;
673 cmd[12].src = paddr(data[10]);
674 cmd[12].dst = EBI2_NAND_ADM_MUX;
675 cmd[12].len = 4;
676
677 cmd[13].cmd = SRC_CRCI_NAND_DATA;
678 cmd[13].src = NC10(NAND_FLASH_STATUS);
679 cmd[13].dst = paddr(&data[7]);
680 cmd[13].len = 4;
681
682 /* adm default mux state */
683 /* 0xFCO */
684 cmd[14].cmd = 0;
685 cmd[14].src = paddr(data[14]);
686 cmd[14].dst = EBI2_NAND_ADM_MUX;
687 cmd[14].len = 4;
688
689 /* disable CS1 */
690 cmd[15].cmd = CMD_OCU | CMD_LC;
691 cmd[15].src = paddr(data[16]);
692 cmd[15].dst = EBI2_CHIP_SELECT_CFG0;
693 cmd[15].len = 4;
694
695 ptr[0] = (paddr(cmd) >> 3) | CMD_PTR_LP;
696
697 dmov_exec_cmdptr(DMOV_NAND_CHAN, ptr);
698
699#if VERBOSE
700 dprintf(INFO, "NC01 status: %x\n", data[6]);
701 dprintf(INFO, "NC10 status: %x\n", data[7]);
702#endif
703
704 /* we fail if there was an operation error, a mpu error, or the
705 ** erase success bit was not set.
706 */
707 if(data[6] & 0x110 || data[7] & 0x110) return -1;
708 if(!(data[6] & 0x80) || !(data[7] & 0x80)) return -1;
709
710 return 0;
711}
712
Dima Zavin03cf4312009-01-23 16:38:30 -0800713struct data_flash_io {
714 unsigned cmd;
715 unsigned addr0;
716 unsigned addr1;
717 unsigned chipsel;
718 unsigned cfg0;
719 unsigned cfg1;
720 unsigned exec;
721 unsigned ecc_cfg;
722 unsigned ecc_cfg_save;
Murali Palnatic54d13a2010-01-15 19:50:19 +0530723 unsigned clrfstatus;
724 unsigned clrrstatus;
Dima Zavin03cf4312009-01-23 16:38:30 -0800725 struct {
726 unsigned flash_status;
727 unsigned buffer_status;
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800728 } result[8];
Dima Zavin03cf4312009-01-23 16:38:30 -0800729};
730
Murali Nalajalaa8c94c62010-03-05 20:24:30 +0530731struct interleave_data_flash_io {
732 uint32_t cmd;
733 uint32_t addr0;
734 uint32_t addr1;
735 uint32_t chipsel_cs0;
736 uint32_t chipsel_cs1;
737 uint32_t cfg0;
738 uint32_t cfg1;
739 uint32_t exec;
740 uint32_t ecc_cfg;
741 uint32_t ecc_cfg_save;
742 uint32_t ebi2_chip_select_cfg0;
743 uint32_t adm_mux_data_ack_req_nc01;
744 uint32_t adm_mux_cmd_ack_req_nc01;
745 uint32_t adm_mux_data_ack_req_nc10;
746 uint32_t adm_mux_cmd_ack_req_nc10;
747 uint32_t adm_default_mux;
748 uint32_t default_ebi2_chip_select_cfg0;
749 struct {
750 uint32_t flash_status;
751 } result[16];
752};
753
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800754static int _flash_nand_read_page(dmov_s *cmdlist, unsigned *ptrlist,
755 unsigned page, void *_addr, void *_spareaddr)
Dima Zavin03cf4312009-01-23 16:38:30 -0800756{
757 dmov_s *cmd = cmdlist;
758 unsigned *ptr = ptrlist;
759 struct data_flash_io *data = (void*) (ptrlist + 4);
760 unsigned addr = (unsigned) _addr;
761 unsigned spareaddr = (unsigned) _spareaddr;
762 unsigned n;
Shashank Mittalad3d05c2009-11-19 15:53:57 -0800763 int isbad = 0;
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800764 unsigned cwperpage;
765 cwperpage = (flash_pagesize >> 9);
Shashank Mittalad3d05c2009-11-19 15:53:57 -0800766
767 /* Check for bad block and read only from a good block */
768 isbad = flash_nand_block_isbad(cmdlist, ptrlist, page);
769 if (isbad)
770 return -2;
Dima Zavin03cf4312009-01-23 16:38:30 -0800771
772 data->cmd = NAND_CMD_PAGE_READ_ECC;
773 data->addr0 = page << 16;
774 data->addr1 = (page >> 16) & 0xff;
775 data->chipsel = 0 | 4; /* flash0 + undoc bit */
776
777 /* GO bit for the EXEC register */
778 data->exec = 1;
779
780 data->cfg0 = CFG0;
781 data->cfg1 = CFG1;
782
783 data->ecc_cfg = 0x203;
784
785 /* save existing ecc config */
786 cmd->cmd = CMD_OCB;
787 cmd->src = NAND_EBI2_ECC_BUF_CFG;
788 cmd->dst = paddr(&data->ecc_cfg_save);
789 cmd->len = 4;
790 cmd++;
791
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800792 for(n = 0; n < cwperpage; n++) {
Dima Zavin03cf4312009-01-23 16:38:30 -0800793 /* write CMD / ADDR0 / ADDR1 / CHIPSEL regs in a burst */
794 cmd->cmd = DST_CRCI_NAND_CMD;
795 cmd->src = paddr(&data->cmd);
796 cmd->dst = NAND_FLASH_CMD;
797 cmd->len = ((n == 0) ? 16 : 4);
798 cmd++;
799
800 if (n == 0) {
801 /* block on cmd ready, set configuration */
802 cmd->cmd = 0;
803 cmd->src = paddr(&data->cfg0);
804 cmd->dst = NAND_DEV0_CFG0;
805 cmd->len = 8;
806 cmd++;
807
808 /* set our ecc config */
809 cmd->cmd = 0;
810 cmd->src = paddr(&data->ecc_cfg);
811 cmd->dst = NAND_EBI2_ECC_BUF_CFG;
812 cmd->len = 4;
813 cmd++;
814 }
815 /* kick the execute register */
816 cmd->cmd = 0;
817 cmd->src = paddr(&data->exec);
818 cmd->dst = NAND_EXEC_CMD;
819 cmd->len = 4;
820 cmd++;
821
822 /* block on data ready, then read the status register */
823 cmd->cmd = SRC_CRCI_NAND_DATA;
824 cmd->src = NAND_FLASH_STATUS;
825 cmd->dst = paddr(&data->result[n]);
826 cmd->len = 8;
827 cmd++;
828
829 /* read data block */
830 cmd->cmd = 0;
831 cmd->src = NAND_FLASH_BUFFER;
832 cmd->dst = addr + n * 516;
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800833 cmd->len = ((n < (cwperpage -1 )) ? 516 : (512 - ((cwperpage - 1) << 2)));
Dima Zavin03cf4312009-01-23 16:38:30 -0800834 cmd++;
835 }
836
837 /* read extra data */
838 cmd->cmd = 0;
839 cmd->src = NAND_FLASH_BUFFER + 500;
840 cmd->dst = spareaddr;
841 cmd->len = 16;
842 cmd++;
843
844 /* restore saved ecc config */
845 cmd->cmd = CMD_OCU | CMD_LC;
846 cmd->src = paddr(&data->ecc_cfg_save);
847 cmd->dst = NAND_EBI2_ECC_BUF_CFG;
848 cmd->len = 4;
849
850 ptr[0] = (paddr(cmdlist) >> 3) | CMD_PTR_LP;
851
852 dmov_exec_cmdptr(DMOV_NAND_CHAN, ptr);
853
854#if VERBOSE
855 dprintf(INFO, "read page %d: status: %x %x %x %x\n",
856 page, data[5], data[6], data[7], data[8]);
857 for(n = 0; n < 4; n++) {
858 ptr = (unsigned*)(addr + 512 * n);
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800859 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 -0800860 ptr = (unsigned*)(spareaddr + 16 * n);
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800861 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 -0800862 }
863#endif
864
865 /* if any of the writes failed (0x10), or there was a
866 ** protection violation (0x100), we lose
867 */
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800868 for(n = 0; n < cwperpage; n++) {
Dima Zavin03cf4312009-01-23 16:38:30 -0800869 if (data->result[n].flash_status & 0x110) {
870 return -1;
871 }
872 }
873
874 return 0;
875}
876
Murali Nalajalaa8c94c62010-03-05 20:24:30 +0530877static int flash_nand_read_page_interleave(dmov_s *cmdlist, unsigned *ptrlist,
878 unsigned page, void *_addr, void *_spareaddr)
879{
880 dmov_s *cmd = cmdlist;
881 unsigned *ptr = ptrlist;
882 struct interleave_data_flash_io *data = (void*) (ptrlist + 4);
883 unsigned addr = (unsigned) _addr;
884 unsigned spareaddr = (unsigned) _spareaddr;
885 unsigned n;
886 int isbad = 0;
887 unsigned cwperpage;
888 cwperpage = (flash_pagesize >> 9);
889
890 /* Check for bad block and read only from a good block */
891 isbad = flash_nand_block_isbad(cmdlist, ptrlist, page);
892 if (isbad)
893 return -2;
894
895 data->cmd = NAND_CMD_PAGE_READ_ECC;
896 data->addr0 = page << 16;
897 data->addr1 = (page >> 16) & 0xff;
898 data->chipsel_cs0 = 0 | 4; /* flash0 + undoc bit */
899 data->chipsel_cs1 = 0 | 5; /* flash0 + undoc bit */
900 data->ebi2_chip_select_cfg0 = 0x00000805;
901 data->adm_mux_data_ack_req_nc01 = 0x00000A3C;
902 data->adm_mux_cmd_ack_req_nc01 = 0x0000053C;
903 data->adm_mux_data_ack_req_nc10 = 0x00000F28;
904 data->adm_mux_cmd_ack_req_nc10 = 0x00000F14;
905 data->adm_default_mux = 0x00000FC0;
906 data->default_ebi2_chip_select_cfg0 = 0x00000801;
907
908 /* GO bit for the EXEC register */
909 data->exec = 1;
910
911 data->cfg0 = CFG0;
912 data->cfg1 = CFG1;
913
914 data->ecc_cfg = 0x203;
915
916 for (n = 0; n < cwperpage; n++) {
917 /* flash + buffer status return words */
918 data->result[n].flash_status = 0xeeeeeeee;
919
920 if (n == 0) {
921 /* enable CS1 */
922 cmd->cmd = CMD_OCB;
923 cmd->src = paddr(&data->ebi2_chip_select_cfg0);
924 cmd->dst = EBI2_CHIP_SELECT_CFG0;
925 cmd->len = 4;
926 cmd++;
927
928 /* save existing ecc config */
929 cmd->cmd = 0;
930 cmd->src = NAND_EBI2_ECC_BUF_CFG;
931 cmd->dst = paddr(&data->ecc_cfg_save);
932 cmd->len = 4;
933 cmd++;
934
935 /* NC01, NC10 --> ADDR0/ADDR1 */
936 cmd->cmd = 0;
937 cmd->src = paddr(&data->addr0);
938 cmd->dst = NC11(NAND_ADDR0);
939 cmd->len = 8;
940 cmd++;
941
942 /* Select the CS0,
943 * for NC01!
944 */
945 cmd->cmd = 0;
946 cmd->src = paddr(&data->chipsel_cs0);
947 cmd->dst = NC01(NAND_FLASH_CHIP_SELECT);
948 cmd->len = 4;
949 cmd++;
950
951 /* Select the CS1,
952 * for NC10!
953 */
954 cmd->cmd = 0;
955 cmd->src = paddr(&data->chipsel_cs1);
956 cmd->dst = NC10(NAND_FLASH_CHIP_SELECT);
957 cmd->len = 4;
958 cmd++;
959
960 cmd->cmd = 0;
961 cmd->src = paddr(&data->cfg0);
962 cmd->dst = NC01(NAND_DEV0_CFG0);
963 cmd->len = 8;
964 cmd++;
965
966 /* config DEV1 for CS1 */
967 cmd->cmd = 0;
968 cmd->src = paddr(&data->cfg0);
969 cmd->dst = NC10(NAND_DEV1_CFG0);
970 cmd->len = 8;
971 cmd++;
972
973 cmd->cmd = 0;
974 cmd->src = paddr(&data->ecc_cfg);
975 cmd->dst = NC11(NAND_EBI2_ECC_BUF_CFG);
976 cmd->len = 4;
977 cmd++;
978
979 /* if 'only' the last code word */
980 if (n == cwperpage - 1) {
981 /* MASK CMD ACK/REQ --> NC01 (0x53C)*/
982 cmd->cmd = 0;
983 cmd->src = paddr(&data->adm_mux_cmd_ack_req_nc01);
984 cmd->dst = EBI2_NAND_ADM_MUX;
985 cmd->len = 4;
986 cmd++;
987
988 /* CMD */
989 cmd->cmd = DST_CRCI_NAND_CMD;
990 cmd->src = paddr(&data->cmd);
991 cmd->dst = NC10(NAND_FLASH_CMD);
992 cmd->len = 4;
993 cmd++;
994
995 /* kick the execute register for NC10 */
996 cmd->cmd = 0;
997 cmd->src = paddr(&data->exec);
998 cmd->dst = NC10(NAND_EXEC_CMD);
999 cmd->len = 4;
1000 cmd++;
1001
1002 /* MASK DATA ACK/REQ --> NC01 (0xA3C)*/
1003 cmd->cmd = 0;
1004 cmd->src = paddr(&data->adm_mux_data_ack_req_nc01);
1005 cmd->dst = EBI2_NAND_ADM_MUX;
1006 cmd->len = 4;
1007 cmd++;
1008
1009 /* block on data ready from NC10, then
1010 * read the status register
1011 */
1012 cmd->cmd = SRC_CRCI_NAND_DATA;
1013 cmd->src = NC10(NAND_FLASH_STATUS);
1014 cmd->dst = paddr(&data->result[n]);
1015 /* NAND_FLASH_STATUS +
1016 * NAND_BUFFER_STATUS
1017 */
1018 cmd->len = 4;
1019 cmd++;
1020 } else {
1021 /* MASK CMD ACK/REQ --> NC10 (0xF14)*/
1022 cmd->cmd = 0;
1023 cmd->src = paddr(&data->adm_mux_cmd_ack_req_nc10);
1024 cmd->dst = EBI2_NAND_ADM_MUX;
1025 cmd->len = 4;
1026 cmd++;
1027
1028 /* CMD */
1029 cmd->cmd = DST_CRCI_NAND_CMD;
1030 cmd->src = paddr(&data->cmd);
1031 cmd->dst = NC01(NAND_FLASH_CMD);
1032 cmd->len = 4;
1033 cmd++;
1034
1035 /* kick the execute register for NC01*/
1036 cmd->cmd = 0;
1037 cmd->src = paddr(&data->exec);
1038 cmd->dst = NC01(NAND_EXEC_CMD);
1039 cmd->len = 4;
1040 cmd++;
1041 }
1042 }
1043
1044
1045 if (n % 2 == 0) {
1046 /* MASK CMD ACK/REQ --> NC01 (0x53C)*/
1047 cmd->cmd = 0;
1048 cmd->src = paddr(&data->adm_mux_cmd_ack_req_nc01);
1049 cmd->dst = EBI2_NAND_ADM_MUX;
1050 cmd->len = 4;
1051 cmd++;
1052
1053 /* CMD */
1054 cmd->cmd = DST_CRCI_NAND_CMD;
1055 cmd->src = paddr(&data->cmd);
1056 cmd->dst = NC10(NAND_FLASH_CMD);
1057 cmd->len = 4;
1058 cmd++;
1059
1060 /* kick the execute register for NC10 */
1061 cmd->cmd = 0;
1062 cmd->src = paddr(&data->exec);
1063 cmd->dst = NC10(NAND_EXEC_CMD);
1064 cmd->len = 4;
1065 cmd++;
1066
1067 /* MASK DATA ACK/REQ --> NC10 (0xF28)*/
1068 cmd->cmd = 0;
1069 cmd->src = paddr(&data->adm_mux_data_ack_req_nc10);
1070 cmd->dst = EBI2_NAND_ADM_MUX;
1071 cmd->len = 4;
1072 cmd++;
1073
1074 /* block on data ready from NC01, then
1075 * read the status register
1076 */
1077 cmd->cmd = SRC_CRCI_NAND_DATA;
1078 cmd->src = NC01(NAND_FLASH_STATUS);
1079 cmd->dst = paddr(&data->result[n]);
1080 /* NAND_FLASH_STATUS +
1081 * NAND_BUFFER_STATUS
1082 */
1083 cmd->len = 4;
1084 cmd++;
1085
1086 /* read data block */
1087 cmd->cmd = 0;
1088 cmd->src = NC01(NAND_FLASH_BUFFER);
1089 cmd->dst = addr + n * 516;
1090 cmd->len = ((n < (cwperpage -1 )) ? 516 : (512 - ((cwperpage - 1) << 2)));
1091 cmd++;
1092 } else {
1093 if (n != cwperpage - 1) {
1094 /* MASK CMD ACK/REQ -->
1095 * NC10 (0xF14)
1096 */
1097 cmd->cmd = 0;
1098 cmd->src = paddr(&data->adm_mux_cmd_ack_req_nc10);
1099 cmd->dst = EBI2_NAND_ADM_MUX;
1100 cmd->len = 4;
1101 cmd++;
1102
1103 /* CMD */
1104 cmd->cmd = DST_CRCI_NAND_CMD;
1105 cmd->src = paddr(&data->cmd);
1106 cmd->dst = NC01(NAND_FLASH_CMD);
1107 cmd->len = 4;
1108 cmd++;
1109
1110 /* EXEC */
1111 cmd->cmd = 0;
1112 cmd->src = paddr(&data->exec);
1113 cmd->dst = NC01(NAND_EXEC_CMD);
1114 cmd->len = 4;
1115 cmd++;
1116
1117 /* MASK DATA ACK/REQ -->
1118 * NC01 (0xA3C)
1119 */
1120 cmd->cmd = 0;
1121 cmd->src = paddr(&data->adm_mux_data_ack_req_nc01);
1122 cmd->dst = EBI2_NAND_ADM_MUX;
1123 cmd->len = 4;
1124 cmd++;
1125
1126 /* block on data ready from NC10
1127 * then read the status register
1128 */
1129 cmd->cmd = SRC_CRCI_NAND_DATA;
1130 cmd->src = NC10(NAND_FLASH_STATUS);
1131 cmd->dst = paddr(&data->result[n]);
1132 /* NAND_FLASH_STATUS +
1133 * NAND_BUFFER_STATUS
1134 */
1135 cmd->len = 4;
1136 cmd++;
1137 } else {
1138 /* MASK DATA ACK/REQ ->
1139 * NC01 (0xA3C)
1140 */
1141 cmd->cmd = 0;
1142 cmd->src = paddr(&data->adm_mux_data_ack_req_nc01);
1143 cmd->dst = EBI2_NAND_ADM_MUX;
1144 cmd->len = 4;
1145 cmd++;
1146
1147 /* block on data ready from NC10
1148 * then read the status register
1149 */
1150 cmd->cmd = SRC_CRCI_NAND_DATA;
1151 cmd->src = NC10(NAND_FLASH_STATUS);
1152 cmd->dst = paddr(&data->result[n]);
1153 /* NAND_FLASH_STATUS +
1154 * NAND_BUFFER_STATUS
1155 */
1156 cmd->len = 4;
1157 cmd++;
1158 }
1159 /* read data block */
1160 cmd->cmd = 0;
1161 cmd->src = NC10(NAND_FLASH_BUFFER);
1162 cmd->dst = addr + n * 516;
1163 cmd->len = ((n < (cwperpage -1 )) ? 516 : (512 - ((cwperpage - 1) << 2)));
1164 cmd++;
1165
1166 if (n == (cwperpage - 1)) {
1167 /* Use NC10 for reading the
1168 * last codeword!!!
1169 */
1170 cmd->cmd = 0;
1171 cmd->src = NC10(NAND_FLASH_BUFFER) +
1172 (512 - ((cwperpage -1) << 2));
1173 cmd->dst = spareaddr;
1174 cmd->len = 16;
1175 cmd++;
1176 }
1177 }
1178 }
1179 /* restore saved ecc config */
1180 cmd->cmd = CMD_OCU | CMD_LC;
1181 cmd->src = paddr(&data->ecc_cfg_save);
1182 cmd->dst = NAND_EBI2_ECC_BUF_CFG;
1183 cmd->len = 4;
1184
1185 /* ADM --> Default mux state (0xFC0) */
1186 cmd->cmd = 0;
1187 cmd->src = paddr(&data->adm_default_mux);
1188 cmd->dst = EBI2_NAND_ADM_MUX;
1189 cmd->len = 4;
1190 cmd++;
1191
1192 /* disable CS1 */
1193 cmd->cmd = 0;
1194 cmd->src = paddr(&data->default_ebi2_chip_select_cfg0);
1195 cmd->dst = EBI2_CHIP_SELECT_CFG0;
1196 cmd->len = 4;
1197 cmd++;
1198
1199 ptr[0] = (paddr(cmdlist) >> 3) | CMD_PTR_LP;
1200
1201 dmov_exec_cmdptr(DMOV_NAND_CHAN, ptr);
1202
1203#if VERBOSE
1204 dprintf(INFO, "read page %d: status: %x %x %x %x %x %x %x %x \
1205 %x %x %x %x %x %x %x %x \n", page,
1206 data->result[0].flash_status[0],
1207 data->result[1].flash_status[1],
1208 data->result[2].flash_status[2],
1209 data->result[3].flash_status[3],
1210 data->result[4].flash_status[4],
1211 data->result[5].flash_status[5],
1212 data->result[6].flash_status[6],
1213 data->result[7].flash_status[7],
1214 data->result[8].flash_status[8],
1215 data->result[9].flash_status[9],
1216 data->result[10].flash_status[10],
1217 data->result[11].flash_status[11],
1218 data->result[12].flash_status[12],
1219 data->result[13].flash_status[13],
1220 data->result[14].flash_status[14],
1221 data->result[15].flash_status[15]);
1222
1223 for(n = 0; n < 4; n++) {
1224 ptr = (unsigned*)(addr + 512 * n);
1225 dprintf(INFO, "data%d: %x %x %x %x\n", n, ptr[0], ptr[1], ptr[2], ptr[3]);
1226 ptr = (unsigned*)(spareaddr + 16 * n);
1227 dprintf(INFO, "spare data%d %x %x %x %x\n", n, ptr[0], ptr[1], ptr[2], ptr[3]);
1228 }
1229#endif
1230
1231 /* if any of the writes failed (0x10), or there was a
1232 ** protection violation (0x100), we lose
1233 */
1234 for(n = 0; n < cwperpage; n++) {
1235 if (data->result[n].flash_status & 0x110) {
1236 return -1;
1237 }
1238 }
1239
1240 return 0;
1241}
1242
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001243static int _flash_nand_write_page(dmov_s *cmdlist, unsigned *ptrlist, unsigned page,
Shashank Mittald0c836d2009-11-20 10:31:18 -08001244 const void *_addr, const void *_spareaddr, unsigned raw_mode)
Dima Zavin03cf4312009-01-23 16:38:30 -08001245{
1246 dmov_s *cmd = cmdlist;
1247 unsigned *ptr = ptrlist;
1248 struct data_flash_io *data = (void*) (ptrlist + 4);
1249 unsigned addr = (unsigned) _addr;
1250 unsigned spareaddr = (unsigned) _spareaddr;
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001251 unsigned n;
Shashank Mittaldcc2e352009-11-19 19:11:16 -08001252 unsigned cwperpage;
1253 cwperpage = (flash_pagesize >> 9);
Shashank Mittal8e49dec2010-03-01 15:19:04 -08001254 unsigned modem_partition = 0;
1255 if (CFG0 == CFG0_M)
1256 {
1257 modem_partition = 1;
1258 }
Dima Zavin03cf4312009-01-23 16:38:30 -08001259
1260 data->cmd = NAND_CMD_PRG_PAGE;
1261 data->addr0 = page << 16;
1262 data->addr1 = (page >> 16) & 0xff;
1263 data->chipsel = 0 | 4; /* flash0 + undoc bit */
Murali Palnatic54d13a2010-01-15 19:50:19 +05301264 data->clrfstatus = 0x00000020;
1265 data->clrrstatus = 0x000000C0;
Dima Zavin03cf4312009-01-23 16:38:30 -08001266
Shashank Mittald0c836d2009-11-20 10:31:18 -08001267 if (!raw_mode){
1268 data->cfg0 = CFG0;
1269 data->cfg1 = CFG1;
1270 }else{
1271 data->cfg0 = (NAND_CFG0_RAW & ~(7 << 6)) |((cwperpage-1) << 6);
1272 data->cfg1 = NAND_CFG1_RAW | (CFG1 & CFG1_WIDE_FLASH);
1273 }
Dima Zavin03cf4312009-01-23 16:38:30 -08001274
1275 /* GO bit for the EXEC register */
1276 data->exec = 1;
1277
Shashank Mittal8e49dec2010-03-01 15:19:04 -08001278 if (modem_partition)
1279 data->ecc_cfg = 0x1FF;
1280 else
1281 data->ecc_cfg = 0x203;
Dima Zavin03cf4312009-01-23 16:38:30 -08001282
1283 /* save existing ecc config */
1284 cmd->cmd = CMD_OCB;
1285 cmd->src = NAND_EBI2_ECC_BUF_CFG;
1286 cmd->dst = paddr(&data->ecc_cfg_save);
1287 cmd->len = 4;
1288 cmd++;
1289
Shashank Mittaldcc2e352009-11-19 19:11:16 -08001290 for(n = 0; n < cwperpage; n++) {
1291 /* write CMD / ADDR0 / ADDR1 / CHIPSEL regs in a burst */
Dima Zavin03cf4312009-01-23 16:38:30 -08001292 cmd->cmd = DST_CRCI_NAND_CMD;
1293 cmd->src = paddr(&data->cmd);
1294 cmd->dst = NAND_FLASH_CMD;
1295 cmd->len = ((n == 0) ? 16 : 4);
1296 cmd++;
1297
1298 if (n == 0) {
1299 /* set configuration */
1300 cmd->cmd = 0;
1301 cmd->src = paddr(&data->cfg0);
1302 cmd->dst = NAND_DEV0_CFG0;
1303 cmd->len = 8;
1304 cmd++;
1305
1306 /* set our ecc config */
1307 cmd->cmd = 0;
1308 cmd->src = paddr(&data->ecc_cfg);
1309 cmd->dst = NAND_EBI2_ECC_BUF_CFG;
1310 cmd->len = 4;
1311 cmd++;
1312 }
1313
1314 /* write data block */
1315 cmd->cmd = 0;
Dima Zavin03cf4312009-01-23 16:38:30 -08001316 cmd->dst = NAND_FLASH_BUFFER;
Shashank Mittald0c836d2009-11-20 10:31:18 -08001317 if (!raw_mode){
Shashank Mittal8e49dec2010-03-01 15:19:04 -08001318 if(modem_partition){
1319 cmd->src = addr + n * 512;
1320 cmd->len = 512;
1321 }else{
1322 cmd->src = addr + n * 516;
1323 cmd->len = ((n < (cwperpage - 1)) ? 516 : (512 - ((cwperpage - 1) << 2)));
1324 }
Shashank Mittald0c836d2009-11-20 10:31:18 -08001325 }else{
1326 cmd->src = addr;
1327 cmd->len = 528;
1328 }
Dima Zavin03cf4312009-01-23 16:38:30 -08001329 cmd++;
1330
Shashank Mittal8e49dec2010-03-01 15:19:04 -08001331 if ((n == (cwperpage - 1)) && (!raw_mode) && (!modem_partition)) {
Dima Zavin03cf4312009-01-23 16:38:30 -08001332 /* write extra data */
1333 cmd->cmd = 0;
1334 cmd->src = spareaddr;
Shashank Mittaldcc2e352009-11-19 19:11:16 -08001335 cmd->dst = NAND_FLASH_BUFFER + (512 - ((cwperpage - 1) << 2));
1336 cmd->len = (cwperpage << 2);
Dima Zavin03cf4312009-01-23 16:38:30 -08001337 cmd++;
1338 }
1339
1340 /* kick the execute register */
1341 cmd->cmd = 0;
1342 cmd->src = paddr(&data->exec);
1343 cmd->dst = NAND_EXEC_CMD;
1344 cmd->len = 4;
1345 cmd++;
1346
1347 /* block on data ready, then read the status register */
1348 cmd->cmd = SRC_CRCI_NAND_DATA;
1349 cmd->src = NAND_FLASH_STATUS;
1350 cmd->dst = paddr(&data->result[n]);
1351 cmd->len = 8;
1352 cmd++;
Murali Palnatic54d13a2010-01-15 19:50:19 +05301353
1354 cmd->cmd = 0;
1355 cmd->src = paddr(&data->clrfstatus);
1356 cmd->dst = NAND_FLASH_STATUS;
1357 cmd->len = 4;
1358 cmd++;
1359
1360 cmd->cmd = 0;
1361 cmd->src = paddr(&data->clrrstatus);
1362 cmd->dst = NAND_READ_STATUS;
1363 cmd->len = 4;
1364 cmd++;
Dima Zavin03cf4312009-01-23 16:38:30 -08001365 }
1366
1367 /* restore saved ecc config */
1368 cmd->cmd = CMD_OCU | CMD_LC;
1369 cmd->src = paddr(&data->ecc_cfg_save);
1370 cmd->dst = NAND_EBI2_ECC_BUF_CFG;
1371 cmd->len = 4;
1372
1373 ptr[0] = (paddr(cmdlist) >> 3) | CMD_PTR_LP;
1374
1375 dmov_exec_cmdptr(DMOV_NAND_CHAN, ptr);
1376
1377#if VERBOSE
1378 dprintf(INFO, "write page %d: status: %x %x %x %x\n",
1379 page, data[5], data[6], data[7], data[8]);
1380#endif
1381
1382 /* if any of the writes failed (0x10), or there was a
1383 ** protection violation (0x100), or the program success
1384 ** bit (0x80) is unset, we lose
1385 */
Shashank Mittaldcc2e352009-11-19 19:11:16 -08001386 for(n = 0; n < cwperpage; n++) {
Dima Zavin03cf4312009-01-23 16:38:30 -08001387 if(data->result[n].flash_status & 0x110) return -1;
1388 if(!(data->result[n].flash_status & 0x80)) return -1;
1389 }
1390
Dima Zavin5582c7d2009-03-03 15:17:59 -08001391#if VERIFY_WRITE
1392 n = _flash_read_page(cmdlist, ptrlist, page, flash_data,
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001393 flash_data + 2048);
Dima Zavin5582c7d2009-03-03 15:17:59 -08001394 if (n != 0)
1395 return -1;
1396 if (memcmp(flash_data, _addr, 2048) ||
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001397 memcmp(flash_data + 2048, _spareaddr, 16)) {
Dima Zavin5582c7d2009-03-03 15:17:59 -08001398 dprintf(CRITICAL, "verify error @ page %d\n", page);
1399 return -1;
1400 }
1401#endif
Dima Zavin03cf4312009-01-23 16:38:30 -08001402 return 0;
1403}
Murali Nalajalaa8c94c62010-03-05 20:24:30 +05301404
1405static int flash_nand_write_page_interleave(dmov_s *cmdlist, unsigned *ptrlist, unsigned page,
1406 const void *_addr, const void *_spareaddr, unsigned raw_mode)
1407{
1408 dmov_s *cmd = cmdlist;
1409 unsigned *ptr = ptrlist;
1410 struct interleave_data_flash_io *data = (void*) (ptrlist + 4);
1411 unsigned addr = (unsigned) _addr;
1412 unsigned spareaddr = (unsigned) _spareaddr;
1413 unsigned n;
1414 unsigned cwperpage, cwcount;
1415
1416 cwperpage = (flash_pagesize >> 9) * 2; /* double for interleave mode */
1417 cwcount = (cwperpage << 1);
1418
1419 data->cmd = NAND_CMD_PRG_PAGE;
1420 data->addr0 = page << 16;
1421 data->addr1 = (page >> 16) & 0xff;
1422 data->chipsel_cs0 = 0 | 4; /* flash0 + undoc bit */
1423 data->chipsel_cs1 = 0 | 5; /* flash0 + undoc bit */
1424 data->ebi2_chip_select_cfg0 = 0x00000805;
1425 data->adm_mux_data_ack_req_nc01 = 0x00000A3C;
1426 data->adm_mux_cmd_ack_req_nc01 = 0x0000053C;
1427 data->adm_mux_data_ack_req_nc10 = 0x00000F28;
1428 data->adm_mux_cmd_ack_req_nc10 = 0x00000F14;
1429 data->adm_default_mux = 0x00000FC0;
1430 data->default_ebi2_chip_select_cfg0 = 0x00000801;
1431
1432 if (!raw_mode){
1433 data->cfg0 = CFG0;
1434 data->cfg1 = CFG1;
1435 }else{
1436 data->cfg0 = (NAND_CFG0_RAW & ~(7 << 6)) |((cwcount-1) << 6);
1437 data->cfg1 = NAND_CFG1_RAW | (CFG1 & CFG1_WIDE_FLASH);
1438 }
1439
1440 /* GO bit for the EXEC register */
1441 data->exec = 1;
1442 data->ecc_cfg = 0x203;
1443
1444 for (n = 0; n < cwperpage; n++) {
1445 /* status return words */
1446 data->result[n].flash_status = 0xeeeeeeee;
1447
1448 if (n == 0) {
1449 /* enable CS1 */
1450 cmd->cmd = CMD_OCB;
1451 cmd->src = paddr(&data->ebi2_chip_select_cfg0);
1452 cmd->dst = EBI2_CHIP_SELECT_CFG0;
1453 cmd->len = 4;
1454 cmd++;
1455
1456 /* save existing ecc config */
1457 cmd->cmd = 0;
1458 cmd->src = NC11(NAND_EBI2_ECC_BUF_CFG);
1459 cmd->dst = paddr(&data->ecc_cfg_save);
1460 cmd->len = 4;
1461 cmd++;
1462
1463 cmd->cmd = 0;
1464 cmd->src = paddr(&data->ecc_cfg);
1465 cmd->dst = NC11(NAND_EBI2_ECC_BUF_CFG);
1466 cmd->len = 4;
1467 cmd++;
1468
1469 cmd->cmd = 0;
1470 cmd->src = paddr(&data->addr0);
1471 cmd->dst = NC11(NAND_ADDR0);
1472 cmd->len = 8;
1473 cmd++;
1474
1475 /* enable CS0 */
1476 cmd->cmd = 0;
1477 cmd->src = paddr(&data->chipsel_cs0);
1478 cmd->dst = NC01(NAND_FLASH_CHIP_SELECT);
1479 cmd->len = 4;
1480 cmd++;
1481
1482 /* enable CS1 */
1483 cmd->cmd = 0;
1484 cmd->src = paddr(&data->chipsel_cs1);
1485 cmd->dst = NC10(NAND_FLASH_CHIP_SELECT);
1486 cmd->len = 4;
1487 cmd++;
1488
1489 cmd->cmd = 0;
1490 cmd->src =paddr(&data->cfg0);
1491 cmd->dst = NC01(NAND_DEV0_CFG0);
1492 cmd->len = 8;
1493 cmd++;
1494
1495 /* config CFG1 for CS1 */
1496 cmd->cmd = 0;
1497 cmd->src =paddr(&data->cfg0);
1498 cmd->dst = NC10(NAND_DEV1_CFG0);
1499 cmd->len = 8;
1500 cmd++;
1501 }
1502
1503 if (n % 2 == 0) {
1504 /* MASK CMD ACK/REQ --> NC10 (0xF14)*/
1505 cmd->cmd = 0;
1506 cmd->src = paddr(&data->adm_mux_cmd_ack_req_nc10);
1507 cmd->dst = EBI2_NAND_ADM_MUX;
1508 cmd->len = 4;
1509 cmd++;
1510
1511 /* CMD */
1512 cmd->cmd = DST_CRCI_NAND_CMD;
1513 cmd->src = paddr(&data->cmd);
1514 cmd->dst = NC01(NAND_FLASH_CMD);
1515 cmd->len = 4;
1516 cmd++;
1517 } else {
1518 /* MASK CMD ACK/REQ --> NC01 (0x53C)*/
1519 cmd->cmd = 0;
1520 cmd->src = paddr(&data->adm_mux_cmd_ack_req_nc01);
1521 cmd->dst = EBI2_NAND_ADM_MUX;
1522 cmd->len = 4;
1523 cmd++;
1524
1525 /* CMD */
1526 cmd->cmd = DST_CRCI_NAND_CMD;
1527 cmd->src = paddr(&data->cmd);
1528 cmd->dst = NC10(NAND_FLASH_CMD);
1529 cmd->len = 4;
1530 cmd++;
1531 }
1532
1533 cmd->cmd = 0;
1534 if (!raw_mode){
1535 cmd->src = addr + n * 516;
1536 cmd->len = ((n < (cwperpage - 1)) ? 516 : (512 - ((cwperpage - 1) << 2)));
1537 }else{
1538 cmd->src = addr;
1539 cmd->len = 528;
1540 }
1541
1542 if (n % 2 == 0)
1543 cmd->dst = NC01(NAND_FLASH_BUFFER);
1544 else
1545 cmd->dst = NC10(NAND_FLASH_BUFFER);
1546 cmd++;
1547
1548 if ((n == (cwperpage - 1)) && (!raw_mode)) {
1549 /* write extra data */
1550 cmd->cmd = 0;
1551 cmd->src = spareaddr;
1552 cmd->dst = NC10(NAND_FLASH_BUFFER) + (512 - ((cwperpage - 1) << 2));
1553 cmd->len = (cwperpage << 2);
1554 cmd++;
1555 }
1556
1557 if (n % 2 == 0) {
1558 /* kick the NC01 execute register */
1559 cmd->cmd = 0;
1560 cmd->src = paddr(&data->exec);
1561 cmd->dst = NC01(NAND_EXEC_CMD);
1562 cmd->len = 4;
1563 cmd++;
1564 if (n != 0) {
1565 /* MASK DATA ACK/REQ --> NC01 (0xA3C)*/
1566 cmd->cmd = 0;
1567 cmd->src = paddr(&data->adm_mux_data_ack_req_nc01);
1568 cmd->dst = EBI2_NAND_ADM_MUX;
1569 cmd->len = 4;
1570 cmd++;
1571
1572 /* block on data ready from NC10, then
1573 * read the status register
1574 */
1575 cmd->cmd = SRC_CRCI_NAND_DATA;
1576 cmd->src = NC10(NAND_FLASH_STATUS);
1577 cmd->dst = paddr(&data->result[n-1]);
1578 cmd->len = 4;
1579 cmd++;
1580 }
1581 } else {
1582 /* kick the execute register */
1583 cmd->cmd = 0;
1584 cmd->src = paddr(&data->exec);
1585 cmd->dst = NC10(NAND_EXEC_CMD);
1586 cmd->len = 4;
1587 cmd++;
1588
1589 /* MASK DATA ACK/REQ --> NC10 (0xF28)*/
1590 cmd->cmd = 0;
1591 cmd->src = paddr(&data->adm_mux_data_ack_req_nc10);
1592 cmd->dst = EBI2_NAND_ADM_MUX;
1593 cmd->len = 4;
1594 cmd++;
1595
1596 /* block on data ready from NC01, then
1597 * read the status register
1598 */
1599 cmd->cmd = SRC_CRCI_NAND_DATA;
1600 cmd->src = NC01(NAND_FLASH_STATUS);
1601 cmd->dst = paddr(&data->result[n-1]);
1602 cmd->len = 4;
1603 cmd++;
1604 }
1605 }
1606
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 /* we should process outstanding request */
1615 /* block on data ready, then
1616 * read the status register
1617 */
1618 cmd->cmd = SRC_CRCI_NAND_DATA;
1619 cmd->src = NC10(NAND_FLASH_STATUS);
1620 cmd->dst = paddr(&data->result[n-1]);
1621 cmd->len = 4;
1622 cmd++;
1623
1624 /* restore saved ecc config */
1625 cmd->cmd = 0;
1626 cmd->src = paddr(&data->ecc_cfg_save);
1627 cmd->dst = NAND_EBI2_ECC_BUF_CFG;
1628 cmd->len = 4;
1629
1630 /* MASK DATA ACK/REQ --> NC01 (0xFC0)*/
1631 cmd->cmd = 0;
1632 cmd->src = paddr(&data->adm_default_mux);
1633 cmd->dst = EBI2_NAND_ADM_MUX;
1634 cmd->len = 4;
1635 cmd++;
1636
1637 /* disable CS1 */
1638 cmd->cmd = CMD_OCU | CMD_LC;
1639 cmd->src = paddr(&data->default_ebi2_chip_select_cfg0);
1640 cmd->dst = EBI2_CHIP_SELECT_CFG0;
1641 cmd->len = 4;
1642 cmd++;
1643
1644 ptr[0] = (paddr(cmdlist) >> 3) | CMD_PTR_LP;
1645
1646 dmov_exec_cmdptr(DMOV_NAND_CHAN, ptr);
1647
1648#if VERBOSE
1649dprintf(INFO, "write page %d: status: %x %x %x %x %x %x %x %x \
1650 %x %x %x %x %x %x %x %x \n", page,
1651 data->result[0].flash_status[0],
1652 data->result[1].flash_status[1],
1653 data->result[2].flash_status[2],
1654 data->result[3].flash_status[3],
1655 data->result[4].flash_status[4],
1656 data->result[5].flash_status[5],
1657 data->result[6].flash_status[6],
1658 data->result[7].flash_status[7],
1659 data->result[8].flash_status[8],
1660 data->result[9].flash_status[9],
1661 data->result[10].flash_status[10],
1662 data->result[11].flash_status[11],
1663 data->result[12].flash_status[12],
1664 data->result[13].flash_status[13],
1665 data->result[14].flash_status[14],
1666 data->result[15].flash_status[15]);
1667#endif
1668
1669 /* if any of the writes failed (0x10), or there was a
1670 ** protection violation (0x100), or the program success
1671 ** bit (0x80) is unset, we lose
1672 */
1673 for(n = 0; n < cwperpage; n++) {
1674 if(data->result[n].flash_status & 0x110) return -1;
1675 if(!(data->result[n].flash_status & 0x80)) return -1;
1676 }
1677
1678#if VERIFY_WRITE
1679 n = _flash_read_page(cmdlist, ptrlist, page, flash_data,
1680 flash_data + 2048);
1681 if (n != 0)
1682 return -1;
1683 if (memcmp(flash_data, _addr, 2048) ||
1684 memcmp(flash_data + 2048, _spareaddr, 16)) {
1685 dprintf(CRITICAL, "verify error @ page %d\n", page);
1686 return -1;
1687 }
1688#endif
1689 return 0;
1690}
1691
Shashank Mittald0c836d2009-11-20 10:31:18 -08001692char empty_buf[528];
1693static int flash_nand_mark_badblock(dmov_s *cmdlist, unsigned *ptrlist, unsigned page)
1694{
1695 memset(empty_buf,0,528);
1696 /* Going to first page of the block */
Channagoud Kadabibeb17d52011-03-25 17:14:00 +05301697 if(page & num_pages_per_blk_mask)
1698 page = page - (page & num_pages_per_blk_mask);
Shashank Mittald0c836d2009-11-20 10:31:18 -08001699 return _flash_nand_write_page(cmdlist, ptrlist, page, empty_buf, 0, 1);
1700}
Dima Zavin03cf4312009-01-23 16:38:30 -08001701
Shashank Mittal83d16d02009-11-18 16:54:42 -08001702unsigned nand_cfg0;
1703unsigned nand_cfg1;
1704
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001705static int flash_nand_read_config(dmov_s *cmdlist, unsigned *ptrlist)
Dima Zavin03cf4312009-01-23 16:38:30 -08001706{
Shashank Mittal8e49dec2010-03-01 15:19:04 -08001707 static unsigned CFG0_TMP, CFG1_TMP;
Dima Zavin03cf4312009-01-23 16:38:30 -08001708 cmdlist[0].cmd = CMD_OCB;
1709 cmdlist[0].src = NAND_DEV0_CFG0;
Shashank Mittal8e49dec2010-03-01 15:19:04 -08001710 cmdlist[0].dst = paddr(&CFG0_TMP);
Dima Zavin03cf4312009-01-23 16:38:30 -08001711 cmdlist[0].len = 4;
1712
1713 cmdlist[1].cmd = CMD_OCU | CMD_LC;
1714 cmdlist[1].src = NAND_DEV0_CFG1;
Shashank Mittal8e49dec2010-03-01 15:19:04 -08001715 cmdlist[1].dst = paddr(&CFG1_TMP);
Dima Zavin03cf4312009-01-23 16:38:30 -08001716 cmdlist[1].len = 4;
1717
1718 *ptrlist = (paddr(cmdlist) >> 3) | CMD_PTR_LP;
1719
1720 dmov_exec_cmdptr(DMOV_NAND_CHAN, ptrlist);
1721
Shashank Mittal8e49dec2010-03-01 15:19:04 -08001722 if((CFG0_TMP == 0) || (CFG1_TMP == 0)) {
Dima Zavin03cf4312009-01-23 16:38:30 -08001723 return -1;
1724 }
1725
Shashank Mittal8e49dec2010-03-01 15:19:04 -08001726 CFG0_A = CFG0_TMP;
1727 CFG1_A = CFG1_TMP;
Shashank Mittal83d16d02009-11-18 16:54:42 -08001728 if (flash_info.type == FLASH_16BIT_NAND_DEVICE) {
1729 nand_cfg1 |= CFG1_WIDE_FLASH;
1730 }
Dima Zavin03cf4312009-01-23 16:38:30 -08001731 dprintf(INFO, "nandcfg: %x %x (initial)\n", CFG0, CFG1);
1732
Shashank Mittal8e49dec2010-03-01 15:19:04 -08001733 CFG0_A = (((flash_pagesize >> 9) - 1) << 6) /* 4/8 cw/pg for 2/4k */
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001734 | (516 << 9) /* 516 user data bytes */
1735 | (10 << 19) /* 10 parity bytes */
1736 | (5 << 27) /* 5 address cycles */
Murali Palnatic54d13a2010-01-15 19:50:19 +05301737 | (0 << 30) /* Do not read status before data */
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001738 | (1 << 31) /* Send read cmd */
1739 /* 0 spare bytes for 16 bit nand or 1 spare bytes for 8 bit */
1740 | ((nand_cfg1 & CFG1_WIDE_FLASH) ? (0 << 23) : (1 << 23));
Shashank Mittal8e49dec2010-03-01 15:19:04 -08001741 CFG1_A = (0 << 0) /* Enable ecc */
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001742 | (7 << 2) /* 8 recovery cycles */
1743 | (0 << 5) /* Allow CS deassertion */
Shashank Mittaldcc2e352009-11-19 19:11:16 -08001744 | ((flash_pagesize - (528 * ((flash_pagesize >> 9) - 1)) + 1) << 6) /* Bad block marker location */
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001745 | (0 << 16) /* Bad block in user data area */
1746 | (2 << 17) /* 6 cycle tWB/tRB */
1747 | (nand_cfg1 & CFG1_WIDE_FLASH); /* preserve wide flash flag */
Dima Zavin03cf4312009-01-23 16:38:30 -08001748
Shashank Mittal8e49dec2010-03-01 15:19:04 -08001749 dprintf(INFO, "nandcfg(Apps): %x %x (used)\n", CFG0_A, CFG1_A);
Dima Zavin03cf4312009-01-23 16:38:30 -08001750
Shashank Mittal8e49dec2010-03-01 15:19:04 -08001751 CFG0_M = CFG0_TMP;
1752 CFG1_M = CFG1_TMP;
1753 if (flash_info.type == FLASH_16BIT_NAND_DEVICE) {
1754 nand_cfg1 |= CFG1_WIDE_FLASH;
1755 }
1756 CFG0_M = (((flash_pagesize >> 9) - 1) << 6) /* 4/8 cw/pg for 2/4k */
1757 | (512 << 9) /* 512 user data bytes */
1758 | (10 << 19) /* 10 parity bytes */
1759 | (5 << 27) /* 5 address cycles */
1760 | (0 << 30) /* Do not read status before data */
1761 | (1 << 31) /* Send read cmd */
1762 | ((nand_cfg1 & CFG1_WIDE_FLASH) ? (4 << 23) : (5 << 23));
1763 CFG1_M = (0 << 0) /* Enable ecc */
1764 | (7 << 2) /* 8 recovery cycles */
1765 | (0 << 5) /* Allow CS deassertion */
1766 | ((flash_pagesize - (528 * ((flash_pagesize >> 9) - 1)) + 1) << 6) /* Bad block marker location */
1767 | (0 << 16) /* Bad block in user data area */
1768 | (2 << 17) /* 6 cycle tWB/tRB */
1769 | (nand_cfg1 & CFG1_WIDE_FLASH); /* preserve wide flash flag */
1770 dprintf(INFO, "nandcfg(Modem): %x %x (used)\n", CFG0_M, CFG1_M);
Dima Zavin03cf4312009-01-23 16:38:30 -08001771 return 0;
1772}
1773
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001774/* OneNAND programming functions */
1775
1776static void flash_onenand_read_id(dmov_s *cmdlist, unsigned *ptrlist)
1777{
1778 dmov_s *cmd = cmdlist;
1779 unsigned *ptr = ptrlist;
1780 unsigned *data = ptrlist + 4;
1781
1782 data[0] = SFLASH_BCFG;
1783 data[1] = SFLASH_PREPCMD(8, 0, 0, NAND_SFCMD_DATXS, NAND_SFCMD_ASYNC, NAND_SFCMD_REGRD);
1784 data[2] = (ONENAND_DEVICE_ID << 16) | (ONENAND_MANUFACTURER_ID);
1785 data[3] = (ONENAND_DATA_BUFFER_SIZE << 16) | (ONENAND_VERSION_ID);
1786 data[4] = (ONENAND_AMOUNT_OF_BUFFERS << 16) | (ONENAND_BOOT_BUFFER_SIZE);
1787 data[5] = (CLEAN_DATA_16 << 16) | (ONENAND_TECHNOLOGY);
1788 data[6] = CLEAN_DATA_32; //status
1789 data[7] = CLEAN_DATA_32; //register read
1790 data[8] = CLEAN_DATA_32; //register read
1791 data[9] = CLEAN_DATA_32; //register read
1792 data[10] = CLEAN_DATA_32; //register read
1793 data[11] = 1;
1794 data[12] = 0 | 4;
1795
1796 /* Setup controller in SFLASH mode */
1797 cmd[0].cmd = 0 | CMD_OCB;
1798 cmd[0].src = paddr(&data[0]);
1799 cmd[0].dst = NAND_SFLASHC_BURST_CFG;
1800 cmd[0].len = 4;
1801
1802 /* Enable data mover for controller */
1803 cmd[1].cmd = 0;
1804 cmd[1].src = paddr(&data[12]);
1805 cmd[1].dst = NAND_FLASH_CHIP_SELECT;
1806 cmd[1].len = 4;
1807
1808 /* Setup SFLASHC_CMD with xfers in async mode */
1809 cmd[2].cmd = DST_CRCI_NAND_CMD;
1810 cmd[2].src = paddr(&data[1]);
1811 cmd[2].dst = NAND_SFLASHC_CMD;
1812 cmd[2].len = 4;
1813
1814 /* Setup to read device information */
1815 cmd[3].cmd = 0;
1816 cmd[3].src = paddr(&data[2]);
1817 cmd[3].dst = NAND_ADDR0;
1818 cmd[3].len = 8;
1819
1820 cmd[4].cmd = 0;
1821 cmd[4].src = paddr(&data[4]);
1822 cmd[4].dst = NAND_ADDR2;
1823 cmd[4].len = 8;
1824
1825 /* Set execute bit */
1826 cmd[5].cmd = 0;
1827 cmd[5].src = paddr(&data[11]);
1828 cmd[5].dst = NAND_SFLASHC_EXEC_CMD;
1829 cmd[5].len = 4;
1830
1831 /* Check status */
1832 cmd[6].cmd = SRC_CRCI_NAND_DATA;
1833 cmd[6].src = NAND_SFLASHC_STATUS;
1834 cmd[6].dst = paddr(&data[6]);
1835 cmd[6].len = 4;
1836
1837 /* Read result device registers */
1838 cmd[7].cmd = 0 | CMD_OCU | CMD_LC;
1839 cmd[7].src = NAND_GENP_REG0;
1840 cmd[7].dst = paddr(&data[7]);
1841 cmd[7].len = 16;
1842
1843 ptr[0] = (paddr(cmd) >> 3) | CMD_PTR_LP;
1844
1845 dmov_exec_cmdptr(DMOV_NAND_CHAN, ptr);
1846
1847#if VERBOSE
1848 dprintf(INFO, "status: %x\n", data[6]);
1849#endif
1850
1851 flash_info.id = data[7];
1852 flash_info.vendor = data[7] & CLEAN_DATA_16;
1853 flash_info.device = (data[7] >> 16) & CLEAN_DATA_16;
1854 return;
1855}
1856
1857
1858struct data_onenand_erase {
1859 unsigned sfbcfg;
1860 unsigned sfcmd[4];
1861 unsigned sfexec;
1862 unsigned sfstat[4];
1863 unsigned addr0;
1864 unsigned addr1;
1865 unsigned addr2;
1866 unsigned addr3;
1867 unsigned addr4;
1868 unsigned addr5;
1869 unsigned addr6;
1870 unsigned data0;
1871 unsigned data1;
1872 unsigned data2;
1873 unsigned data3;
1874 unsigned data4;
1875 unsigned data5;
1876 unsigned data6;
1877};
1878
Shashank Mittalad3d05c2009-11-19 15:53:57 -08001879
1880static int _flash_onenand_read_page(dmov_s *cmdlist, unsigned *ptrlist,
1881 unsigned page, void *_addr,
1882 void *_spareaddr, unsigned raw_mode);
1883
1884
1885static int flash_onenand_block_isbad(dmov_s *cmdlist, unsigned *ptrlist,
1886 unsigned page)
1887{
1888 unsigned char page_data[2112];
1889 unsigned char *oobptr = &(page_data[2048]);
1890
1891 /* Going to first page of the block */
Channagoud Kadabibeb17d52011-03-25 17:14:00 +05301892 if(page & num_pages_per_blk_mask)
1893 page = page - (page & num_pages_per_blk_mask);
Shashank Mittalad3d05c2009-11-19 15:53:57 -08001894
1895 /* Reading page in raw mode */
1896 if (_flash_onenand_read_page(cmdlist, ptrlist,page, page_data, 0, 1))
1897 return 1;
1898
1899 /* Checking if block is bad */
1900 if ((oobptr[0] != 0xFF) || (oobptr[1] != 0xFF) ||
1901 (oobptr[16] != 0xFF) || (oobptr[17] != 0xFF) ||
1902 (oobptr[32] != 0xFF) || (oobptr[33] != 0xFF) ||
1903 (oobptr[48] != 0xFF) || (oobptr[49] != 0xFF)
1904 )
1905 {
1906 return 1;
1907 }
1908 return 0;
1909}
1910
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001911static int flash_onenand_erase_block(dmov_s *cmdlist, unsigned *ptrlist,
1912 unsigned page)
1913{
1914 dmov_s *cmd = cmdlist;
1915 unsigned *ptr = ptrlist;
1916 struct data_onenand_erase *data = (void *)ptrlist + 4;
Shashank Mittalad3d05c2009-11-19 15:53:57 -08001917 int isbad = 0;
Channagoud Kadabibeb17d52011-03-25 17:14:00 +05301918 unsigned erasesize = (flash_pagesize * num_pages_per_blk);
Shashank Mittaldcc2e352009-11-19 19:11:16 -08001919 unsigned onenand_startaddr1 = DEVICE_FLASHCORE_0 | (page * flash_pagesize)/erasesize;
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001920 unsigned onenand_startaddr8 = 0x0000;
1921 unsigned onenand_startaddr2 = DEVICE_BUFFERRAM_0 << 15;
1922 unsigned onenand_startbuffer = DATARAM0_0 << 8;
1923
1924 unsigned controller_status;
1925 unsigned interrupt_status;
1926 unsigned ecc_status;
1927
Shashank Mittaldcc2e352009-11-19 19:11:16 -08001928 if((page * flash_pagesize) & (erasesize-1)) return -1;
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001929
Shashank Mittalad3d05c2009-11-19 15:53:57 -08001930 /* Check for bad block and erase only if block is not marked bad */
1931 isbad = flash_onenand_block_isbad(cmdlist, ptrlist, page);
1932 if (isbad)
1933 {
Channagoud Kadabibeb17d52011-03-25 17:14:00 +05301934 dprintf(INFO, "skipping @ %d (bad block)\n", page / num_pages_per_blk);
Shashank Mittalad3d05c2009-11-19 15:53:57 -08001935 return -1;
1936 }
1937
1938 /*Erase block*/
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001939 onenand_startaddr1 = DEVICE_FLASHCORE_0 |
Shashank Mittaldcc2e352009-11-19 19:11:16 -08001940 ((page * flash_pagesize) / (erasesize));
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001941 onenand_startaddr8 = 0x0000;
1942 onenand_startaddr2 = DEVICE_BUFFERRAM_0 << 15;
1943 onenand_startbuffer = DATARAM0_0 << 8;
1944
1945
1946 data->sfbcfg = SFLASH_BCFG;
1947 data->sfcmd[0] = SFLASH_PREPCMD(7, 0, 0,
1948 NAND_SFCMD_CMDXS,
1949 NAND_SFCMD_ASYNC,
1950 NAND_SFCMD_REGWR);
1951 data->sfcmd[1] = SFLASH_PREPCMD(0, 0, 32,
1952 NAND_SFCMD_CMDXS,
1953 NAND_SFCMD_ASYNC,
1954 NAND_SFCMD_INTHI);
1955 data->sfcmd[2] = SFLASH_PREPCMD(3, 7, 0,
1956 NAND_SFCMD_DATXS,
1957 NAND_SFCMD_ASYNC,
1958 NAND_SFCMD_REGRD);
1959 data->sfcmd[3] = SFLASH_PREPCMD(4, 10, 0,
1960 NAND_SFCMD_CMDXS,
1961 NAND_SFCMD_ASYNC,
1962 NAND_SFCMD_REGWR);
1963 data->sfexec = 1;
1964 data->sfstat[0] = CLEAN_DATA_32;
1965 data->sfstat[1] = CLEAN_DATA_32;
1966 data->sfstat[2] = CLEAN_DATA_32;
1967 data->sfstat[3] = CLEAN_DATA_32;
1968 data->addr0 = (ONENAND_INTERRUPT_STATUS << 16) |
1969 (ONENAND_SYSTEM_CONFIG_1);
1970 data->addr1 = (ONENAND_START_ADDRESS_8 << 16) |
1971 (ONENAND_START_ADDRESS_1);
1972 data->addr2 = (ONENAND_START_BUFFER << 16) |
1973 (ONENAND_START_ADDRESS_2);
1974 data->addr3 = (ONENAND_ECC_STATUS << 16) |
1975 (ONENAND_COMMAND);
1976 data->addr4 = (ONENAND_CONTROLLER_STATUS << 16) |
1977 (ONENAND_INTERRUPT_STATUS);
1978 data->addr5 = (ONENAND_INTERRUPT_STATUS << 16) |
1979 (ONENAND_SYSTEM_CONFIG_1);
1980 data->addr6 = (ONENAND_START_ADDRESS_3 << 16) |
1981 (ONENAND_START_ADDRESS_1);
1982 data->data0 = (ONENAND_CLRINTR << 16) |
1983 (ONENAND_SYSCFG1_ECCENA);
1984 data->data1 = (onenand_startaddr8 << 16) |
1985 (onenand_startaddr1);
1986 data->data2 = (onenand_startbuffer << 16) |
1987 (onenand_startaddr2);
1988 data->data3 = (CLEAN_DATA_16 << 16) |
1989 (ONENAND_CMDERAS);
1990 data->data4 = (CLEAN_DATA_16 << 16) |
1991 (CLEAN_DATA_16);
1992 data->data5 = (ONENAND_CLRINTR << 16) |
1993 (ONENAND_SYSCFG1_ECCENA);
1994 data->data6 = (ONENAND_STARTADDR3_RES << 16) |
1995 (ONENAND_STARTADDR1_RES);
1996
1997 /***************************************************************/
1998 /* Write the necessary address registers in the onenand device */
1999 /***************************************************************/
2000
2001 /* Enable and configure the SFlash controller */
2002 cmd->cmd = 0 | CMD_OCB;
2003 cmd->src = paddr(&data->sfbcfg);
2004 cmd->dst = NAND_SFLASHC_BURST_CFG;
2005 cmd->len = 4;
2006 cmd++;
2007
2008 /* Block on cmd ready and write CMD register */
2009 cmd->cmd = DST_CRCI_NAND_CMD;
2010 cmd->src = paddr(&data->sfcmd[0]);
2011 cmd->dst = NAND_SFLASHC_CMD;
2012 cmd->len = 4;
2013 cmd++;
2014
2015 /* Write the ADDR0 and ADDR1 registers */
2016 cmd->cmd = 0;
2017 cmd->src = paddr(&data->addr0);
2018 cmd->dst = NAND_ADDR0;
2019 cmd->len = 8;
2020 cmd++;
2021
2022 /* Write the ADDR2 ADDR3 ADDR4 ADDR5 registers */
2023 cmd->cmd = 0;
2024 cmd->src = paddr(&data->addr2);
2025 cmd->dst = NAND_ADDR2;
2026 cmd->len = 16;
2027 cmd++;
2028
2029 /* Write the ADDR6 registers */
2030 cmd->cmd = 0;
2031 cmd->src = paddr(&data->addr6);
2032 cmd->dst = NAND_ADDR6;
2033 cmd->len = 4;
2034 cmd++;
2035
2036 /* Write the GENP0, GENP1, GENP2, GENP3, GENP4 registers */
2037 cmd->cmd = 0;
2038 cmd->src = paddr(&data->data0);
2039 cmd->dst = NAND_GENP_REG0;
2040 cmd->len = 16;
2041 cmd++;
2042
2043 /* Write the FLASH_DEV_CMD4,5,6 registers */
2044 cmd->cmd = 0;
2045 cmd->src = paddr(&data->data4);
2046 cmd->dst = NAND_DEV_CMD4;
2047 cmd->len = 12;
2048 cmd++;
2049
2050 /* Kick the execute command */
2051 cmd->cmd = 0;
2052 cmd->src = paddr(&data->sfexec);
2053 cmd->dst = NAND_SFLASHC_EXEC_CMD;
2054 cmd->len = 4;
2055 cmd++;
2056
2057 /* Block on data ready, and read the status register */
2058 cmd->cmd = SRC_CRCI_NAND_DATA;
2059 cmd->src = NAND_SFLASHC_STATUS;
2060 cmd->dst = paddr(&data->sfstat[0]);
2061 cmd->len = 4;
2062 cmd++;
2063
2064 /***************************************************************/
2065 /* Wait for the interrupt from the Onenand device controller */
2066 /***************************************************************/
2067
2068 /* Block on cmd ready and write CMD register */
2069 cmd->cmd = DST_CRCI_NAND_CMD;
2070 cmd->src = paddr(&data->sfcmd[1]);
2071 cmd->dst = NAND_SFLASHC_CMD;
2072 cmd->len = 4;
2073 cmd++;
2074
2075 /* Kick the execute command */
2076 cmd->cmd = 0;
2077 cmd->src = paddr(&data->sfexec);
2078 cmd->dst = NAND_SFLASHC_EXEC_CMD;
2079 cmd->len = 4;
2080 cmd++;
2081
2082 /* Block on data ready, and read the status register */
2083 cmd->cmd = SRC_CRCI_NAND_DATA;
2084 cmd->src = NAND_SFLASHC_STATUS;
2085 cmd->dst = paddr(&data->sfstat[1]);
2086 cmd->len = 4;
2087 cmd++;
2088
2089 /***************************************************************/
2090 /* Read the necessary status registers from the onenand device */
2091 /***************************************************************/
2092
2093 /* Block on cmd ready and write CMD register */
2094 cmd->cmd = DST_CRCI_NAND_CMD;
2095 cmd->src = paddr(&data->sfcmd[2]);
2096 cmd->dst = NAND_SFLASHC_CMD;
2097 cmd->len = 4;
2098 cmd++;
2099
2100 /* Kick the execute command */
2101 cmd->cmd = 0;
2102 cmd->src = paddr(&data->sfexec);
2103 cmd->dst = NAND_SFLASHC_EXEC_CMD;
2104 cmd->len = 4;
2105 cmd++;
2106
2107 /* Block on data ready, and read the status register */
2108 cmd->cmd = SRC_CRCI_NAND_DATA;
2109 cmd->src = NAND_SFLASHC_STATUS;
2110 cmd->dst = paddr(&data->sfstat[2]);
2111 cmd->len = 4;
2112 cmd++;
2113
2114 /* Read the GENP3 register */
2115 cmd->cmd = 0;
2116 cmd->src = NAND_GENP_REG3;
2117 cmd->dst = paddr(&data->data3);
2118 cmd->len = 4;
2119 cmd++;
2120
2121 /* Read the DEVCMD4 register */
2122 cmd->cmd = 0;
2123 cmd->src = NAND_DEV_CMD4;
2124 cmd->dst = paddr(&data->data4);
2125 cmd->len = 4;
2126 cmd++;
2127
2128 /***************************************************************/
2129 /* Restore the necessary registers to proper values */
2130 /***************************************************************/
2131
2132 /* Block on cmd ready and write CMD register */
2133 cmd->cmd = DST_CRCI_NAND_CMD;
2134 cmd->src = paddr(&data->sfcmd[3]);
2135 cmd->dst = NAND_SFLASHC_CMD;
2136 cmd->len = 4;
2137 cmd++;
2138
2139 /* Kick the execute command */
2140 cmd->cmd = 0;
2141 cmd->src = paddr(&data->sfexec);
2142 cmd->dst = NAND_SFLASHC_EXEC_CMD;
2143 cmd->len = 4;
2144 cmd++;
2145
2146 /* Block on data ready, and read the status register */
2147 cmd->cmd = SRC_CRCI_NAND_DATA | CMD_OCU | CMD_LC;
2148 cmd->src = NAND_SFLASHC_STATUS;
2149 cmd->dst = paddr(&data->sfstat[3]);
2150 cmd->len = 4;
2151 cmd++;
2152
2153 ptr[0] = (paddr(cmdlist) >> 3) | CMD_PTR_LP;
2154
2155 dmov_exec_cmdptr(DMOV_NAND_CHAN, ptr);
2156
2157 ecc_status = (data->data3 >> 16) & 0x0000FFFF;
2158 interrupt_status = (data->data4 >> 0) & 0x0000FFFF;
2159 controller_status = (data->data4 >> 16) & 0x0000FFFF;
2160
2161#if VERBOSE
2162 dprintf(INFO, "\n%s: sflash status %x %x %x %x\n", __func__,
2163 data->sfstat[0],
2164 data->sfstat[1],
2165 data->sfstat[2],
2166 data->sfstat[3]);
2167
2168 dprintf(INFO, "%s: controller_status = %x\n", __func__,
2169 controller_status);
2170 dprintf(INFO, "%s: interrupt_status = %x\n", __func__,
2171 interrupt_status);
2172 dprintf(INFO, "%s: ecc_status = %x\n", __func__,
2173 ecc_status);
2174#endif
2175 /* Check for errors, protection violations etc */
2176 if ((controller_status != 0)
2177 || (data->sfstat[0] & 0x110)
2178 || (data->sfstat[1] & 0x110)
2179 || (data->sfstat[2] & 0x110)
2180 || (data->sfstat[3] & 0x110)) {
2181 dprintf(CRITICAL, "%s: ECC/MPU/OP error\n", __func__);
2182 return -1;
2183 }
2184
2185
2186#if VERBOSE
2187 dprintf(INFO, "status: %x\n", data[5]);
2188#endif
2189
2190 return 0;
2191}
2192
2193
2194struct data_onenand_read {
2195 unsigned sfbcfg;
2196 unsigned sfcmd[9];
2197 unsigned sfexec;
2198 unsigned sfstat[9];
2199 unsigned addr0;
2200 unsigned addr1;
2201 unsigned addr2;
2202 unsigned addr3;
2203 unsigned addr4;
2204 unsigned addr5;
2205 unsigned addr6;
2206 unsigned data0;
2207 unsigned data1;
2208 unsigned data2;
2209 unsigned data3;
2210 unsigned data4;
2211 unsigned data5;
2212 unsigned data6;
2213 unsigned macro[5];
2214};
2215
2216
2217static int _flash_onenand_read_page(dmov_s *cmdlist, unsigned *ptrlist,
Shashank Mittalad3d05c2009-11-19 15:53:57 -08002218 unsigned page, void *_addr, void *_spareaddr,
2219 unsigned raw_mode)
Shashank Mittalc20b5a12009-11-18 19:35:30 -08002220{
2221 dmov_s *cmd = cmdlist;
2222 unsigned *ptr = ptrlist;
2223 struct data_onenand_read *data = (void*) (ptrlist + 4);
2224 unsigned addr = (unsigned) _addr;
2225 unsigned curr_addr = (unsigned) _addr;
2226 unsigned spareaddr = (unsigned) _spareaddr;
2227 unsigned i;
Channagoud Kadabibeb17d52011-03-25 17:14:00 +05302228 unsigned erasesize = (flash_pagesize * num_pages_per_blk);
Shashank Mittaldcc2e352009-11-19 19:11:16 -08002229 unsigned writesize = flash_pagesize;
Shashank Mittalc20b5a12009-11-18 19:35:30 -08002230
2231 unsigned onenand_startaddr1 = DEVICE_FLASHCORE_0 |
Shashank Mittaldcc2e352009-11-19 19:11:16 -08002232 ((unsigned)(page * flash_pagesize) / erasesize);
2233 unsigned onenand_startaddr8 = (((unsigned)(page * flash_pagesize) &
Shashank Mittalc20b5a12009-11-18 19:35:30 -08002234 (erasesize - 1)) / writesize) << 2;
2235 unsigned onenand_startaddr2 = DEVICE_BUFFERRAM_0 << 15;
2236 unsigned onenand_startbuffer = DATARAM0_0 << 8;
Shashank Mittalad3d05c2009-11-19 15:53:57 -08002237 unsigned onenand_sysconfig1 = (raw_mode == 1) ? ONENAND_SYSCFG1_ECCDIS :\
2238 ONENAND_SYSCFG1_ECCENA;
Shashank Mittalc20b5a12009-11-18 19:35:30 -08002239
2240 unsigned controller_status;
2241 unsigned interrupt_status;
2242 unsigned ecc_status;
Shashank Mittalad3d05c2009-11-19 15:53:57 -08002243 if (raw_mode != 1)
2244 {
2245 int isbad = 0;
2246 isbad = flash_onenand_block_isbad(cmdlist, ptrlist, page);
2247 if (isbad)
2248 return -2;
2249 }
Shashank Mittalc20b5a12009-11-18 19:35:30 -08002250
2251 //static int oobfree_offset[8] = {2, 14, 18, 30, 34, 46, 50, 62};
2252 //static int oobfree_length[8] = {3, 2, 3, 2, 3, 2, 3, 2};
2253
2254 data->sfbcfg = SFLASH_BCFG;
2255 data->sfcmd[0] = SFLASH_PREPCMD(7, 0, 0,
2256 NAND_SFCMD_CMDXS,
2257 NAND_SFCMD_ASYNC,
2258 NAND_SFCMD_REGWR);
2259 data->sfcmd[1] = SFLASH_PREPCMD(0, 0, 32,
2260 NAND_SFCMD_CMDXS,
2261 NAND_SFCMD_ASYNC,
2262 NAND_SFCMD_INTHI);
2263 data->sfcmd[2] = SFLASH_PREPCMD(3, 7, 0,
2264 NAND_SFCMD_DATXS,
2265 NAND_SFCMD_ASYNC,
2266 NAND_SFCMD_REGRD);
2267 data->sfcmd[3] = SFLASH_PREPCMD(256, 0, 0,
2268 NAND_SFCMD_DATXS,
2269 NAND_SFCMD_ASYNC,
2270 NAND_SFCMD_DATRD);
2271 data->sfcmd[4] = SFLASH_PREPCMD(256, 0, 0,
2272 NAND_SFCMD_DATXS,
2273 NAND_SFCMD_ASYNC,
2274 NAND_SFCMD_DATRD);
2275 data->sfcmd[5] = SFLASH_PREPCMD(256, 0, 0,
2276 NAND_SFCMD_DATXS,
2277 NAND_SFCMD_ASYNC,
2278 NAND_SFCMD_DATRD);
2279 data->sfcmd[6] = SFLASH_PREPCMD(256, 0, 0,
2280 NAND_SFCMD_DATXS,
2281 NAND_SFCMD_ASYNC,
2282 NAND_SFCMD_DATRD);
2283 data->sfcmd[7] = SFLASH_PREPCMD(32, 0, 0,
2284 NAND_SFCMD_DATXS,
2285 NAND_SFCMD_ASYNC,
2286 NAND_SFCMD_DATRD);
2287 data->sfcmd[8] = SFLASH_PREPCMD(4, 10, 0,
2288 NAND_SFCMD_CMDXS,
2289 NAND_SFCMD_ASYNC,
2290 NAND_SFCMD_REGWR);
2291 data->sfexec = 1;
2292 data->sfstat[0] = CLEAN_DATA_32;
2293 data->sfstat[1] = CLEAN_DATA_32;
2294 data->sfstat[2] = CLEAN_DATA_32;
2295 data->sfstat[3] = CLEAN_DATA_32;
2296 data->sfstat[4] = CLEAN_DATA_32;
2297 data->sfstat[5] = CLEAN_DATA_32;
2298 data->sfstat[6] = CLEAN_DATA_32;
2299 data->sfstat[7] = CLEAN_DATA_32;
2300 data->sfstat[8] = CLEAN_DATA_32;
2301
2302 data->addr0 = (ONENAND_INTERRUPT_STATUS << 16) |
2303 (ONENAND_SYSTEM_CONFIG_1);
2304 data->addr1 = (ONENAND_START_ADDRESS_8 << 16) |
2305 (ONENAND_START_ADDRESS_1);
2306 data->addr2 = (ONENAND_START_BUFFER << 16) |
2307 (ONENAND_START_ADDRESS_2);
2308 data->addr3 = (ONENAND_ECC_STATUS << 16) |
2309 (ONENAND_COMMAND);
2310 data->addr4 = (ONENAND_CONTROLLER_STATUS << 16) |
2311 (ONENAND_INTERRUPT_STATUS);
2312 data->addr5 = (ONENAND_INTERRUPT_STATUS << 16) |
2313 (ONENAND_SYSTEM_CONFIG_1);
2314 data->addr6 = (ONENAND_START_ADDRESS_3 << 16) |
2315 (ONENAND_START_ADDRESS_1);
2316 data->data0 = (ONENAND_CLRINTR << 16) |
2317 (onenand_sysconfig1);
2318 data->data1 = (onenand_startaddr8 << 16) |
2319 (onenand_startaddr1);
2320 data->data2 = (onenand_startbuffer << 16) |
2321 (onenand_startaddr2);
2322 data->data3 = (CLEAN_DATA_16 << 16) |
2323 (ONENAND_CMDLOADSPARE);
2324 data->data4 = (CLEAN_DATA_16 << 16) |
2325 (CLEAN_DATA_16);
2326 data->data5 = (ONENAND_CLRINTR << 16) |
2327 (ONENAND_SYSCFG1_ECCENA);
2328 data->data6 = (ONENAND_STARTADDR3_RES << 16) |
2329 (ONENAND_STARTADDR1_RES);
2330 data->macro[0] = 0x0200;
2331 data->macro[1] = 0x0300;
2332 data->macro[2] = 0x0400;
2333 data->macro[3] = 0x0500;
2334 data->macro[4] = 0x8010;
2335
2336 /*************************************************************/
2337 /* Write necessary address registers in the onenand device */
2338 /*************************************************************/
2339
2340 /* Enable and configure the SFlash controller */
2341 cmd->cmd = 0 | CMD_OCB;
2342 cmd->src = paddr(&data->sfbcfg);
2343 cmd->dst = NAND_SFLASHC_BURST_CFG;
2344 cmd->len = 4;
2345 cmd++;
2346
2347 /* Block on cmd ready and write CMD register */
2348 cmd->cmd = DST_CRCI_NAND_CMD;
2349 cmd->src = paddr(&data->sfcmd[0]);
2350 cmd->dst = NAND_SFLASHC_CMD;
2351 cmd->len = 4;
2352 cmd++;
2353
2354 /* Write the ADDR0 and ADDR1 registers */
2355 cmd->cmd = 0;
2356 cmd->src = paddr(&data->addr0);
2357 cmd->dst = NAND_ADDR0;
2358 cmd->len = 8;
2359 cmd++;
2360
2361 /* Write the ADDR2 ADDR3 ADDR4 ADDR5 registers */
2362 cmd->cmd = 0;
2363 cmd->src = paddr(&data->addr2);
2364 cmd->dst = NAND_ADDR2;
2365 cmd->len = 16;
2366 cmd++;
2367
2368 /* Write the ADDR6 registers */
2369 cmd->cmd = 0;
2370 cmd->src = paddr(&data->addr6);
2371 cmd->dst = NAND_ADDR6;
2372 cmd->len = 4;
2373 cmd++;
2374
2375 /* Write the GENP0, GENP1, GENP2, GENP3 registers */
2376 cmd->cmd = 0;
2377 cmd->src = paddr(&data->data0);
2378 cmd->dst = NAND_GENP_REG0;
2379 cmd->len = 16;
2380 cmd++;
2381
2382 /* Write the FLASH_DEV_CMD4,5,6 registers */
2383 cmd->cmd = 0;
2384 cmd->src = paddr(&data->data4);
2385 cmd->dst = NAND_DEV_CMD4;
2386 cmd->len = 12;
2387 cmd++;
2388
2389 /* Kick the execute command */
2390 cmd->cmd = 0;
2391 cmd->src = paddr(&data->sfexec);
2392 cmd->dst = NAND_SFLASHC_EXEC_CMD;
2393 cmd->len = 4;
2394 cmd++;
2395
2396 /* Block on data ready, and read the status register */
2397 cmd->cmd = SRC_CRCI_NAND_DATA;
2398 cmd->src = NAND_SFLASHC_STATUS;
2399 cmd->dst = paddr(&data->sfstat[0]);
2400 cmd->len = 4;
2401 cmd++;
2402
2403 /*************************************************************/
2404 /* Wait for the interrupt from the Onenand device controller */
2405 /*************************************************************/
2406
2407 /* Block on cmd ready and write CMD register */
2408 cmd->cmd = DST_CRCI_NAND_CMD;
2409 cmd->src = paddr(&data->sfcmd[1]);
2410 cmd->dst = NAND_SFLASHC_CMD;
2411 cmd->len = 4;
2412 cmd++;
2413
2414 /* Kick the execute command */
2415 cmd->cmd = 0;
2416 cmd->src = paddr(&data->sfexec);
2417 cmd->dst = NAND_SFLASHC_EXEC_CMD;
2418 cmd->len = 4;
2419 cmd++;
2420
2421 /* Block on data ready, and read the status register */
2422 cmd->cmd = SRC_CRCI_NAND_DATA;
2423 cmd->src = NAND_SFLASHC_STATUS;
2424 cmd->dst = paddr(&data->sfstat[1]);
2425 cmd->len = 4;
2426 cmd++;
2427
2428
2429 /*************************************************************/
2430 /* Read necessary status registers from the onenand device */
2431 /*************************************************************/
2432
2433 /* Block on cmd ready and write CMD register */
2434 cmd->cmd = DST_CRCI_NAND_CMD;
2435 cmd->src = paddr(&data->sfcmd[2]);
2436 cmd->dst = NAND_SFLASHC_CMD;
2437 cmd->len = 4;
2438 cmd++;
2439
2440 /* Kick the execute command */
2441 cmd->cmd = 0;
2442 cmd->src = paddr(&data->sfexec);
2443 cmd->dst = NAND_SFLASHC_EXEC_CMD;
2444 cmd->len = 4;
2445 cmd++;
2446
2447 /* Block on data ready, and read the status register */
2448 cmd->cmd = SRC_CRCI_NAND_DATA;
2449 cmd->src = NAND_SFLASHC_STATUS;
2450 cmd->dst = paddr(&data->sfstat[2]);
2451 cmd->len = 4;
2452 cmd++;
2453
2454 /* Read the GENP3 register */
2455 cmd->cmd = 0;
2456 cmd->src = NAND_GENP_REG3;
2457 cmd->dst = paddr(&data->data3);
2458 cmd->len = 4;
2459 cmd++;
2460
2461 /* Read the DEVCMD4 register */
2462 cmd->cmd = 0;
2463 cmd->src = NAND_DEV_CMD4;
2464 cmd->dst = paddr(&data->data4);
2465 cmd->len = 4;
2466 cmd++;
2467
2468
2469 /*************************************************************/
2470 /* Read the data ram area from the onenand buffer ram */
2471 /*************************************************************/
2472
2473 if (addr) {
2474
2475 data->data3 = (CLEAN_DATA_16 << 16) |
2476 (ONENAND_CMDLOAD);
2477
2478 for (i = 0; i < 4; i++) {
2479
2480 /* Block on cmd ready and write CMD register */
2481 cmd->cmd = DST_CRCI_NAND_CMD;
2482 cmd->src = paddr(&data->sfcmd[3+i]);
2483 cmd->dst = NAND_SFLASHC_CMD;
2484 cmd->len = 4;
2485 cmd++;
2486
2487 /* Write the MACRO1 register */
2488 cmd->cmd = 0;
2489 cmd->src = paddr(&data->macro[i]);
2490 cmd->dst = NAND_MACRO1_REG;
2491 cmd->len = 4;
2492 cmd++;
2493
2494 /* Kick the execute command */
2495 cmd->cmd = 0;
2496 cmd->src = paddr(&data->sfexec);
2497 cmd->dst = NAND_SFLASHC_EXEC_CMD;
2498 cmd->len = 4;
2499 cmd++;
2500
2501 /* Block on data rdy, & read status register */
2502 cmd->cmd = SRC_CRCI_NAND_DATA;
2503 cmd->src = NAND_SFLASHC_STATUS;
2504 cmd->dst = paddr(&data->sfstat[3+i]);
2505 cmd->len = 4;
2506 cmd++;
2507
2508 /* Transfer nand ctlr buf contents to usr buf */
2509 cmd->cmd = 0;
2510 cmd->src = NAND_FLASH_BUFFER;
2511 cmd->dst = curr_addr;
2512 cmd->len = 512;
2513 curr_addr += 512;
2514 cmd++;
2515 }
2516 }
2517
Shashank Mittalad3d05c2009-11-19 15:53:57 -08002518 /* Read oob bytes in Raw Mode */
2519 if (raw_mode == 1)
2520 {
2521 /* Block on cmd ready and write CMD register */
2522 cmd->cmd = DST_CRCI_NAND_CMD;
2523 cmd->src = paddr(&data->sfcmd[7]);
2524 cmd->dst = NAND_SFLASHC_CMD;
2525 cmd->len = 4;
2526 cmd++;
2527
2528 /* Write the MACRO1 register */
2529 cmd->cmd = 0;
2530 cmd->src = paddr(&data->macro[4]);
2531 cmd->dst = NAND_MACRO1_REG;
2532 cmd->len = 4;
2533 cmd++;
2534
2535 /* Kick the execute command */
2536 cmd->cmd = 0;
2537 cmd->src = paddr(&data->sfexec);
2538 cmd->dst = NAND_SFLASHC_EXEC_CMD;
2539 cmd->len = 4;
2540 cmd++;
2541
2542 /* Block on data rdy, & read status register */
2543 cmd->cmd = SRC_CRCI_NAND_DATA;
2544 cmd->src = NAND_SFLASHC_STATUS;
2545 cmd->dst = paddr(&data->sfstat[7]);
2546 cmd->len = 4;
2547 cmd++;
2548
2549 /* Transfer nand ctlr buf contents to usr buf */
2550 cmd->cmd = 0;
2551 cmd->src = NAND_FLASH_BUFFER;
2552 cmd->dst = curr_addr;
2553 cmd->len = 64;
2554 curr_addr += 64;
2555 cmd++;
2556 }
2557
Shashank Mittalc20b5a12009-11-18 19:35:30 -08002558 /*************************************************************/
2559 /* Restore the necessary registers to proper values */
2560 /*************************************************************/
2561
2562 /* Block on cmd ready and write CMD register */
2563 cmd->cmd = DST_CRCI_NAND_CMD;
2564 cmd->src = paddr(&data->sfcmd[8]);
2565 cmd->dst = NAND_SFLASHC_CMD;
2566 cmd->len = 4;
2567 cmd++;
2568
2569 /* Kick the execute command */
2570 cmd->cmd = 0;
2571 cmd->src = paddr(&data->sfexec);
2572 cmd->dst = NAND_SFLASHC_EXEC_CMD;
2573 cmd->len = 4;
2574 cmd++;
2575
2576 /* Block on data ready, and read the status register */
2577 cmd->cmd = SRC_CRCI_NAND_DATA | CMD_OCU | CMD_LC;
2578 cmd->src = NAND_SFLASHC_STATUS;
2579 cmd->dst = paddr(&data->sfstat[8]);
2580 cmd->len = 4;
2581 cmd++;
2582
2583
2584 ptr[0] = (paddr(cmdlist) >> 3) | CMD_PTR_LP;
2585
2586 dmov_exec_cmdptr(DMOV_NAND_CHAN, ptr);
2587
2588
2589 ecc_status = (data->data3 >> 16) &
2590 0x0000FFFF;
2591 interrupt_status = (data->data4 >> 0) &
2592 0x0000FFFF;
2593 controller_status = (data->data4 >> 16) &
2594 0x0000FFFF;
2595
2596#if VERBOSE
2597 dprintf(INFO, "\n%s: sflash status %x %x %x %x %x %x %x"
2598 "%x %x\n", __func__,
2599 data->sfstat[0],
2600 data->sfstat[1],
2601 data->sfstat[2],
2602 data->sfstat[3],
2603 data->sfstat[4],
2604 data->sfstat[5],
2605 data->sfstat[6],
2606 data->sfstat[7]);
2607
2608 dprintf(INFO, "%s: controller_status = %x\n", __func__,
2609 controller_status);
2610 dprintf(INFO, "%s: interrupt_status = %x\n", __func__,
2611 interrupt_status);
2612 dprintf(INFO, "%s: ecc_status = %x\n", __func__,
2613 ecc_status);
2614#endif
2615 /* Check for errors, protection violations etc */
2616 if ((controller_status != 0)
2617 || (data->sfstat[0] & 0x110)
2618 || (data->sfstat[1] & 0x110)
2619 || (data->sfstat[2] & 0x110)
2620 || ((data->sfstat[3] & 0x110) &&
2621 (addr))
2622 || ((data->sfstat[4] & 0x110) &&
2623 (addr))
2624 || ((data->sfstat[5] & 0x110) &&
2625 (addr))
2626 || ((data->sfstat[6] & 0x110) &&
2627 (addr))) {
2628 dprintf(INFO, "%s: ECC/MPU/OP error\n", __func__);
2629 return -1;
2630 }
2631
2632#if VERBOSE
2633 dprintf(INFO, "read page %d: status: %x %x %x %x\n",
2634 page, data[5], data[6], data[7], data[8]);
2635 for(n = 0; n < 4; n++) {
2636 ptr = (unsigned*)(addr + 512 * n);
2637 dprintf(INFO, "data%d: %x %x %x %x\n", n, ptr[0], ptr[1], ptr[2], ptr[3]);
2638 ptr = (unsigned*)(spareaddr + 16 * n);
2639 dprintf(INFO, "spare data%d %x %x %x %x\n", n, ptr[0], ptr[1], ptr[2], ptr[3]);
2640 }
2641#endif
2642
2643 return 0;
2644}
2645
2646
2647struct data_onenand_write {
2648 unsigned sfbcfg;
2649 unsigned sfcmd[9];
2650 unsigned sfexec;
2651 unsigned sfstat[9];
2652 unsigned addr0;
2653 unsigned addr1;
2654 unsigned addr2;
2655 unsigned addr3;
2656 unsigned addr4;
2657 unsigned addr5;
2658 unsigned addr6;
2659 unsigned data0;
2660 unsigned data1;
2661 unsigned data2;
2662 unsigned data3;
2663 unsigned data4;
2664 unsigned data5;
2665 unsigned data6;
2666 unsigned macro[5];
2667};
2668
2669static int _flash_onenand_write_page(dmov_s *cmdlist, unsigned *ptrlist,
2670 unsigned page, const void *_addr,
Shashank Mittald0c836d2009-11-20 10:31:18 -08002671 const void *_spareaddr, unsigned raw_mode)
Shashank Mittalc20b5a12009-11-18 19:35:30 -08002672{
2673 dmov_s *cmd = cmdlist;
2674 unsigned *ptr = ptrlist;
2675 struct data_onenand_write *data = (void*) (ptrlist + 4);
2676 unsigned addr = (unsigned) _addr;
2677 unsigned addr_curr = (unsigned) _addr;
2678 char * spareaddr = (char *) _spareaddr;
2679 unsigned i, j, k;
2680
Channagoud Kadabibeb17d52011-03-25 17:14:00 +05302681 unsigned erasesize = (flash_pagesize * num_pages_per_blk);
Shashank Mittaldcc2e352009-11-19 19:11:16 -08002682 unsigned writesize = flash_pagesize;
Shashank Mittalc20b5a12009-11-18 19:35:30 -08002683
Shashank Mittaldcc2e352009-11-19 19:11:16 -08002684 unsigned onenand_startaddr1 = (page * flash_pagesize) / erasesize;
2685 unsigned onenand_startaddr8 = (((unsigned)(page * flash_pagesize) &
Shashank Mittalc20b5a12009-11-18 19:35:30 -08002686 (erasesize-1)) / writesize) << 2;
2687 unsigned onenand_startaddr2 = DEVICE_BUFFERRAM_0 << 15;
2688 unsigned onenand_startbuffer = DATARAM0_0 << 8;
Shashank Mittald0c836d2009-11-20 10:31:18 -08002689 unsigned onenand_sysconfig1 = (raw_mode == 1) ? ONENAND_SYSCFG1_ECCDIS :\
2690 ONENAND_SYSCFG1_ECCENA;
Shashank Mittalc20b5a12009-11-18 19:35:30 -08002691
2692 unsigned controller_status;
2693 unsigned interrupt_status;
2694 unsigned ecc_status;
2695
2696 char flash_oob[64];
2697
2698 unsigned oobfree_offset[8] = {2, 14, 18, 30, 34, 46, 50, 62};
2699 unsigned oobfree_length[8] = {3, 2, 3, 2, 3, 2, 3, 2};
2700
2701 for (i = 0; i < 64; i++)
2702 flash_oob[i] = 0xFF;
2703
2704 data->sfbcfg = SFLASH_BCFG;
2705 data->sfcmd[0] = SFLASH_PREPCMD(256, 0, 0,
2706 NAND_SFCMD_CMDXS,
2707 NAND_SFCMD_ASYNC,
2708 NAND_SFCMD_DATWR);
2709 data->sfcmd[1] = SFLASH_PREPCMD(256, 0, 0,
2710 NAND_SFCMD_CMDXS,
2711 NAND_SFCMD_ASYNC,
2712 NAND_SFCMD_DATWR);
2713 data->sfcmd[2] = SFLASH_PREPCMD(256, 0, 0,
2714 NAND_SFCMD_CMDXS,
2715 NAND_SFCMD_ASYNC,
2716 NAND_SFCMD_DATWR);
2717 data->sfcmd[3] = SFLASH_PREPCMD(256, 0, 0,
2718 NAND_SFCMD_CMDXS,
2719 NAND_SFCMD_ASYNC,
2720 NAND_SFCMD_DATWR);
2721 data->sfcmd[4] = SFLASH_PREPCMD(32, 0, 0,
2722 NAND_SFCMD_CMDXS,
2723 NAND_SFCMD_ASYNC,
2724 NAND_SFCMD_DATWR);
2725 data->sfcmd[5] = SFLASH_PREPCMD(7, 0, 0,
2726 NAND_SFCMD_CMDXS,
2727 NAND_SFCMD_ASYNC,
2728 NAND_SFCMD_REGWR);
2729 data->sfcmd[6] = SFLASH_PREPCMD(0, 0, 32,
2730 NAND_SFCMD_CMDXS,
2731 NAND_SFCMD_ASYNC,
2732 NAND_SFCMD_INTHI);
2733 data->sfcmd[7] = SFLASH_PREPCMD(3, 7, 0,
2734 NAND_SFCMD_DATXS,
2735 NAND_SFCMD_ASYNC,
2736 NAND_SFCMD_REGRD);
2737 data->sfcmd[8] = SFLASH_PREPCMD(4, 10, 0,
2738 NAND_SFCMD_CMDXS,
2739 NAND_SFCMD_ASYNC,
2740 NAND_SFCMD_REGWR);
2741 data->sfexec = 1;
2742
2743 data->sfstat[0] = CLEAN_DATA_32;
2744 data->sfstat[1] = CLEAN_DATA_32;
2745 data->sfstat[2] = CLEAN_DATA_32;
2746 data->sfstat[3] = CLEAN_DATA_32;
2747 data->sfstat[4] = CLEAN_DATA_32;
2748 data->sfstat[5] = CLEAN_DATA_32;
2749 data->sfstat[6] = CLEAN_DATA_32;
2750 data->sfstat[7] = CLEAN_DATA_32;
2751 data->sfstat[8] = CLEAN_DATA_32;
2752 data->addr0 = (ONENAND_INTERRUPT_STATUS << 16) |
2753 (ONENAND_SYSTEM_CONFIG_1);
2754 data->addr1 = (ONENAND_START_ADDRESS_8 << 16) |
2755 (ONENAND_START_ADDRESS_1);
2756 data->addr2 = (ONENAND_START_BUFFER << 16) |
2757 (ONENAND_START_ADDRESS_2);
2758 data->addr3 = (ONENAND_ECC_STATUS << 16) |
2759 (ONENAND_COMMAND);
2760 data->addr4 = (ONENAND_CONTROLLER_STATUS << 16) |
2761 (ONENAND_INTERRUPT_STATUS);
2762 data->addr5 = (ONENAND_INTERRUPT_STATUS << 16) |
2763 (ONENAND_SYSTEM_CONFIG_1);
2764 data->addr6 = (ONENAND_START_ADDRESS_3 << 16) |
2765 (ONENAND_START_ADDRESS_1);
2766 data->data0 = (ONENAND_CLRINTR << 16) |
2767 (onenand_sysconfig1);
2768 data->data1 = (onenand_startaddr8 << 16) |
2769 (onenand_startaddr1);
2770 data->data2 = (onenand_startbuffer << 16) |
2771 (onenand_startaddr2);
2772 data->data3 = (CLEAN_DATA_16 << 16) |
2773 (ONENAND_CMDPROGSPARE);
2774 data->data3 = (CLEAN_DATA_16 << 16) |
2775 (ONENAND_CMDPROGSPARE);
2776 data->data4 = (CLEAN_DATA_16 << 16) |
2777 (CLEAN_DATA_16);
2778 data->data5 = (ONENAND_CLRINTR << 16) |
2779 (ONENAND_SYSCFG1_ECCENA);
2780 data->data6 = (ONENAND_STARTADDR3_RES << 16) |
2781 (ONENAND_STARTADDR1_RES);
2782 data->macro[0] = 0x0200;
2783 data->macro[1] = 0x0300;
2784 data->macro[2] = 0x0400;
2785 data->macro[3] = 0x0500;
2786 data->macro[4] = 0x8010;
2787
2788
2789 /*************************************************************/
2790 /* Write the data ram area in the onenand buffer ram */
2791 /*************************************************************/
2792
2793 /* Enable and configure the SFlash controller */
2794 cmd->cmd = 0 | CMD_OCB;
2795 cmd->src = paddr(&data->sfbcfg);
2796 cmd->dst = NAND_SFLASHC_BURST_CFG;
2797 cmd->len = 4;
2798 cmd++;
2799
2800 if (addr) {
2801 data->data3 = (CLEAN_DATA_16 << 16) |
2802 (ONENAND_CMDPROG);
2803
2804 for (i = 0; i < 4; i++) {
2805
2806 /* Block on cmd ready and write CMD register */
2807 cmd->cmd = DST_CRCI_NAND_CMD;
2808 cmd->src = paddr(&data->sfcmd[i]);
2809 cmd->dst = NAND_SFLASHC_CMD;
2810 cmd->len = 4;
2811 cmd++;
2812
2813 /* Trnsfr usr buf contents to nand ctlr buf */
2814 cmd->cmd = 0;
2815 cmd->src = paddr(addr_curr);
2816 cmd->dst = NAND_FLASH_BUFFER;
2817 cmd->len = 512;
Shashank Mittald0c836d2009-11-20 10:31:18 -08002818 if(!raw_mode)
2819 addr_curr += 512;
Shashank Mittalc20b5a12009-11-18 19:35:30 -08002820 cmd++;
2821
2822 /* Write the MACRO1 register */
2823 cmd->cmd = 0;
2824 cmd->src = paddr(&data->macro[i]);
2825 cmd->dst = NAND_MACRO1_REG;
2826 cmd->len = 4;
2827 cmd++;
2828
2829 /* Kick the execute command */
2830 cmd->cmd = 0;
2831 cmd->src = paddr(&data->sfexec);
2832 cmd->dst = NAND_SFLASHC_EXEC_CMD;
2833 cmd->len = 4;
2834 cmd++;
2835
2836 /* Block on data rdy, & read status register */
2837 cmd->cmd = SRC_CRCI_NAND_DATA;
2838 cmd->src = NAND_SFLASHC_STATUS;
2839 cmd->dst = paddr(&data->sfstat[i]);
2840 cmd->len = 4;
2841 cmd++;
2842
2843 }
2844 }
2845
2846 /* Block on cmd ready and write CMD register */
2847 cmd->cmd = DST_CRCI_NAND_CMD;
2848 cmd->src = paddr(&data->sfcmd[4]);
2849 cmd->dst = NAND_SFLASHC_CMD;
2850 cmd->len = 4;
2851 cmd++;
2852
2853 if (spareaddr)
2854 {
2855 // Auto mode
2856 for (i = 0, k = 0; i < 8; i++) {
2857 for (j = 0; j < oobfree_length[i]; j++) {
2858 flash_oob[j+oobfree_offset[i]] = spareaddr[k];
2859 k++;
2860 }
2861 }
2862
2863 cmd->cmd = 0;
2864 cmd->src = paddr(&flash_oob);
2865 cmd->dst = NAND_FLASH_BUFFER;
2866 cmd->len = 64;
2867 cmd++;
2868 }
2869
Shashank Mittald0c836d2009-11-20 10:31:18 -08002870 if (raw_mode){
2871 cmd->cmd = 0;
2872 cmd->src = paddr(addr_curr);
2873 cmd->dst = NAND_FLASH_BUFFER;
2874 cmd->len = 64;
2875 cmd++;
2876 }
2877
Shashank Mittalc20b5a12009-11-18 19:35:30 -08002878 /* Write the MACRO1 register */
2879 cmd->cmd = 0;
2880 cmd->src = paddr(&data->macro[4]);
2881 cmd->dst = NAND_MACRO1_REG;
2882 cmd->len = 4;
2883 cmd++;
2884
2885 /* Kick the execute command */
2886 cmd->cmd = 0;
2887 cmd->src = paddr(&data->sfexec);
2888 cmd->dst = NAND_SFLASHC_EXEC_CMD;
2889 cmd->len = 4;
2890 cmd++;
2891
2892 /* Block on data ready, and read the status register */
2893 cmd->cmd = SRC_CRCI_NAND_DATA;
2894 cmd->src = NAND_SFLASHC_STATUS;
2895 cmd->dst = paddr(&data->sfstat[4]);
2896 cmd->len = 4;
2897 cmd++;
2898
2899 /*************************************************************/
2900 /* Write necessary address registers in the onenand device */
2901 /*************************************************************/
2902
2903 /* Block on cmd ready and write CMD register */
2904 cmd->cmd = DST_CRCI_NAND_CMD;
2905 cmd->src = paddr(&data->sfcmd[5]);
2906 cmd->dst = NAND_SFLASHC_CMD;
2907 cmd->len = 4;
2908 cmd++;
2909
2910 /* Write the ADDR0 and ADDR1 registers */
2911 cmd->cmd = 0;
2912 cmd->src = paddr(&data->addr0);
2913 cmd->dst = NAND_ADDR0;
2914 cmd->len = 8;
2915 cmd++;
2916
2917 /* Write the ADDR2 ADDR3 ADDR4 ADDR5 registers */
2918 cmd->cmd = 0;
2919 cmd->src = paddr(&data->addr2);
2920 cmd->dst = NAND_ADDR2;
2921 cmd->len = 16;
2922 cmd++;
2923
2924 /* Write the ADDR6 registers */
2925 cmd->cmd = 0;
2926 cmd->src = paddr(&data->addr6);
2927 cmd->dst = NAND_ADDR6;
2928 cmd->len = 4;
2929 cmd++;
2930
2931 /* Write the GENP0, GENP1, GENP2, GENP3 registers */
2932 cmd->cmd = 0;
2933 cmd->src = paddr(&data->data0);
2934 cmd->dst = NAND_GENP_REG0;
2935 cmd->len = 16;
2936 cmd++;
2937
2938 /* Write the FLASH_DEV_CMD4,5,6 registers */
2939 cmd->cmd = 0;
2940 cmd->src = paddr(&data->data4);
2941 cmd->dst = NAND_DEV_CMD4;
2942 cmd->len = 12;
2943 cmd++;
2944
2945 /* Kick the execute command */
2946 cmd->cmd = 0;
2947 cmd->src = paddr(&data->sfexec);
2948 cmd->dst = NAND_SFLASHC_EXEC_CMD;
2949 cmd->len = 4;
2950 cmd++;
2951
2952 /* Block on data ready, and read the status register */
2953 cmd->cmd = SRC_CRCI_NAND_DATA;
2954 cmd->src = NAND_SFLASHC_STATUS;
2955 cmd->dst = paddr(&data->sfstat[5]);
2956 cmd->len = 4;
2957 cmd++;
2958
2959 /*************************************************************/
2960 /* Wait for the interrupt from the Onenand device controller */
2961 /*************************************************************/
2962
2963 /* Block on cmd ready and write CMD register */
2964 cmd->cmd = DST_CRCI_NAND_CMD;
2965 cmd->src = paddr(&data->sfcmd[6]);
2966 cmd->dst = NAND_SFLASHC_CMD;
2967 cmd->len = 4;
2968 cmd++;
2969
2970 /* Kick the execute command */
2971 cmd->cmd = 0;
2972 cmd->src = paddr(&data->sfexec);
2973 cmd->dst = NAND_SFLASHC_EXEC_CMD;
2974 cmd->len = 4;
2975 cmd++;
2976
2977 /* Block on data ready, and read the status register */
2978 cmd->cmd = SRC_CRCI_NAND_DATA;
2979 cmd->src = NAND_SFLASHC_STATUS;
2980 cmd->dst = paddr(&data->sfstat[6]);
2981 cmd->len = 4;
2982 cmd++;
2983
2984 /*************************************************************/
2985 /* Read necessary status registers from the onenand device */
2986 /*************************************************************/
2987
2988 /* Block on cmd ready and write CMD register */
2989 cmd->cmd = DST_CRCI_NAND_CMD;
2990 cmd->src = paddr(&data->sfcmd[7]);
2991 cmd->dst = NAND_SFLASHC_CMD;
2992 cmd->len = 4;
2993 cmd++;
2994
2995 /* Kick the execute command */
2996 cmd->cmd = 0;
2997 cmd->src = paddr(&data->sfexec);
2998 cmd->dst = NAND_SFLASHC_EXEC_CMD;
2999 cmd->len = 4;
3000 cmd++;
3001
3002 /* Block on data ready, and read the status register */
3003 cmd->cmd = SRC_CRCI_NAND_DATA;
3004 cmd->src = NAND_SFLASHC_STATUS;
3005 cmd->dst = paddr(&data->sfstat[7]);
3006 cmd->len = 4;
3007 cmd++;
3008
3009 /* Read the GENP3 register */
3010 cmd->cmd = 0;
3011 cmd->src = NAND_GENP_REG3;
3012 cmd->dst = paddr(&data->data3);
3013 cmd->len = 4;
3014 cmd++;
3015
3016 /* Read the DEVCMD4 register */
3017 cmd->cmd = 0;
3018 cmd->src = NAND_DEV_CMD4;
3019 cmd->dst = paddr(&data->data4);
3020 cmd->len = 4;
3021 cmd++;
3022
3023
3024 /*************************************************************/
3025 /* Restore the necessary registers to proper values */
3026 /*************************************************************/
3027
3028 /* Block on cmd ready and write CMD register */
3029 cmd->cmd = DST_CRCI_NAND_CMD;
3030 cmd->src = paddr(&data->sfcmd[8]);
3031 cmd->dst = NAND_SFLASHC_CMD;
3032 cmd->len = 4;
3033 cmd++;
3034
3035 /* Kick the execute command */
3036 cmd->cmd = 0;
3037 cmd->src = paddr(&data->sfexec);
3038 cmd->dst = NAND_SFLASHC_EXEC_CMD;
3039 cmd->len = 4;
3040 cmd++;
3041
3042 /* Block on data ready, and read the status register */
3043 cmd->cmd = SRC_CRCI_NAND_DATA | CMD_OCU | CMD_LC;
3044 cmd->src = NAND_SFLASHC_STATUS;
3045 cmd->dst = paddr(&data->sfstat[8]);
3046 cmd->len = 4;
3047 cmd++;
3048
3049
3050 ptr[0] = (paddr(cmdlist) >> 3) | CMD_PTR_LP;
3051
3052 dmov_exec_cmdptr(DMOV_NAND_CHAN, ptr);
3053
3054 ecc_status = (data->data3 >> 16) & 0x0000FFFF;
3055 interrupt_status = (data->data4 >> 0)&0x0000FFFF;
3056 controller_status = (data->data4 >> 16)&0x0000FFFF;
3057
3058#if VERBOSE
3059 dprintf(INFO, "\n%s: sflash status %x %x %x %x %x %x %x %x %x\n", __func__,
3060 data->sfstat[0],
3061 data->sfstat[1],
3062 data->sfstat[2],
3063 data->sfstat[3],
3064 data->sfstat[4],
3065 data->sfstat[5],
3066 data->sfstat[6],
3067 data->sfstat[7],
3068 data->sfstat[8]);
3069
3070 dprintf(INFO, "%s: controller_status = %x\n", __func__,
3071 controller_status);
3072 dprintf(INFO, "%s: interrupt_status = %x\n", __func__,
3073 interrupt_status);
3074 dprintf(INFO, "%s: ecc_status = %x\n", __func__,
3075 ecc_status);
3076#endif
3077 /* Check for errors, protection violations etc */
3078 if ((controller_status != 0)
3079 || (data->sfstat[5] & 0x110)
3080 || (data->sfstat[6] & 0x110)
3081 || (data->sfstat[7] & 0x110)
3082 || (data->sfstat[8] & 0x110)
3083 || ((data->sfstat[0] & 0x110) &&
3084 (addr))
3085 || ((data->sfstat[1] & 0x110) &&
3086 (addr))
3087 || ((data->sfstat[2] & 0x110) &&
3088 (addr))
3089 || ((data->sfstat[3] & 0x110) &&
3090 (addr))) {
3091 dprintf(CRITICAL, "%s: ECC/MPU/OP error\n", __func__);
3092 return -1;
3093 }
3094
3095
3096 return 0;
3097}
Shashank Mittald0c836d2009-11-20 10:31:18 -08003098
3099static int flash_onenand_mark_badblock(dmov_s *cmdlist, unsigned *ptrlist, unsigned page)
3100{
3101 memset(empty_buf,0,528);
3102 /* Going to first page of the block */
Channagoud Kadabibeb17d52011-03-25 17:14:00 +05303103 if(page & num_pages_per_blk_mask)
3104 page = page - (page & num_pages_per_blk_mask);
Shashank Mittald0c836d2009-11-20 10:31:18 -08003105 return _flash_onenand_write_page(cmdlist, ptrlist, page, empty_buf, 0, 1);
3106}
3107
3108static int flash_mark_badblock(dmov_s *cmdlist, unsigned *ptrlist, unsigned page)
3109{
3110 switch(flash_info.type) {
3111 case FLASH_8BIT_NAND_DEVICE:
3112 case FLASH_16BIT_NAND_DEVICE:
3113 return flash_nand_mark_badblock(cmdlist, ptrlist, page);
3114 case FLASH_ONENAND_DEVICE:
3115 return flash_onenand_mark_badblock(cmdlist, ptrlist, page);
3116 default:
3117 return -1;
3118 }
3119}
3120
3121
Shashank Mittalc20b5a12009-11-18 19:35:30 -08003122/* Wrapper functions */
3123static void flash_read_id(dmov_s *cmdlist, unsigned *ptrlist)
3124{
3125 int dev_found = 0;
3126 unsigned index;
3127
3128 // Try to read id
3129 flash_nand_read_id(cmdlist, ptrlist);
3130 // Check if we support the device
3131 for (index=1;
3132 index < (sizeof(supported_flash)/sizeof(struct flash_identification));
3133 index++)
3134 {
3135 if ((flash_info.id & supported_flash[index].mask) ==
3136 (supported_flash[index].flash_id &
3137 (supported_flash[index].mask))) {
3138 dev_found = 1;
3139 break;
3140 }
3141 }
3142
3143 if(!dev_found) {
3144 flash_onenand_read_id(cmdlist, ptrlist);
3145 for (index=1;
3146 index < (sizeof(supported_flash)/sizeof(struct flash_identification));
3147 index++)
3148 {
3149 if ((flash_info.id & supported_flash[index].mask) ==
3150 (supported_flash[index].flash_id &
3151 (supported_flash[index].mask))) {
3152 dev_found = 1;
3153 break;
3154 }
3155 }
3156 }
3157
3158
3159
3160 if(dev_found) {
3161 if (supported_flash[index].widebus)
3162 flash_info.type = FLASH_16BIT_NAND_DEVICE;
3163 else
3164 flash_info.type = FLASH_8BIT_NAND_DEVICE;
3165 if (supported_flash[index].onenand)
3166 flash_info.type = FLASH_ONENAND_DEVICE;
3167 flash_info.page_size = supported_flash[index].pagesize;
Shashank Mittaldcc2e352009-11-19 19:11:16 -08003168 flash_pagesize = flash_info.page_size;
Shashank Mittalc20b5a12009-11-18 19:35:30 -08003169 flash_info.block_size = supported_flash[index].blksize;
3170 flash_info.spare_size = supported_flash[index].oobsize;
3171 if (flash_info.block_size && flash_info.page_size)
3172 {
3173 flash_info.num_blocks = supported_flash[index].density;
Chandan Uddaraju40605112010-08-09 14:25:08 -07003174 flash_info.num_blocks /= (flash_info.block_size);
Shashank Mittalc20b5a12009-11-18 19:35:30 -08003175 }
3176 else
3177 {
3178 flash_info.num_blocks = 0;
3179 }
3180 ASSERT(flash_info.num_blocks);
Channagoud Kadabibeb17d52011-03-25 17:14:00 +05303181 // Use this for getting the next/current blocks
3182 num_pages_per_blk = flash_info.block_size / flash_pagesize;
3183 num_pages_per_blk_mask = num_pages_per_blk - 1;
Shashank Mittalc20b5a12009-11-18 19:35:30 -08003184 return;
3185 }
3186
3187 // Assume 8 bit nand device for backward compatability
3188 if (dev_found == 0) {
3189 dprintf(INFO, "Device not supported. Assuming 8 bit NAND device\n");
3190 flash_info.type = FLASH_8BIT_NAND_DEVICE;
3191 }
3192 dprintf(INFO, "nandid: 0x%x maker=0x%02x device=0x%02x page_size=%d\n",
3193 flash_info.id, flash_info.vendor, flash_info.device,
3194 flash_info.page_size);
3195 dprintf(INFO, " spare_size=%d block_size=%d num_blocks=%d\n",
3196 flash_info.spare_size, flash_info.block_size,
3197 flash_info.num_blocks);
3198}
3199
3200static int flash_erase_block(dmov_s *cmdlist, unsigned *ptrlist, unsigned page)
3201{
3202 switch(flash_info.type) {
3203 case FLASH_8BIT_NAND_DEVICE:
3204 case FLASH_16BIT_NAND_DEVICE:
3205 return flash_nand_erase_block(cmdlist, ptrlist, page);
3206 case FLASH_ONENAND_DEVICE:
3207 return flash_onenand_erase_block(cmdlist, ptrlist, page);
3208 default:
3209 return -1;
3210 }
3211}
3212
3213static int _flash_read_page(dmov_s *cmdlist, unsigned *ptrlist,
3214 unsigned page, void *_addr, void *_spareaddr)
3215{
3216 switch(flash_info.type) {
3217 case FLASH_8BIT_NAND_DEVICE:
3218 case FLASH_16BIT_NAND_DEVICE:
Chandan Uddaraju14e57eb2010-06-28 12:11:06 -07003219 if(interleaved_mode)
3220 return flash_nand_read_page_interleave(cmdlist, ptrlist, page, _addr, _spareaddr);
3221 else
Shashank Mittalc20b5a12009-11-18 19:35:30 -08003222 return _flash_nand_read_page(cmdlist, ptrlist, page, _addr, _spareaddr);
3223 case FLASH_ONENAND_DEVICE:
Shashank Mittalad3d05c2009-11-19 15:53:57 -08003224 return _flash_onenand_read_page(cmdlist, ptrlist, page, _addr, _spareaddr, 0);
Shashank Mittalc20b5a12009-11-18 19:35:30 -08003225 default:
3226 return -1;
3227 }
3228}
3229
Shashank Mittalad3d05c2009-11-19 15:53:57 -08003230static int _flash_block_isbad(dmov_s *cmdlist, unsigned *ptrlist, unsigned page)
3231{
3232 switch(flash_info.type) {
3233 case FLASH_8BIT_NAND_DEVICE:
3234 case FLASH_16BIT_NAND_DEVICE:
3235 return flash_nand_block_isbad(cmdlist, ptrlist, page);
3236 case FLASH_ONENAND_DEVICE:
3237 return flash_onenand_block_isbad(cmdlist, ptrlist, page);
3238 default:
3239 return -1;
3240 }
3241}
Shashank Mittalc20b5a12009-11-18 19:35:30 -08003242
3243static int _flash_write_page(dmov_s *cmdlist, unsigned *ptrlist,
3244 unsigned page, const void *_addr,
3245 const void *_spareaddr)
3246{
3247 switch(flash_info.type) {
3248 case FLASH_8BIT_NAND_DEVICE:
3249 case FLASH_16BIT_NAND_DEVICE:
Chandan Uddaraju14e57eb2010-06-28 12:11:06 -07003250 if(interleaved_mode)
3251 return flash_nand_write_page_interleave(cmdlist, ptrlist, page, _addr, _spareaddr, 0);
3252 else
Shashank Mittald0c836d2009-11-20 10:31:18 -08003253 return _flash_nand_write_page(cmdlist, ptrlist, page, _addr, _spareaddr, 0);
Shashank Mittalc20b5a12009-11-18 19:35:30 -08003254 case FLASH_ONENAND_DEVICE:
Shashank Mittald0c836d2009-11-20 10:31:18 -08003255 return _flash_onenand_write_page(cmdlist, ptrlist, page, _addr, _spareaddr, 0);
Shashank Mittalc20b5a12009-11-18 19:35:30 -08003256 default:
3257 return -1;
3258 }
3259}
3260
Dima Zavin03cf4312009-01-23 16:38:30 -08003261static unsigned *flash_ptrlist;
3262static dmov_s *flash_cmdlist;
Dima Zavin03cf4312009-01-23 16:38:30 -08003263
3264static struct ptable *flash_ptable = NULL;
3265
Dima Zavine5f64352009-03-02 16:04:20 -08003266void flash_init(void)
Dima Zavin03cf4312009-01-23 16:38:30 -08003267{
Dima Zavine5f64352009-03-02 16:04:20 -08003268 ASSERT(flash_ptable == NULL);
Dima Zavin03cf4312009-01-23 16:38:30 -08003269
3270 flash_ptrlist = memalign(32, 1024);
3271 flash_cmdlist = memalign(32, 1024);
Ajay Dudani232ce812009-12-02 00:14:11 -08003272 flash_data = memalign(32, 4096 + 128);
3273 flash_spare = memalign(32, 128);
Dima Zavin03cf4312009-01-23 16:38:30 -08003274
Dima Zavin03cf4312009-01-23 16:38:30 -08003275 flash_read_id(flash_cmdlist, flash_ptrlist);
Shashank Mittal83d16d02009-11-18 16:54:42 -08003276 if((FLASH_8BIT_NAND_DEVICE == flash_info.type)
3277 ||(FLASH_16BIT_NAND_DEVICE == flash_info.type)) {
Shashank Mittalc20b5a12009-11-18 19:35:30 -08003278 if(flash_nand_read_config(flash_cmdlist, flash_ptrlist)) {
Shashank Mittal83d16d02009-11-18 16:54:42 -08003279 dprintf(CRITICAL, "ERROR: could not read CFG0/CFG1 state\n");
3280 ASSERT(0);
3281 }
3282 }
Dima Zavin03cf4312009-01-23 16:38:30 -08003283}
3284
3285struct ptable *flash_get_ptable(void)
3286{
3287 return flash_ptable;
3288}
3289
Dima Zavine5f64352009-03-02 16:04:20 -08003290void flash_set_ptable(struct ptable *new_ptable)
3291{
3292 ASSERT(flash_ptable == NULL && new_ptable != NULL);
3293 flash_ptable = new_ptable;
3294}
3295
Dima Zavinca337f52009-03-02 16:41:44 -08003296struct flash_info *flash_get_info(void)
3297{
3298 return &flash_info;
3299}
3300
Dima Zavin03cf4312009-01-23 16:38:30 -08003301int flash_erase(struct ptentry *ptn)
3302{
3303 unsigned block = ptn->start;
3304 unsigned count = ptn->length;
3305
Shashank Mittal8e49dec2010-03-01 15:19:04 -08003306 set_nand_configuration(ptn->type);
Dima Zavin03cf4312009-01-23 16:38:30 -08003307 while(count-- > 0) {
Channagoud Kadabibeb17d52011-03-25 17:14:00 +05303308 if(flash_erase_block(flash_cmdlist, flash_ptrlist, block * num_pages_per_blk)) {
Dima Zavin03cf4312009-01-23 16:38:30 -08003309 dprintf(INFO, "cannot erase @ %d (bad block?)\n", block);
3310 }
3311 block++;
3312 }
3313 return 0;
3314}
3315
3316int flash_read_ext(struct ptentry *ptn, unsigned extra_per_page,
Shashank Mittalc20b5a12009-11-18 19:35:30 -08003317 unsigned offset, void *data, unsigned bytes)
Dima Zavin03cf4312009-01-23 16:38:30 -08003318{
Channagoud Kadabibeb17d52011-03-25 17:14:00 +05303319 unsigned page = (ptn->start * num_pages_per_blk) + (offset / flash_pagesize);
3320 unsigned lastpage = (ptn->start + ptn->length) * num_pages_per_blk;
Shashank Mittaldcc2e352009-11-19 19:11:16 -08003321 unsigned count = (bytes + flash_pagesize - 1 + extra_per_page) / (flash_pagesize + extra_per_page);
Dima Zavin03cf4312009-01-23 16:38:30 -08003322 unsigned *spare = (unsigned*) flash_spare;
3323 unsigned errors = 0;
3324 unsigned char *image = data;
Channagoud Kadabibeb17d52011-03-25 17:14:00 +05303325 unsigned current_block = (page - (page & num_pages_per_blk_mask)) / num_pages_per_blk;
Shashank Mittalad3d05c2009-11-19 15:53:57 -08003326 unsigned start_block = ptn->start;
3327 int result = 0;
3328 int isbad = 0;
Shashank Mittalfd1f04f2010-08-03 17:38:48 -07003329 int start_block_count = 0;
Dima Zavin03cf4312009-01-23 16:38:30 -08003330
Shashank Mittal8e49dec2010-03-01 15:19:04 -08003331 ASSERT(ptn->type == TYPE_APPS_PARTITION);
3332 set_nand_configuration(TYPE_APPS_PARTITION);
3333
Shashank Mittaldcc2e352009-11-19 19:11:16 -08003334 if(offset & (flash_pagesize - 1))
Dima Zavin03cf4312009-01-23 16:38:30 -08003335 return -1;
3336
Shashank Mittalfd1f04f2010-08-03 17:38:48 -07003337// Adjust page offset based on number of bad blocks from start to current page
3338 if (start_block < current_block)
3339 {
3340 start_block_count = (current_block - start_block);
3341 while (start_block_count && (start_block < (ptn->start + ptn->length))) {
Channagoud Kadabibeb17d52011-03-25 17:14:00 +05303342 isbad = _flash_block_isbad(flash_cmdlist, flash_ptrlist, start_block*num_pages_per_blk);
Shashank Mittalfd1f04f2010-08-03 17:38:48 -07003343 if (isbad)
Channagoud Kadabibeb17d52011-03-25 17:14:00 +05303344 page += num_pages_per_blk;
Shashank Mittalfd1f04f2010-08-03 17:38:48 -07003345 else
3346 start_block_count--;
3347 start_block++;
3348 }
Shashank Mittalad3d05c2009-11-19 15:53:57 -08003349 }
3350
Shashank Mittalfd1f04f2010-08-03 17:38:48 -07003351 while((page < lastpage) && !start_block_count) {
Dima Zavin03cf4312009-01-23 16:38:30 -08003352 if(count == 0) {
3353 dprintf(INFO, "flash_read_image: success (%d errors)\n", errors);
3354 return 0;
3355 }
3356
Shashank Mittalad3d05c2009-11-19 15:53:57 -08003357 result = _flash_read_page(flash_cmdlist, flash_ptrlist, page, image, spare);
3358
3359 if (result == -1) {
3360 // bad page, go to next page
3361 page++;
Dima Zavin03cf4312009-01-23 16:38:30 -08003362 errors++;
3363 continue;
3364 }
Shashank Mittalad3d05c2009-11-19 15:53:57 -08003365 else if (result == -2) {
3366 // bad block, go to next block same offset
Channagoud Kadabibeb17d52011-03-25 17:14:00 +05303367 page += num_pages_per_blk;
Shashank Mittalad3d05c2009-11-19 15:53:57 -08003368 errors++;
3369 continue;
3370 }
3371
3372 page++;
Shashank Mittaldcc2e352009-11-19 19:11:16 -08003373 image += flash_pagesize;
Dima Zavin03cf4312009-01-23 16:38:30 -08003374 memcpy(image, spare, extra_per_page);
3375 image += extra_per_page;
3376 count -= 1;
3377 }
3378
3379 /* could not find enough valid pages before we hit the end */
3380 dprintf(INFO, "flash_read_image: failed (%d errors)\n", errors);
3381 return 0xffffffff;
3382}
3383
3384int flash_write(struct ptentry *ptn, unsigned extra_per_page, const void *data,
3385 unsigned bytes)
3386{
Channagoud Kadabibeb17d52011-03-25 17:14:00 +05303387 unsigned page = ptn->start * num_pages_per_blk;
3388 unsigned lastpage = (ptn->start + ptn->length) * num_pages_per_blk;
Dima Zavin03cf4312009-01-23 16:38:30 -08003389 unsigned *spare = (unsigned*) flash_spare;
3390 const unsigned char *image = data;
Shashank Mittaldcc2e352009-11-19 19:11:16 -08003391 unsigned wsize = flash_pagesize + extra_per_page;
Dima Zavin03cf4312009-01-23 16:38:30 -08003392 unsigned n;
3393 int r;
3394
Shashank Mittal8e49dec2010-03-01 15:19:04 -08003395 if ((flash_info.type == FLASH_ONENAND_DEVICE) && (ptn->type == TYPE_MODEM_PARTITION))
3396 {
3397 dprintf(CRITICAL, "flash_write_image: feature not supported\n");
3398 return -1;
3399 }
3400
3401 set_nand_configuration(ptn->type);
Dima Zavin03cf4312009-01-23 16:38:30 -08003402 for(n = 0; n < 16; n++) spare[n] = 0xffffffff;
3403
3404 while(bytes > 0) {
3405 if(bytes < wsize) {
3406 dprintf(CRITICAL, "flash_write_image: image undersized (%d < %d)\n", bytes, wsize);
3407 return -1;
3408 }
3409 if(page >= lastpage) {
3410 dprintf(CRITICAL, "flash_write_image: out of space\n");
3411 return -1;
3412 }
3413
Channagoud Kadabibeb17d52011-03-25 17:14:00 +05303414 if((page & num_pages_per_blk_mask) == 0) {
Dima Zavin03cf4312009-01-23 16:38:30 -08003415 if(flash_erase_block(flash_cmdlist, flash_ptrlist, page)) {
Channagoud Kadabibeb17d52011-03-25 17:14:00 +05303416 dprintf(INFO, "flash_write_image: bad block @ %d\n", page / num_pages_per_blk);
3417 page += num_pages_per_blk;
Dima Zavin03cf4312009-01-23 16:38:30 -08003418 continue;
3419 }
3420 }
3421
3422 if(extra_per_page) {
Shashank Mittald0c836d2009-11-20 10:31:18 -08003423 r = _flash_write_page(flash_cmdlist, flash_ptrlist, page, image, image + flash_pagesize);
Dima Zavin03cf4312009-01-23 16:38:30 -08003424 } else {
Shashank Mittald0c836d2009-11-20 10:31:18 -08003425 r = _flash_write_page(flash_cmdlist, flash_ptrlist, page, image, spare);
Dima Zavin03cf4312009-01-23 16:38:30 -08003426 }
3427 if(r) {
3428 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 +05303429 image -= (page & num_pages_per_blk_mask) * wsize;
3430 bytes += (page & num_pages_per_blk_mask) * wsize;
3431 page &= ~num_pages_per_blk_mask;
Dima Zavin03cf4312009-01-23 16:38:30 -08003432 if(flash_erase_block(flash_cmdlist, flash_ptrlist, page)) {
3433 dprintf(INFO, "flash_write_image: erase failure @ page %d\n", page);
3434 }
Shashank Mittal8e49dec2010-03-01 15:19:04 -08003435 if (ptn->type != TYPE_MODEM_PARTITION) {
3436 flash_mark_badblock(flash_cmdlist, flash_ptrlist, page);
3437 }
Dima Zavin03cf4312009-01-23 16:38:30 -08003438 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 +05303439 page += num_pages_per_blk;
Dima Zavin03cf4312009-01-23 16:38:30 -08003440 continue;
3441 }
Shashank Mittald0c836d2009-11-20 10:31:18 -08003442 page++;
Dima Zavin03cf4312009-01-23 16:38:30 -08003443 image += wsize;
3444 bytes -= wsize;
3445 }
3446
3447 /* erase any remaining pages in the partition */
Channagoud Kadabibeb17d52011-03-25 17:14:00 +05303448 page = (page + num_pages_per_blk_mask) & (~num_pages_per_blk_mask);
Dima Zavin03cf4312009-01-23 16:38:30 -08003449 while(page < lastpage){
3450 if(flash_erase_block(flash_cmdlist, flash_ptrlist, page)) {
Channagoud Kadabibeb17d52011-03-25 17:14:00 +05303451 dprintf(INFO, "flash_write_image: bad block @ %d\n", page / num_pages_per_blk);
Dima Zavin03cf4312009-01-23 16:38:30 -08003452 }
Channagoud Kadabibeb17d52011-03-25 17:14:00 +05303453 page += num_pages_per_blk;
Dima Zavin03cf4312009-01-23 16:38:30 -08003454 }
3455
3456 dprintf(INFO, "flash_write_image: success\n");
3457 return 0;
3458}
3459
3460#if 0
3461static int flash_read_page(unsigned page, void *data, void *extra)
3462{
3463 return _flash_read_page(flash_cmdlist, flash_ptrlist,
3464 page, data, extra);
3465}
3466#endif
Shashank Mittaldcc2e352009-11-19 19:11:16 -08003467
3468unsigned flash_page_size(void)
3469{
3470 return flash_pagesize;
3471}
Chandan Uddaraju14e57eb2010-06-28 12:11:06 -07003472
3473void enable_interleave_mode(int status)
3474{
3475 interleaved_mode = status;
3476 if(status)
3477 {
3478 flash_pagesize *= 2;
3479 platform_config_interleaved_mode_gpios();
3480 }
3481 return;
3482}