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