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