blob: 57a3867453034aedbdb704922e90a1bc9360ace2 [file] [log] [blame]
Dima Zavin03cf4312009-01-23 16:38:30 -08001/*
2 * Copyright (c) 2008, Google Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in
Shashank Mittalc20b5a12009-11-18 19:35:30 -080012 * the documentation and/or other materials provided with the
Dima Zavin03cf4312009-01-23 16:38:30 -080013 * distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
Shashank Mittalc20b5a12009-11-18 19:35:30 -080022 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
Dima Zavin03cf4312009-01-23 16:38:30 -080023 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29#include <debug.h>
30#include <reg.h>
31#include <stdlib.h>
32#include <string.h>
33#include <dev/flash.h>
34#include <lib/ptable.h>
35
36#include "dmov.h"
37#include "nand.h"
38
39#define VERBOSE 0
Dima Zavin5582c7d2009-03-03 15:17:59 -080040#define VERIFY_WRITE 0
41
42static void *flash_spare;
43static void *flash_data;
Dima Zavin03cf4312009-01-23 16:38:30 -080044
45typedef struct dmov_ch dmov_ch;
Shashank Mittalc20b5a12009-11-18 19:35:30 -080046struct dmov_ch
Dima Zavin03cf4312009-01-23 16:38:30 -080047{
48 volatile unsigned cmd;
49 volatile unsigned result;
50 volatile unsigned status;
51 volatile unsigned config;
52};
53
54static void dmov_prep_ch(dmov_ch *ch, unsigned id)
55{
56 ch->cmd = DMOV_CMD_PTR(id);
57 ch->result = DMOV_RSLT(id);
58 ch->status = DMOV_STATUS(id);
59 ch->config = DMOV_CONFIG(id);
60}
61
62#define SRC_CRCI_NAND_CMD CMD_SRC_CRCI(DMOV_NAND_CRCI_CMD)
63#define DST_CRCI_NAND_CMD CMD_DST_CRCI(DMOV_NAND_CRCI_CMD)
64#define SRC_CRCI_NAND_DATA CMD_SRC_CRCI(DMOV_NAND_CRCI_DATA)
65#define DST_CRCI_NAND_DATA CMD_DST_CRCI(DMOV_NAND_CRCI_DATA)
66
Shashank Mittalad3d05c2009-11-19 15:53:57 -080067#define NAND_CFG0_RAW 0xA80420C0
68#define NAND_CFG1_RAW 0x5045D
69
Dima Zavin03cf4312009-01-23 16:38:30 -080070static unsigned CFG0, CFG1;
71
72#define CFG1_WIDE_FLASH (1U << 1)
73
74#define paddr(n) ((unsigned) (n))
75
76static int dmov_exec_cmdptr(unsigned id, unsigned *ptr)
77{
78 dmov_ch ch;
79 unsigned n;
80
81 dmov_prep_ch(&ch, id);
82
83 writel(DMOV_CMD_PTR_LIST | DMOV_CMD_ADDR(paddr(ptr)), ch.cmd);
84
85 while(!(readl(ch.status) & DMOV_STATUS_RSLT_VALID)) ;
86
87 n = readl(ch.status);
88 while(DMOV_STATUS_RSLT_COUNT(n)) {
89 n = readl(ch.result);
90 if(n != 0x80000002) {
91 dprintf(CRITICAL, "ERROR: result: %x\n", n);
92 dprintf(CRITICAL, "ERROR: flush: %x %x %x %x\n",
93 readl(DMOV_FLUSH0(DMOV_NAND_CHAN)),
94 readl(DMOV_FLUSH1(DMOV_NAND_CHAN)),
95 readl(DMOV_FLUSH2(DMOV_NAND_CHAN)),
96 readl(DMOV_FLUSH3(DMOV_NAND_CHAN)));
97 }
98 n = readl(ch.status);
99 }
100
101 return 0;
102}
103
Dima Zavinca337f52009-03-02 16:41:44 -0800104static struct flash_info flash_info;
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800105static unsigned flash_pagesize = 0;
Dima Zavin03cf4312009-01-23 16:38:30 -0800106
Shashank Mittal83d16d02009-11-18 16:54:42 -0800107struct flash_identification {
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800108 unsigned flash_id;
109 unsigned mask;
110 unsigned density;
111 unsigned widebus;
112 unsigned pagesize;
113 unsigned blksize;
114 unsigned oobsize;
115 unsigned onenand;
Shashank Mittal83d16d02009-11-18 16:54:42 -0800116};
117
118static struct flash_identification supported_flash[] =
119{
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800120 /* Flash ID ID Mask Density(MB) Wid Pgsz Blksz oobsz onenand Manuf */
121 {0x00000000, 0xFFFFFFFF, 0, 0, 0, 0, 0, 0}, /*ONFI*/
122 {0x1500aaec, 0xFF00FFFF, (256<<20), 0, 2048, (2048<<6), 64, 0}, /*Sams*/
123 {0x5500baec, 0xFF00FFFF, (256<<20), 1, 2048, (2048<<6), 64, 0}, /*Sams*/
124 {0x1500aa98, 0xFFFFFFFF, (256<<20), 0, 2048, (2048<<6), 64, 0}, /*Tosh*/
125 {0x5500ba98, 0xFFFFFFFF, (256<<20), 1, 2048, (2048<<6), 64, 0}, /*Tosh*/
126 {0xd580b12c, 0xFFFFFFFF, (128<<20), 1, 2048, (2048<<6), 64, 0}, /*Micr*/
127 {0x5590bc2c, 0xFFFFFFFF, (128<<20), 1, 2048, (2048<<6), 64, 0}, /*Micr*/
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800128 {0x1580aa2c, 0xFFFFFFFF, (128<<20), 0, 2048, (2048<<6), 64, 0}, /*Micr*/
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800129 {0x5580baad, 0xFFFFFFFF, (256<<20), 1, 2048, (2048<<6), 64, 0}, /*Hynx*/
130 {0x5510baad, 0xFFFFFFFF, (256<<20), 1, 2048, (2048<<6), 64, 0}, /*Hynx*/
131 {0x004000ec, 0xFFFFFFFF, (256<<20), 0, 2048, (2048<<6), 64, 1}, /*Sams*/
132 {0x005c00ec, 0xFFFFFFFF, (256<<20), 0, 2048, (2048<<6), 64, 1}, /*Sams*/
133 {0x005800ec, 0xFFFFFFFF, (256<<20), 0, 2048, (2048<<6), 64, 1}, /*Sams*/
134 {0x6600bcec, 0xFF00FFFF, (512<<20), 1, 4096, (4096<<6), 128, 0}, /*Sams*/
135 /* Note: Width flag is 0 for 8 bit Flash and 1 for 16 bit flash */
136 /* Note: Onenand flag is 0 for NAND Flash and 1 for OneNAND flash */
137 /* Note: The First row will be filled at runtime during ONFI probe */
Shashank Mittal83d16d02009-11-18 16:54:42 -0800138};
139
140static void flash_nand_read_id(dmov_s *cmdlist, unsigned *ptrlist)
Dima Zavin03cf4312009-01-23 16:38:30 -0800141{
142 dmov_s *cmd = cmdlist;
143 unsigned *ptr = ptrlist;
144 unsigned *data = ptrlist + 4;
145
146 data[0] = 0 | 4;
147 data[1] = NAND_CMD_FETCH_ID;
148 data[2] = 1;
149 data[3] = 0;
150 data[4] = 0;
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800151 data[5] = 0;
152 data[6] = 0;
153 data[7] = 0xAAD40000; /* Default value for CFG0 for reading device id */
Dima Zavin03cf4312009-01-23 16:38:30 -0800154
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800155 /* Read NAND device id */
Dima Zavin03cf4312009-01-23 16:38:30 -0800156 cmd[0].cmd = 0 | CMD_OCB;
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800157 cmd[0].src = paddr(&data[7]);
158 cmd[0].dst = NAND_DEV0_CFG0;
Dima Zavin03cf4312009-01-23 16:38:30 -0800159 cmd[0].len = 4;
160
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800161 cmd[1].cmd = 0;
162 cmd[1].src = NAND_SFLASHC_BURST_CFG;
163 cmd[1].dst = paddr(&data[5]);
Dima Zavin03cf4312009-01-23 16:38:30 -0800164 cmd[1].len = 4;
165
166 cmd[2].cmd = 0;
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800167 cmd[2].src = paddr(&data[6]);
168 cmd[2].dst = NAND_SFLASHC_BURST_CFG;
Dima Zavin03cf4312009-01-23 16:38:30 -0800169 cmd[2].len = 4;
170
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800171 cmd[3].cmd = 0;
172 cmd[3].src = paddr(&data[0]);
173 cmd[3].dst = NAND_FLASH_CHIP_SELECT;
Dima Zavin03cf4312009-01-23 16:38:30 -0800174 cmd[3].len = 4;
175
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800176 cmd[4].cmd = DST_CRCI_NAND_CMD;
177 cmd[4].src = paddr(&data[1]);
178 cmd[4].dst = NAND_FLASH_CMD;
Dima Zavin03cf4312009-01-23 16:38:30 -0800179 cmd[4].len = 4;
180
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800181 cmd[5].cmd = 0;
182 cmd[5].src = paddr(&data[2]);
183 cmd[5].dst = NAND_EXEC_CMD;
184 cmd[5].len = 4;
185
186 cmd[6].cmd = SRC_CRCI_NAND_DATA;
187 cmd[6].src = NAND_FLASH_STATUS;
188 cmd[6].dst = paddr(&data[3]);
189 cmd[6].len = 4;
190
191 cmd[7].cmd = 0;
192 cmd[7].src = NAND_READ_ID;
193 cmd[7].dst = paddr(&data[4]);
194 cmd[7].len = 4;
195
196 cmd[8].cmd = CMD_OCU | CMD_LC;
197 cmd[8].src = paddr(&data[5]);
198 cmd[8].dst = NAND_SFLASHC_BURST_CFG;
199 cmd[8].len = 4;
200
Dima Zavin03cf4312009-01-23 16:38:30 -0800201 ptr[0] = (paddr(cmd) >> 3) | CMD_PTR_LP;
202
203 dmov_exec_cmdptr(DMOV_NAND_CHAN, ptr);
204
205#if VERBOSE
206 dprintf(INFO, "status: %x\n", data[3]);
207#endif
Dima Zavin03cf4312009-01-23 16:38:30 -0800208
Shashank Mittal83d16d02009-11-18 16:54:42 -0800209 flash_info.id = data[4];
Dima Zavinca337f52009-03-02 16:41:44 -0800210 flash_info.vendor = data[4] & 0xff;
211 flash_info.device = (data[4] >> 8) & 0xff;
Shashank Mittal83d16d02009-11-18 16:54:42 -0800212 return;
213}
Dima Zavinca337f52009-03-02 16:41:44 -0800214
Shashank Mittalad3d05c2009-11-19 15:53:57 -0800215static int flash_nand_block_isbad(dmov_s *cmdlist, unsigned *ptrlist,
216 unsigned page)
217{
218 dmov_s *cmd = cmdlist;
219 unsigned *ptr = ptrlist;
220 unsigned *data = ptrlist + 4;
221 char buf[4];
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800222 unsigned cwperpage;
223
224 cwperpage = (flash_pagesize >> 9);
Shashank Mittalad3d05c2009-11-19 15:53:57 -0800225
226 /* Check first page of this block */
227 if(page & 63)
228 page = page - (page & 63);
229
230 /* Check bad block marker */
231 data[0] = NAND_CMD_PAGE_READ; /* command */
232
233 /* addr0 */
234 if (CFG1 & CFG1_WIDE_FLASH)
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800235 data[1] = (page << 16) | ((528*(cwperpage-1)) >> 1);
Shashank Mittalad3d05c2009-11-19 15:53:57 -0800236 else
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800237 data[1] = (page << 16) | (528*(cwperpage-1));
Shashank Mittalad3d05c2009-11-19 15:53:57 -0800238
239 data[2] = (page >> 16) & 0xff; /* addr1 */
240 data[3] = 0 | 4; /* chipsel */
241 data[4] = NAND_CFG0_RAW & ~(7U << 6); /* cfg0 */
242 data[5] = NAND_CFG1_RAW | (CFG1 & CFG1_WIDE_FLASH); /* cfg1 */
243 data[6] = 1;
244 data[7] = CLEAN_DATA_32; /* flash status */
245 data[8] = CLEAN_DATA_32; /* buf status */
246
247 cmd[0].cmd = DST_CRCI_NAND_CMD | CMD_OCB;
248 cmd[0].src = paddr(&data[0]);
249 cmd[0].dst = NAND_FLASH_CMD;
250 cmd[0].len = 16;
251
252 cmd[1].cmd = 0;
253 cmd[1].src = paddr(&data[4]);
254 cmd[1].dst = NAND_DEV0_CFG0;
255 cmd[1].len = 8;
256
257 cmd[2].cmd = 0;
258 cmd[2].src = paddr(&data[6]);
259 cmd[2].dst = NAND_EXEC_CMD;
260 cmd[2].len = 4;
261
262 cmd[3].cmd = SRC_CRCI_NAND_DATA;
263 cmd[3].src = NAND_FLASH_STATUS;
264 cmd[3].dst = paddr(&data[7]);
265 cmd[3].len = 8;
266
267 cmd[4].cmd = CMD_OCU | CMD_LC;
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800268 cmd[4].src = NAND_FLASH_BUFFER + (flash_pagesize - (528*(cwperpage-1)));
Shashank Mittalad3d05c2009-11-19 15:53:57 -0800269 cmd[4].dst = paddr(&buf);
270 cmd[4].len = 4;
271
272 ptr[0] = (paddr(cmd) >> 3) | CMD_PTR_LP;
273
274 dmov_exec_cmdptr(DMOV_NAND_CHAN, ptr);
275
276#if VERBOSE
277 dprintf(INFO, "status: %x\n", data[7]);
278#endif
279
280 /* we fail if there was an operation error, a mpu error, or the
281 ** erase success bit was not set.
282 */
283 if(data[7] & 0x110) return -1;
284
285 /* Check for bad block marker byte */
286 if (CFG1 & CFG1_WIDE_FLASH) {
287 if (buf[0] != 0xFF || buf[1] != 0xFF)
288 return 1;
289 } else {
290 if (buf[0] != 0xFF)
291 return 1;
292 }
293
294 return 0;
295}
296
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800297static int flash_nand_erase_block(dmov_s *cmdlist, unsigned *ptrlist,
298 unsigned page)
Dima Zavin03cf4312009-01-23 16:38:30 -0800299{
300 dmov_s *cmd = cmdlist;
301 unsigned *ptr = ptrlist;
302 unsigned *data = ptrlist + 4;
Shashank Mittalad3d05c2009-11-19 15:53:57 -0800303 int isbad = 0;
Dima Zavin03cf4312009-01-23 16:38:30 -0800304
305 /* only allow erasing on block boundaries */
306 if(page & 63) return -1;
307
Shashank Mittalad3d05c2009-11-19 15:53:57 -0800308 /* Check for bad block and erase only if block is not marked bad */
309 isbad = flash_nand_block_isbad(cmdlist, ptrlist, page);
310
311 if (isbad) {
312 dprintf(INFO, "skipping @ %d (bad block)\n", page >> 6);
313 return -1;
314 }
315
316 /* Erase block */
Dima Zavin03cf4312009-01-23 16:38:30 -0800317 data[0] = NAND_CMD_BLOCK_ERASE;
318 data[1] = page;
319 data[2] = 0;
320 data[3] = 0 | 4;
321 data[4] = 1;
322 data[5] = 0xeeeeeeee;
323 data[6] = CFG0 & (~(7 << 6)); /* CW_PER_PAGE = 0 */
324 data[7] = CFG1;
325
326 cmd[0].cmd = DST_CRCI_NAND_CMD | CMD_OCB;
327 cmd[0].src = paddr(&data[0]);
328 cmd[0].dst = NAND_FLASH_CMD;
329 cmd[0].len = 16;
330
331 cmd[1].cmd = 0;
332 cmd[1].src = paddr(&data[6]);
333 cmd[1].dst = NAND_DEV0_CFG0;
334 cmd[1].len = 8;
335
336 cmd[2].cmd = 0;
337 cmd[2].src = paddr(&data[4]);
338 cmd[2].dst = NAND_EXEC_CMD;
339 cmd[2].len = 4;
340
341 cmd[3].cmd = SRC_CRCI_NAND_DATA | CMD_OCU | CMD_LC;
342 cmd[3].src = NAND_FLASH_STATUS;
343 cmd[3].dst = paddr(&data[5]);
344 cmd[3].len = 4;
345
346 ptr[0] = (paddr(cmd) >> 3) | CMD_PTR_LP;
347
348 dmov_exec_cmdptr(DMOV_NAND_CHAN, ptr);
349
350#if VERBOSE
351 dprintf(INFO, "status: %x\n", data[5]);
352#endif
353
354 /* we fail if there was an operation error, a mpu error, or the
355 ** erase success bit was not set.
356 */
357 if(data[5] & 0x110) return -1;
358 if(!(data[5] & 0x80)) return -1;
359
360 return 0;
361}
362
363struct data_flash_io {
364 unsigned cmd;
365 unsigned addr0;
366 unsigned addr1;
367 unsigned chipsel;
368 unsigned cfg0;
369 unsigned cfg1;
370 unsigned exec;
371 unsigned ecc_cfg;
372 unsigned ecc_cfg_save;
373 struct {
374 unsigned flash_status;
375 unsigned buffer_status;
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800376 } result[8];
Dima Zavin03cf4312009-01-23 16:38:30 -0800377};
378
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800379static int _flash_nand_read_page(dmov_s *cmdlist, unsigned *ptrlist,
380 unsigned page, void *_addr, void *_spareaddr)
Dima Zavin03cf4312009-01-23 16:38:30 -0800381{
382 dmov_s *cmd = cmdlist;
383 unsigned *ptr = ptrlist;
384 struct data_flash_io *data = (void*) (ptrlist + 4);
385 unsigned addr = (unsigned) _addr;
386 unsigned spareaddr = (unsigned) _spareaddr;
387 unsigned n;
Shashank Mittalad3d05c2009-11-19 15:53:57 -0800388 int isbad = 0;
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800389 unsigned cwperpage;
390 cwperpage = (flash_pagesize >> 9);
Shashank Mittalad3d05c2009-11-19 15:53:57 -0800391
392 /* Check for bad block and read only from a good block */
393 isbad = flash_nand_block_isbad(cmdlist, ptrlist, page);
394 if (isbad)
395 return -2;
Dima Zavin03cf4312009-01-23 16:38:30 -0800396
397 data->cmd = NAND_CMD_PAGE_READ_ECC;
398 data->addr0 = page << 16;
399 data->addr1 = (page >> 16) & 0xff;
400 data->chipsel = 0 | 4; /* flash0 + undoc bit */
401
402 /* GO bit for the EXEC register */
403 data->exec = 1;
404
405 data->cfg0 = CFG0;
406 data->cfg1 = CFG1;
407
408 data->ecc_cfg = 0x203;
409
410 /* save existing ecc config */
411 cmd->cmd = CMD_OCB;
412 cmd->src = NAND_EBI2_ECC_BUF_CFG;
413 cmd->dst = paddr(&data->ecc_cfg_save);
414 cmd->len = 4;
415 cmd++;
416
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800417 for(n = 0; n < cwperpage; n++) {
Dima Zavin03cf4312009-01-23 16:38:30 -0800418 /* write CMD / ADDR0 / ADDR1 / CHIPSEL regs in a burst */
419 cmd->cmd = DST_CRCI_NAND_CMD;
420 cmd->src = paddr(&data->cmd);
421 cmd->dst = NAND_FLASH_CMD;
422 cmd->len = ((n == 0) ? 16 : 4);
423 cmd++;
424
425 if (n == 0) {
426 /* block on cmd ready, set configuration */
427 cmd->cmd = 0;
428 cmd->src = paddr(&data->cfg0);
429 cmd->dst = NAND_DEV0_CFG0;
430 cmd->len = 8;
431 cmd++;
432
433 /* set our ecc config */
434 cmd->cmd = 0;
435 cmd->src = paddr(&data->ecc_cfg);
436 cmd->dst = NAND_EBI2_ECC_BUF_CFG;
437 cmd->len = 4;
438 cmd++;
439 }
440 /* kick the execute register */
441 cmd->cmd = 0;
442 cmd->src = paddr(&data->exec);
443 cmd->dst = NAND_EXEC_CMD;
444 cmd->len = 4;
445 cmd++;
446
447 /* block on data ready, then read the status register */
448 cmd->cmd = SRC_CRCI_NAND_DATA;
449 cmd->src = NAND_FLASH_STATUS;
450 cmd->dst = paddr(&data->result[n]);
451 cmd->len = 8;
452 cmd++;
453
454 /* read data block */
455 cmd->cmd = 0;
456 cmd->src = NAND_FLASH_BUFFER;
457 cmd->dst = addr + n * 516;
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800458 cmd->len = ((n < (cwperpage -1 )) ? 516 : (512 - ((cwperpage - 1) << 2)));
Dima Zavin03cf4312009-01-23 16:38:30 -0800459 cmd++;
460 }
461
462 /* read extra data */
463 cmd->cmd = 0;
464 cmd->src = NAND_FLASH_BUFFER + 500;
465 cmd->dst = spareaddr;
466 cmd->len = 16;
467 cmd++;
468
469 /* restore saved ecc config */
470 cmd->cmd = CMD_OCU | CMD_LC;
471 cmd->src = paddr(&data->ecc_cfg_save);
472 cmd->dst = NAND_EBI2_ECC_BUF_CFG;
473 cmd->len = 4;
474
475 ptr[0] = (paddr(cmdlist) >> 3) | CMD_PTR_LP;
476
477 dmov_exec_cmdptr(DMOV_NAND_CHAN, ptr);
478
479#if VERBOSE
480 dprintf(INFO, "read page %d: status: %x %x %x %x\n",
481 page, data[5], data[6], data[7], data[8]);
482 for(n = 0; n < 4; n++) {
483 ptr = (unsigned*)(addr + 512 * n);
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800484 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 -0800485 ptr = (unsigned*)(spareaddr + 16 * n);
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800486 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 -0800487 }
488#endif
489
490 /* if any of the writes failed (0x10), or there was a
491 ** protection violation (0x100), we lose
492 */
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800493 for(n = 0; n < cwperpage; n++) {
Dima Zavin03cf4312009-01-23 16:38:30 -0800494 if (data->result[n].flash_status & 0x110) {
495 return -1;
496 }
497 }
498
499 return 0;
500}
501
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800502static int _flash_nand_write_page(dmov_s *cmdlist, unsigned *ptrlist, unsigned page,
Shashank Mittald0c836d2009-11-20 10:31:18 -0800503 const void *_addr, const void *_spareaddr, unsigned raw_mode)
Dima Zavin03cf4312009-01-23 16:38:30 -0800504{
505 dmov_s *cmd = cmdlist;
506 unsigned *ptr = ptrlist;
507 struct data_flash_io *data = (void*) (ptrlist + 4);
508 unsigned addr = (unsigned) _addr;
509 unsigned spareaddr = (unsigned) _spareaddr;
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800510 unsigned n;
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800511 unsigned cwperpage;
512 cwperpage = (flash_pagesize >> 9);
Dima Zavin03cf4312009-01-23 16:38:30 -0800513
514 data->cmd = NAND_CMD_PRG_PAGE;
515 data->addr0 = page << 16;
516 data->addr1 = (page >> 16) & 0xff;
517 data->chipsel = 0 | 4; /* flash0 + undoc bit */
518
Shashank Mittald0c836d2009-11-20 10:31:18 -0800519 if (!raw_mode){
520 data->cfg0 = CFG0;
521 data->cfg1 = CFG1;
522 }else{
523 data->cfg0 = (NAND_CFG0_RAW & ~(7 << 6)) |((cwperpage-1) << 6);
524 data->cfg1 = NAND_CFG1_RAW | (CFG1 & CFG1_WIDE_FLASH);
525 }
Dima Zavin03cf4312009-01-23 16:38:30 -0800526
527 /* GO bit for the EXEC register */
528 data->exec = 1;
529
530 data->ecc_cfg = 0x203;
531
532 /* save existing ecc config */
533 cmd->cmd = CMD_OCB;
534 cmd->src = NAND_EBI2_ECC_BUF_CFG;
535 cmd->dst = paddr(&data->ecc_cfg_save);
536 cmd->len = 4;
537 cmd++;
538
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800539 for(n = 0; n < cwperpage; n++) {
540 /* write CMD / ADDR0 / ADDR1 / CHIPSEL regs in a burst */
Dima Zavin03cf4312009-01-23 16:38:30 -0800541 cmd->cmd = DST_CRCI_NAND_CMD;
542 cmd->src = paddr(&data->cmd);
543 cmd->dst = NAND_FLASH_CMD;
544 cmd->len = ((n == 0) ? 16 : 4);
545 cmd++;
546
547 if (n == 0) {
548 /* set configuration */
549 cmd->cmd = 0;
550 cmd->src = paddr(&data->cfg0);
551 cmd->dst = NAND_DEV0_CFG0;
552 cmd->len = 8;
553 cmd++;
554
555 /* set our ecc config */
556 cmd->cmd = 0;
557 cmd->src = paddr(&data->ecc_cfg);
558 cmd->dst = NAND_EBI2_ECC_BUF_CFG;
559 cmd->len = 4;
560 cmd++;
561 }
562
563 /* write data block */
564 cmd->cmd = 0;
Dima Zavin03cf4312009-01-23 16:38:30 -0800565 cmd->dst = NAND_FLASH_BUFFER;
Shashank Mittald0c836d2009-11-20 10:31:18 -0800566 if (!raw_mode){
567 cmd->src = addr + n * 516;
568 cmd->len = ((n < (cwperpage - 1)) ? 516 : (512 - ((cwperpage - 1) << 2)));
569 }else{
570 cmd->src = addr;
571 cmd->len = 528;
572 }
Dima Zavin03cf4312009-01-23 16:38:30 -0800573 cmd++;
574
Shashank Mittald0c836d2009-11-20 10:31:18 -0800575 if ((n == (cwperpage - 1)) && (!raw_mode)) {
Dima Zavin03cf4312009-01-23 16:38:30 -0800576 /* write extra data */
577 cmd->cmd = 0;
578 cmd->src = spareaddr;
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800579 cmd->dst = NAND_FLASH_BUFFER + (512 - ((cwperpage - 1) << 2));
580 cmd->len = (cwperpage << 2);
Dima Zavin03cf4312009-01-23 16:38:30 -0800581 cmd++;
582 }
583
584 /* kick the execute register */
585 cmd->cmd = 0;
586 cmd->src = paddr(&data->exec);
587 cmd->dst = NAND_EXEC_CMD;
588 cmd->len = 4;
589 cmd++;
590
591 /* block on data ready, then read the status register */
592 cmd->cmd = SRC_CRCI_NAND_DATA;
593 cmd->src = NAND_FLASH_STATUS;
594 cmd->dst = paddr(&data->result[n]);
595 cmd->len = 8;
596 cmd++;
597 }
598
599 /* restore saved ecc config */
600 cmd->cmd = CMD_OCU | CMD_LC;
601 cmd->src = paddr(&data->ecc_cfg_save);
602 cmd->dst = NAND_EBI2_ECC_BUF_CFG;
603 cmd->len = 4;
604
605 ptr[0] = (paddr(cmdlist) >> 3) | CMD_PTR_LP;
606
607 dmov_exec_cmdptr(DMOV_NAND_CHAN, ptr);
608
609#if VERBOSE
610 dprintf(INFO, "write page %d: status: %x %x %x %x\n",
611 page, data[5], data[6], data[7], data[8]);
612#endif
613
614 /* if any of the writes failed (0x10), or there was a
615 ** protection violation (0x100), or the program success
616 ** bit (0x80) is unset, we lose
617 */
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800618 for(n = 0; n < cwperpage; n++) {
Dima Zavin03cf4312009-01-23 16:38:30 -0800619 if(data->result[n].flash_status & 0x110) return -1;
620 if(!(data->result[n].flash_status & 0x80)) return -1;
621 }
622
Dima Zavin5582c7d2009-03-03 15:17:59 -0800623#if VERIFY_WRITE
624 n = _flash_read_page(cmdlist, ptrlist, page, flash_data,
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800625 flash_data + 2048);
Dima Zavin5582c7d2009-03-03 15:17:59 -0800626 if (n != 0)
627 return -1;
628 if (memcmp(flash_data, _addr, 2048) ||
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800629 memcmp(flash_data + 2048, _spareaddr, 16)) {
Dima Zavin5582c7d2009-03-03 15:17:59 -0800630 dprintf(CRITICAL, "verify error @ page %d\n", page);
631 return -1;
632 }
633#endif
Dima Zavin03cf4312009-01-23 16:38:30 -0800634 return 0;
635}
Shashank Mittald0c836d2009-11-20 10:31:18 -0800636char empty_buf[528];
637static int flash_nand_mark_badblock(dmov_s *cmdlist, unsigned *ptrlist, unsigned page)
638{
639 memset(empty_buf,0,528);
640 /* Going to first page of the block */
641 if(page & 63)
642 page = page - (page & 63);
643 return _flash_nand_write_page(cmdlist, ptrlist, page, empty_buf, 0, 1);
644}
Dima Zavin03cf4312009-01-23 16:38:30 -0800645
Shashank Mittal83d16d02009-11-18 16:54:42 -0800646unsigned nand_cfg0;
647unsigned nand_cfg1;
648
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800649static int flash_nand_read_config(dmov_s *cmdlist, unsigned *ptrlist)
Dima Zavin03cf4312009-01-23 16:38:30 -0800650{
651 cmdlist[0].cmd = CMD_OCB;
652 cmdlist[0].src = NAND_DEV0_CFG0;
653 cmdlist[0].dst = paddr(&CFG0);
654 cmdlist[0].len = 4;
655
656 cmdlist[1].cmd = CMD_OCU | CMD_LC;
657 cmdlist[1].src = NAND_DEV0_CFG1;
658 cmdlist[1].dst = paddr(&CFG1);
659 cmdlist[1].len = 4;
660
661 *ptrlist = (paddr(cmdlist) >> 3) | CMD_PTR_LP;
662
663 dmov_exec_cmdptr(DMOV_NAND_CHAN, ptrlist);
664
665 if((CFG0 == 0) || (CFG1 == 0)) {
666 return -1;
667 }
668
Shashank Mittal83d16d02009-11-18 16:54:42 -0800669 if (flash_info.type == FLASH_16BIT_NAND_DEVICE) {
670 nand_cfg1 |= CFG1_WIDE_FLASH;
671 }
Dima Zavin03cf4312009-01-23 16:38:30 -0800672 dprintf(INFO, "nandcfg: %x %x (initial)\n", CFG0, CFG1);
673
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800674 CFG0 = (((flash_pagesize >> 9) - 1) << 6) /* 4/8 cw/pg for 2/4k */
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800675 | (516 << 9) /* 516 user data bytes */
676 | (10 << 19) /* 10 parity bytes */
677 | (5 << 27) /* 5 address cycles */
678 | (1 << 30) /* Read status before data */
679 | (1 << 31) /* Send read cmd */
680 /* 0 spare bytes for 16 bit nand or 1 spare bytes for 8 bit */
681 | ((nand_cfg1 & CFG1_WIDE_FLASH) ? (0 << 23) : (1 << 23));
Dima Zavin03cf4312009-01-23 16:38:30 -0800682 CFG1 = (0 << 0) /* Enable ecc */
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800683 | (7 << 2) /* 8 recovery cycles */
684 | (0 << 5) /* Allow CS deassertion */
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800685 | ((flash_pagesize - (528 * ((flash_pagesize >> 9) - 1)) + 1) << 6) /* Bad block marker location */
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800686 | (0 << 16) /* Bad block in user data area */
687 | (2 << 17) /* 6 cycle tWB/tRB */
688 | (nand_cfg1 & CFG1_WIDE_FLASH); /* preserve wide flash flag */
Dima Zavin03cf4312009-01-23 16:38:30 -0800689
690 dprintf(INFO, "nandcfg: %x %x (used)\n", CFG0, CFG1);
691
692 return 0;
693}
694
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800695/* OneNAND programming functions */
696
697static void flash_onenand_read_id(dmov_s *cmdlist, unsigned *ptrlist)
698{
699 dmov_s *cmd = cmdlist;
700 unsigned *ptr = ptrlist;
701 unsigned *data = ptrlist + 4;
702
703 data[0] = SFLASH_BCFG;
704 data[1] = SFLASH_PREPCMD(8, 0, 0, NAND_SFCMD_DATXS, NAND_SFCMD_ASYNC, NAND_SFCMD_REGRD);
705 data[2] = (ONENAND_DEVICE_ID << 16) | (ONENAND_MANUFACTURER_ID);
706 data[3] = (ONENAND_DATA_BUFFER_SIZE << 16) | (ONENAND_VERSION_ID);
707 data[4] = (ONENAND_AMOUNT_OF_BUFFERS << 16) | (ONENAND_BOOT_BUFFER_SIZE);
708 data[5] = (CLEAN_DATA_16 << 16) | (ONENAND_TECHNOLOGY);
709 data[6] = CLEAN_DATA_32; //status
710 data[7] = CLEAN_DATA_32; //register read
711 data[8] = CLEAN_DATA_32; //register read
712 data[9] = CLEAN_DATA_32; //register read
713 data[10] = CLEAN_DATA_32; //register read
714 data[11] = 1;
715 data[12] = 0 | 4;
716
717 /* Setup controller in SFLASH mode */
718 cmd[0].cmd = 0 | CMD_OCB;
719 cmd[0].src = paddr(&data[0]);
720 cmd[0].dst = NAND_SFLASHC_BURST_CFG;
721 cmd[0].len = 4;
722
723 /* Enable data mover for controller */
724 cmd[1].cmd = 0;
725 cmd[1].src = paddr(&data[12]);
726 cmd[1].dst = NAND_FLASH_CHIP_SELECT;
727 cmd[1].len = 4;
728
729 /* Setup SFLASHC_CMD with xfers in async mode */
730 cmd[2].cmd = DST_CRCI_NAND_CMD;
731 cmd[2].src = paddr(&data[1]);
732 cmd[2].dst = NAND_SFLASHC_CMD;
733 cmd[2].len = 4;
734
735 /* Setup to read device information */
736 cmd[3].cmd = 0;
737 cmd[3].src = paddr(&data[2]);
738 cmd[3].dst = NAND_ADDR0;
739 cmd[3].len = 8;
740
741 cmd[4].cmd = 0;
742 cmd[4].src = paddr(&data[4]);
743 cmd[4].dst = NAND_ADDR2;
744 cmd[4].len = 8;
745
746 /* Set execute bit */
747 cmd[5].cmd = 0;
748 cmd[5].src = paddr(&data[11]);
749 cmd[5].dst = NAND_SFLASHC_EXEC_CMD;
750 cmd[5].len = 4;
751
752 /* Check status */
753 cmd[6].cmd = SRC_CRCI_NAND_DATA;
754 cmd[6].src = NAND_SFLASHC_STATUS;
755 cmd[6].dst = paddr(&data[6]);
756 cmd[6].len = 4;
757
758 /* Read result device registers */
759 cmd[7].cmd = 0 | CMD_OCU | CMD_LC;
760 cmd[7].src = NAND_GENP_REG0;
761 cmd[7].dst = paddr(&data[7]);
762 cmd[7].len = 16;
763
764 ptr[0] = (paddr(cmd) >> 3) | CMD_PTR_LP;
765
766 dmov_exec_cmdptr(DMOV_NAND_CHAN, ptr);
767
768#if VERBOSE
769 dprintf(INFO, "status: %x\n", data[6]);
770#endif
771
772 flash_info.id = data[7];
773 flash_info.vendor = data[7] & CLEAN_DATA_16;
774 flash_info.device = (data[7] >> 16) & CLEAN_DATA_16;
775 return;
776}
777
778
779struct data_onenand_erase {
780 unsigned sfbcfg;
781 unsigned sfcmd[4];
782 unsigned sfexec;
783 unsigned sfstat[4];
784 unsigned addr0;
785 unsigned addr1;
786 unsigned addr2;
787 unsigned addr3;
788 unsigned addr4;
789 unsigned addr5;
790 unsigned addr6;
791 unsigned data0;
792 unsigned data1;
793 unsigned data2;
794 unsigned data3;
795 unsigned data4;
796 unsigned data5;
797 unsigned data6;
798};
799
Shashank Mittalad3d05c2009-11-19 15:53:57 -0800800
801static int _flash_onenand_read_page(dmov_s *cmdlist, unsigned *ptrlist,
802 unsigned page, void *_addr,
803 void *_spareaddr, unsigned raw_mode);
804
805
806static int flash_onenand_block_isbad(dmov_s *cmdlist, unsigned *ptrlist,
807 unsigned page)
808{
809 unsigned char page_data[2112];
810 unsigned char *oobptr = &(page_data[2048]);
811
812 /* Going to first page of the block */
813 if(page & 63)
814 page = page - (page & 63);
815
816 /* Reading page in raw mode */
817 if (_flash_onenand_read_page(cmdlist, ptrlist,page, page_data, 0, 1))
818 return 1;
819
820 /* Checking if block is bad */
821 if ((oobptr[0] != 0xFF) || (oobptr[1] != 0xFF) ||
822 (oobptr[16] != 0xFF) || (oobptr[17] != 0xFF) ||
823 (oobptr[32] != 0xFF) || (oobptr[33] != 0xFF) ||
824 (oobptr[48] != 0xFF) || (oobptr[49] != 0xFF)
825 )
826 {
827 return 1;
828 }
829 return 0;
830}
831
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800832static int flash_onenand_erase_block(dmov_s *cmdlist, unsigned *ptrlist,
833 unsigned page)
834{
835 dmov_s *cmd = cmdlist;
836 unsigned *ptr = ptrlist;
837 struct data_onenand_erase *data = (void *)ptrlist + 4;
Shashank Mittalad3d05c2009-11-19 15:53:57 -0800838 int isbad = 0;
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800839 unsigned erasesize = (flash_pagesize << 6);
840 unsigned onenand_startaddr1 = DEVICE_FLASHCORE_0 | (page * flash_pagesize)/erasesize;
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800841 unsigned onenand_startaddr8 = 0x0000;
842 unsigned onenand_startaddr2 = DEVICE_BUFFERRAM_0 << 15;
843 unsigned onenand_startbuffer = DATARAM0_0 << 8;
844
845 unsigned controller_status;
846 unsigned interrupt_status;
847 unsigned ecc_status;
848
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800849 if((page * flash_pagesize) & (erasesize-1)) return -1;
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800850
Shashank Mittalad3d05c2009-11-19 15:53:57 -0800851 /* Check for bad block and erase only if block is not marked bad */
852 isbad = flash_onenand_block_isbad(cmdlist, ptrlist, page);
853 if (isbad)
854 {
855 dprintf(INFO, "skipping @ %d (bad block)\n", page >> 6);
856 return -1;
857 }
858
859 /*Erase block*/
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800860 onenand_startaddr1 = DEVICE_FLASHCORE_0 |
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800861 ((page * flash_pagesize) / (erasesize));
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800862 onenand_startaddr8 = 0x0000;
863 onenand_startaddr2 = DEVICE_BUFFERRAM_0 << 15;
864 onenand_startbuffer = DATARAM0_0 << 8;
865
866
867 data->sfbcfg = SFLASH_BCFG;
868 data->sfcmd[0] = SFLASH_PREPCMD(7, 0, 0,
869 NAND_SFCMD_CMDXS,
870 NAND_SFCMD_ASYNC,
871 NAND_SFCMD_REGWR);
872 data->sfcmd[1] = SFLASH_PREPCMD(0, 0, 32,
873 NAND_SFCMD_CMDXS,
874 NAND_SFCMD_ASYNC,
875 NAND_SFCMD_INTHI);
876 data->sfcmd[2] = SFLASH_PREPCMD(3, 7, 0,
877 NAND_SFCMD_DATXS,
878 NAND_SFCMD_ASYNC,
879 NAND_SFCMD_REGRD);
880 data->sfcmd[3] = SFLASH_PREPCMD(4, 10, 0,
881 NAND_SFCMD_CMDXS,
882 NAND_SFCMD_ASYNC,
883 NAND_SFCMD_REGWR);
884 data->sfexec = 1;
885 data->sfstat[0] = CLEAN_DATA_32;
886 data->sfstat[1] = CLEAN_DATA_32;
887 data->sfstat[2] = CLEAN_DATA_32;
888 data->sfstat[3] = CLEAN_DATA_32;
889 data->addr0 = (ONENAND_INTERRUPT_STATUS << 16) |
890 (ONENAND_SYSTEM_CONFIG_1);
891 data->addr1 = (ONENAND_START_ADDRESS_8 << 16) |
892 (ONENAND_START_ADDRESS_1);
893 data->addr2 = (ONENAND_START_BUFFER << 16) |
894 (ONENAND_START_ADDRESS_2);
895 data->addr3 = (ONENAND_ECC_STATUS << 16) |
896 (ONENAND_COMMAND);
897 data->addr4 = (ONENAND_CONTROLLER_STATUS << 16) |
898 (ONENAND_INTERRUPT_STATUS);
899 data->addr5 = (ONENAND_INTERRUPT_STATUS << 16) |
900 (ONENAND_SYSTEM_CONFIG_1);
901 data->addr6 = (ONENAND_START_ADDRESS_3 << 16) |
902 (ONENAND_START_ADDRESS_1);
903 data->data0 = (ONENAND_CLRINTR << 16) |
904 (ONENAND_SYSCFG1_ECCENA);
905 data->data1 = (onenand_startaddr8 << 16) |
906 (onenand_startaddr1);
907 data->data2 = (onenand_startbuffer << 16) |
908 (onenand_startaddr2);
909 data->data3 = (CLEAN_DATA_16 << 16) |
910 (ONENAND_CMDERAS);
911 data->data4 = (CLEAN_DATA_16 << 16) |
912 (CLEAN_DATA_16);
913 data->data5 = (ONENAND_CLRINTR << 16) |
914 (ONENAND_SYSCFG1_ECCENA);
915 data->data6 = (ONENAND_STARTADDR3_RES << 16) |
916 (ONENAND_STARTADDR1_RES);
917
918 /***************************************************************/
919 /* Write the necessary address registers in the onenand device */
920 /***************************************************************/
921
922 /* Enable and configure the SFlash controller */
923 cmd->cmd = 0 | CMD_OCB;
924 cmd->src = paddr(&data->sfbcfg);
925 cmd->dst = NAND_SFLASHC_BURST_CFG;
926 cmd->len = 4;
927 cmd++;
928
929 /* Block on cmd ready and write CMD register */
930 cmd->cmd = DST_CRCI_NAND_CMD;
931 cmd->src = paddr(&data->sfcmd[0]);
932 cmd->dst = NAND_SFLASHC_CMD;
933 cmd->len = 4;
934 cmd++;
935
936 /* Write the ADDR0 and ADDR1 registers */
937 cmd->cmd = 0;
938 cmd->src = paddr(&data->addr0);
939 cmd->dst = NAND_ADDR0;
940 cmd->len = 8;
941 cmd++;
942
943 /* Write the ADDR2 ADDR3 ADDR4 ADDR5 registers */
944 cmd->cmd = 0;
945 cmd->src = paddr(&data->addr2);
946 cmd->dst = NAND_ADDR2;
947 cmd->len = 16;
948 cmd++;
949
950 /* Write the ADDR6 registers */
951 cmd->cmd = 0;
952 cmd->src = paddr(&data->addr6);
953 cmd->dst = NAND_ADDR6;
954 cmd->len = 4;
955 cmd++;
956
957 /* Write the GENP0, GENP1, GENP2, GENP3, GENP4 registers */
958 cmd->cmd = 0;
959 cmd->src = paddr(&data->data0);
960 cmd->dst = NAND_GENP_REG0;
961 cmd->len = 16;
962 cmd++;
963
964 /* Write the FLASH_DEV_CMD4,5,6 registers */
965 cmd->cmd = 0;
966 cmd->src = paddr(&data->data4);
967 cmd->dst = NAND_DEV_CMD4;
968 cmd->len = 12;
969 cmd++;
970
971 /* Kick the execute command */
972 cmd->cmd = 0;
973 cmd->src = paddr(&data->sfexec);
974 cmd->dst = NAND_SFLASHC_EXEC_CMD;
975 cmd->len = 4;
976 cmd++;
977
978 /* Block on data ready, and read the status register */
979 cmd->cmd = SRC_CRCI_NAND_DATA;
980 cmd->src = NAND_SFLASHC_STATUS;
981 cmd->dst = paddr(&data->sfstat[0]);
982 cmd->len = 4;
983 cmd++;
984
985 /***************************************************************/
986 /* Wait for the interrupt from the Onenand device controller */
987 /***************************************************************/
988
989 /* Block on cmd ready and write CMD register */
990 cmd->cmd = DST_CRCI_NAND_CMD;
991 cmd->src = paddr(&data->sfcmd[1]);
992 cmd->dst = NAND_SFLASHC_CMD;
993 cmd->len = 4;
994 cmd++;
995
996 /* Kick the execute command */
997 cmd->cmd = 0;
998 cmd->src = paddr(&data->sfexec);
999 cmd->dst = NAND_SFLASHC_EXEC_CMD;
1000 cmd->len = 4;
1001 cmd++;
1002
1003 /* Block on data ready, and read the status register */
1004 cmd->cmd = SRC_CRCI_NAND_DATA;
1005 cmd->src = NAND_SFLASHC_STATUS;
1006 cmd->dst = paddr(&data->sfstat[1]);
1007 cmd->len = 4;
1008 cmd++;
1009
1010 /***************************************************************/
1011 /* Read the necessary status registers from the onenand device */
1012 /***************************************************************/
1013
1014 /* Block on cmd ready and write CMD register */
1015 cmd->cmd = DST_CRCI_NAND_CMD;
1016 cmd->src = paddr(&data->sfcmd[2]);
1017 cmd->dst = NAND_SFLASHC_CMD;
1018 cmd->len = 4;
1019 cmd++;
1020
1021 /* Kick the execute command */
1022 cmd->cmd = 0;
1023 cmd->src = paddr(&data->sfexec);
1024 cmd->dst = NAND_SFLASHC_EXEC_CMD;
1025 cmd->len = 4;
1026 cmd++;
1027
1028 /* Block on data ready, and read the status register */
1029 cmd->cmd = SRC_CRCI_NAND_DATA;
1030 cmd->src = NAND_SFLASHC_STATUS;
1031 cmd->dst = paddr(&data->sfstat[2]);
1032 cmd->len = 4;
1033 cmd++;
1034
1035 /* Read the GENP3 register */
1036 cmd->cmd = 0;
1037 cmd->src = NAND_GENP_REG3;
1038 cmd->dst = paddr(&data->data3);
1039 cmd->len = 4;
1040 cmd++;
1041
1042 /* Read the DEVCMD4 register */
1043 cmd->cmd = 0;
1044 cmd->src = NAND_DEV_CMD4;
1045 cmd->dst = paddr(&data->data4);
1046 cmd->len = 4;
1047 cmd++;
1048
1049 /***************************************************************/
1050 /* Restore the necessary registers to proper values */
1051 /***************************************************************/
1052
1053 /* Block on cmd ready and write CMD register */
1054 cmd->cmd = DST_CRCI_NAND_CMD;
1055 cmd->src = paddr(&data->sfcmd[3]);
1056 cmd->dst = NAND_SFLASHC_CMD;
1057 cmd->len = 4;
1058 cmd++;
1059
1060 /* Kick the execute command */
1061 cmd->cmd = 0;
1062 cmd->src = paddr(&data->sfexec);
1063 cmd->dst = NAND_SFLASHC_EXEC_CMD;
1064 cmd->len = 4;
1065 cmd++;
1066
1067 /* Block on data ready, and read the status register */
1068 cmd->cmd = SRC_CRCI_NAND_DATA | CMD_OCU | CMD_LC;
1069 cmd->src = NAND_SFLASHC_STATUS;
1070 cmd->dst = paddr(&data->sfstat[3]);
1071 cmd->len = 4;
1072 cmd++;
1073
1074 ptr[0] = (paddr(cmdlist) >> 3) | CMD_PTR_LP;
1075
1076 dmov_exec_cmdptr(DMOV_NAND_CHAN, ptr);
1077
1078 ecc_status = (data->data3 >> 16) & 0x0000FFFF;
1079 interrupt_status = (data->data4 >> 0) & 0x0000FFFF;
1080 controller_status = (data->data4 >> 16) & 0x0000FFFF;
1081
1082#if VERBOSE
1083 dprintf(INFO, "\n%s: sflash status %x %x %x %x\n", __func__,
1084 data->sfstat[0],
1085 data->sfstat[1],
1086 data->sfstat[2],
1087 data->sfstat[3]);
1088
1089 dprintf(INFO, "%s: controller_status = %x\n", __func__,
1090 controller_status);
1091 dprintf(INFO, "%s: interrupt_status = %x\n", __func__,
1092 interrupt_status);
1093 dprintf(INFO, "%s: ecc_status = %x\n", __func__,
1094 ecc_status);
1095#endif
1096 /* Check for errors, protection violations etc */
1097 if ((controller_status != 0)
1098 || (data->sfstat[0] & 0x110)
1099 || (data->sfstat[1] & 0x110)
1100 || (data->sfstat[2] & 0x110)
1101 || (data->sfstat[3] & 0x110)) {
1102 dprintf(CRITICAL, "%s: ECC/MPU/OP error\n", __func__);
1103 return -1;
1104 }
1105
1106
1107#if VERBOSE
1108 dprintf(INFO, "status: %x\n", data[5]);
1109#endif
1110
1111 return 0;
1112}
1113
1114
1115struct data_onenand_read {
1116 unsigned sfbcfg;
1117 unsigned sfcmd[9];
1118 unsigned sfexec;
1119 unsigned sfstat[9];
1120 unsigned addr0;
1121 unsigned addr1;
1122 unsigned addr2;
1123 unsigned addr3;
1124 unsigned addr4;
1125 unsigned addr5;
1126 unsigned addr6;
1127 unsigned data0;
1128 unsigned data1;
1129 unsigned data2;
1130 unsigned data3;
1131 unsigned data4;
1132 unsigned data5;
1133 unsigned data6;
1134 unsigned macro[5];
1135};
1136
1137
1138static int _flash_onenand_read_page(dmov_s *cmdlist, unsigned *ptrlist,
Shashank Mittalad3d05c2009-11-19 15:53:57 -08001139 unsigned page, void *_addr, void *_spareaddr,
1140 unsigned raw_mode)
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001141{
1142 dmov_s *cmd = cmdlist;
1143 unsigned *ptr = ptrlist;
1144 struct data_onenand_read *data = (void*) (ptrlist + 4);
1145 unsigned addr = (unsigned) _addr;
1146 unsigned curr_addr = (unsigned) _addr;
1147 unsigned spareaddr = (unsigned) _spareaddr;
1148 unsigned i;
Shashank Mittaldcc2e352009-11-19 19:11:16 -08001149 unsigned erasesize = (flash_pagesize<<6);
1150 unsigned writesize = flash_pagesize;
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001151
1152 unsigned onenand_startaddr1 = DEVICE_FLASHCORE_0 |
Shashank Mittaldcc2e352009-11-19 19:11:16 -08001153 ((unsigned)(page * flash_pagesize) / erasesize);
1154 unsigned onenand_startaddr8 = (((unsigned)(page * flash_pagesize) &
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001155 (erasesize - 1)) / writesize) << 2;
1156 unsigned onenand_startaddr2 = DEVICE_BUFFERRAM_0 << 15;
1157 unsigned onenand_startbuffer = DATARAM0_0 << 8;
Shashank Mittalad3d05c2009-11-19 15:53:57 -08001158 unsigned onenand_sysconfig1 = (raw_mode == 1) ? ONENAND_SYSCFG1_ECCDIS :\
1159 ONENAND_SYSCFG1_ECCENA;
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001160
1161 unsigned controller_status;
1162 unsigned interrupt_status;
1163 unsigned ecc_status;
Shashank Mittalad3d05c2009-11-19 15:53:57 -08001164 if (raw_mode != 1)
1165 {
1166 int isbad = 0;
1167 isbad = flash_onenand_block_isbad(cmdlist, ptrlist, page);
1168 if (isbad)
1169 return -2;
1170 }
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001171
1172 //static int oobfree_offset[8] = {2, 14, 18, 30, 34, 46, 50, 62};
1173 //static int oobfree_length[8] = {3, 2, 3, 2, 3, 2, 3, 2};
1174
1175 data->sfbcfg = SFLASH_BCFG;
1176 data->sfcmd[0] = SFLASH_PREPCMD(7, 0, 0,
1177 NAND_SFCMD_CMDXS,
1178 NAND_SFCMD_ASYNC,
1179 NAND_SFCMD_REGWR);
1180 data->sfcmd[1] = SFLASH_PREPCMD(0, 0, 32,
1181 NAND_SFCMD_CMDXS,
1182 NAND_SFCMD_ASYNC,
1183 NAND_SFCMD_INTHI);
1184 data->sfcmd[2] = SFLASH_PREPCMD(3, 7, 0,
1185 NAND_SFCMD_DATXS,
1186 NAND_SFCMD_ASYNC,
1187 NAND_SFCMD_REGRD);
1188 data->sfcmd[3] = SFLASH_PREPCMD(256, 0, 0,
1189 NAND_SFCMD_DATXS,
1190 NAND_SFCMD_ASYNC,
1191 NAND_SFCMD_DATRD);
1192 data->sfcmd[4] = SFLASH_PREPCMD(256, 0, 0,
1193 NAND_SFCMD_DATXS,
1194 NAND_SFCMD_ASYNC,
1195 NAND_SFCMD_DATRD);
1196 data->sfcmd[5] = SFLASH_PREPCMD(256, 0, 0,
1197 NAND_SFCMD_DATXS,
1198 NAND_SFCMD_ASYNC,
1199 NAND_SFCMD_DATRD);
1200 data->sfcmd[6] = SFLASH_PREPCMD(256, 0, 0,
1201 NAND_SFCMD_DATXS,
1202 NAND_SFCMD_ASYNC,
1203 NAND_SFCMD_DATRD);
1204 data->sfcmd[7] = SFLASH_PREPCMD(32, 0, 0,
1205 NAND_SFCMD_DATXS,
1206 NAND_SFCMD_ASYNC,
1207 NAND_SFCMD_DATRD);
1208 data->sfcmd[8] = SFLASH_PREPCMD(4, 10, 0,
1209 NAND_SFCMD_CMDXS,
1210 NAND_SFCMD_ASYNC,
1211 NAND_SFCMD_REGWR);
1212 data->sfexec = 1;
1213 data->sfstat[0] = CLEAN_DATA_32;
1214 data->sfstat[1] = CLEAN_DATA_32;
1215 data->sfstat[2] = CLEAN_DATA_32;
1216 data->sfstat[3] = CLEAN_DATA_32;
1217 data->sfstat[4] = CLEAN_DATA_32;
1218 data->sfstat[5] = CLEAN_DATA_32;
1219 data->sfstat[6] = CLEAN_DATA_32;
1220 data->sfstat[7] = CLEAN_DATA_32;
1221 data->sfstat[8] = CLEAN_DATA_32;
1222
1223 data->addr0 = (ONENAND_INTERRUPT_STATUS << 16) |
1224 (ONENAND_SYSTEM_CONFIG_1);
1225 data->addr1 = (ONENAND_START_ADDRESS_8 << 16) |
1226 (ONENAND_START_ADDRESS_1);
1227 data->addr2 = (ONENAND_START_BUFFER << 16) |
1228 (ONENAND_START_ADDRESS_2);
1229 data->addr3 = (ONENAND_ECC_STATUS << 16) |
1230 (ONENAND_COMMAND);
1231 data->addr4 = (ONENAND_CONTROLLER_STATUS << 16) |
1232 (ONENAND_INTERRUPT_STATUS);
1233 data->addr5 = (ONENAND_INTERRUPT_STATUS << 16) |
1234 (ONENAND_SYSTEM_CONFIG_1);
1235 data->addr6 = (ONENAND_START_ADDRESS_3 << 16) |
1236 (ONENAND_START_ADDRESS_1);
1237 data->data0 = (ONENAND_CLRINTR << 16) |
1238 (onenand_sysconfig1);
1239 data->data1 = (onenand_startaddr8 << 16) |
1240 (onenand_startaddr1);
1241 data->data2 = (onenand_startbuffer << 16) |
1242 (onenand_startaddr2);
1243 data->data3 = (CLEAN_DATA_16 << 16) |
1244 (ONENAND_CMDLOADSPARE);
1245 data->data4 = (CLEAN_DATA_16 << 16) |
1246 (CLEAN_DATA_16);
1247 data->data5 = (ONENAND_CLRINTR << 16) |
1248 (ONENAND_SYSCFG1_ECCENA);
1249 data->data6 = (ONENAND_STARTADDR3_RES << 16) |
1250 (ONENAND_STARTADDR1_RES);
1251 data->macro[0] = 0x0200;
1252 data->macro[1] = 0x0300;
1253 data->macro[2] = 0x0400;
1254 data->macro[3] = 0x0500;
1255 data->macro[4] = 0x8010;
1256
1257 /*************************************************************/
1258 /* Write necessary address registers in the onenand device */
1259 /*************************************************************/
1260
1261 /* Enable and configure the SFlash controller */
1262 cmd->cmd = 0 | CMD_OCB;
1263 cmd->src = paddr(&data->sfbcfg);
1264 cmd->dst = NAND_SFLASHC_BURST_CFG;
1265 cmd->len = 4;
1266 cmd++;
1267
1268 /* Block on cmd ready and write CMD register */
1269 cmd->cmd = DST_CRCI_NAND_CMD;
1270 cmd->src = paddr(&data->sfcmd[0]);
1271 cmd->dst = NAND_SFLASHC_CMD;
1272 cmd->len = 4;
1273 cmd++;
1274
1275 /* Write the ADDR0 and ADDR1 registers */
1276 cmd->cmd = 0;
1277 cmd->src = paddr(&data->addr0);
1278 cmd->dst = NAND_ADDR0;
1279 cmd->len = 8;
1280 cmd++;
1281
1282 /* Write the ADDR2 ADDR3 ADDR4 ADDR5 registers */
1283 cmd->cmd = 0;
1284 cmd->src = paddr(&data->addr2);
1285 cmd->dst = NAND_ADDR2;
1286 cmd->len = 16;
1287 cmd++;
1288
1289 /* Write the ADDR6 registers */
1290 cmd->cmd = 0;
1291 cmd->src = paddr(&data->addr6);
1292 cmd->dst = NAND_ADDR6;
1293 cmd->len = 4;
1294 cmd++;
1295
1296 /* Write the GENP0, GENP1, GENP2, GENP3 registers */
1297 cmd->cmd = 0;
1298 cmd->src = paddr(&data->data0);
1299 cmd->dst = NAND_GENP_REG0;
1300 cmd->len = 16;
1301 cmd++;
1302
1303 /* Write the FLASH_DEV_CMD4,5,6 registers */
1304 cmd->cmd = 0;
1305 cmd->src = paddr(&data->data4);
1306 cmd->dst = NAND_DEV_CMD4;
1307 cmd->len = 12;
1308 cmd++;
1309
1310 /* Kick the execute command */
1311 cmd->cmd = 0;
1312 cmd->src = paddr(&data->sfexec);
1313 cmd->dst = NAND_SFLASHC_EXEC_CMD;
1314 cmd->len = 4;
1315 cmd++;
1316
1317 /* Block on data ready, and read the status register */
1318 cmd->cmd = SRC_CRCI_NAND_DATA;
1319 cmd->src = NAND_SFLASHC_STATUS;
1320 cmd->dst = paddr(&data->sfstat[0]);
1321 cmd->len = 4;
1322 cmd++;
1323
1324 /*************************************************************/
1325 /* Wait for the interrupt from the Onenand device controller */
1326 /*************************************************************/
1327
1328 /* Block on cmd ready and write CMD register */
1329 cmd->cmd = DST_CRCI_NAND_CMD;
1330 cmd->src = paddr(&data->sfcmd[1]);
1331 cmd->dst = NAND_SFLASHC_CMD;
1332 cmd->len = 4;
1333 cmd++;
1334
1335 /* Kick the execute command */
1336 cmd->cmd = 0;
1337 cmd->src = paddr(&data->sfexec);
1338 cmd->dst = NAND_SFLASHC_EXEC_CMD;
1339 cmd->len = 4;
1340 cmd++;
1341
1342 /* Block on data ready, and read the status register */
1343 cmd->cmd = SRC_CRCI_NAND_DATA;
1344 cmd->src = NAND_SFLASHC_STATUS;
1345 cmd->dst = paddr(&data->sfstat[1]);
1346 cmd->len = 4;
1347 cmd++;
1348
1349
1350 /*************************************************************/
1351 /* Read necessary status registers from the onenand device */
1352 /*************************************************************/
1353
1354 /* Block on cmd ready and write CMD register */
1355 cmd->cmd = DST_CRCI_NAND_CMD;
1356 cmd->src = paddr(&data->sfcmd[2]);
1357 cmd->dst = NAND_SFLASHC_CMD;
1358 cmd->len = 4;
1359 cmd++;
1360
1361 /* Kick the execute command */
1362 cmd->cmd = 0;
1363 cmd->src = paddr(&data->sfexec);
1364 cmd->dst = NAND_SFLASHC_EXEC_CMD;
1365 cmd->len = 4;
1366 cmd++;
1367
1368 /* Block on data ready, and read the status register */
1369 cmd->cmd = SRC_CRCI_NAND_DATA;
1370 cmd->src = NAND_SFLASHC_STATUS;
1371 cmd->dst = paddr(&data->sfstat[2]);
1372 cmd->len = 4;
1373 cmd++;
1374
1375 /* Read the GENP3 register */
1376 cmd->cmd = 0;
1377 cmd->src = NAND_GENP_REG3;
1378 cmd->dst = paddr(&data->data3);
1379 cmd->len = 4;
1380 cmd++;
1381
1382 /* Read the DEVCMD4 register */
1383 cmd->cmd = 0;
1384 cmd->src = NAND_DEV_CMD4;
1385 cmd->dst = paddr(&data->data4);
1386 cmd->len = 4;
1387 cmd++;
1388
1389
1390 /*************************************************************/
1391 /* Read the data ram area from the onenand buffer ram */
1392 /*************************************************************/
1393
1394 if (addr) {
1395
1396 data->data3 = (CLEAN_DATA_16 << 16) |
1397 (ONENAND_CMDLOAD);
1398
1399 for (i = 0; i < 4; i++) {
1400
1401 /* Block on cmd ready and write CMD register */
1402 cmd->cmd = DST_CRCI_NAND_CMD;
1403 cmd->src = paddr(&data->sfcmd[3+i]);
1404 cmd->dst = NAND_SFLASHC_CMD;
1405 cmd->len = 4;
1406 cmd++;
1407
1408 /* Write the MACRO1 register */
1409 cmd->cmd = 0;
1410 cmd->src = paddr(&data->macro[i]);
1411 cmd->dst = NAND_MACRO1_REG;
1412 cmd->len = 4;
1413 cmd++;
1414
1415 /* Kick the execute command */
1416 cmd->cmd = 0;
1417 cmd->src = paddr(&data->sfexec);
1418 cmd->dst = NAND_SFLASHC_EXEC_CMD;
1419 cmd->len = 4;
1420 cmd++;
1421
1422 /* Block on data rdy, & read status register */
1423 cmd->cmd = SRC_CRCI_NAND_DATA;
1424 cmd->src = NAND_SFLASHC_STATUS;
1425 cmd->dst = paddr(&data->sfstat[3+i]);
1426 cmd->len = 4;
1427 cmd++;
1428
1429 /* Transfer nand ctlr buf contents to usr buf */
1430 cmd->cmd = 0;
1431 cmd->src = NAND_FLASH_BUFFER;
1432 cmd->dst = curr_addr;
1433 cmd->len = 512;
1434 curr_addr += 512;
1435 cmd++;
1436 }
1437 }
1438
Shashank Mittalad3d05c2009-11-19 15:53:57 -08001439 /* Read oob bytes in Raw Mode */
1440 if (raw_mode == 1)
1441 {
1442 /* Block on cmd ready and write CMD register */
1443 cmd->cmd = DST_CRCI_NAND_CMD;
1444 cmd->src = paddr(&data->sfcmd[7]);
1445 cmd->dst = NAND_SFLASHC_CMD;
1446 cmd->len = 4;
1447 cmd++;
1448
1449 /* Write the MACRO1 register */
1450 cmd->cmd = 0;
1451 cmd->src = paddr(&data->macro[4]);
1452 cmd->dst = NAND_MACRO1_REG;
1453 cmd->len = 4;
1454 cmd++;
1455
1456 /* Kick the execute command */
1457 cmd->cmd = 0;
1458 cmd->src = paddr(&data->sfexec);
1459 cmd->dst = NAND_SFLASHC_EXEC_CMD;
1460 cmd->len = 4;
1461 cmd++;
1462
1463 /* Block on data rdy, & read status register */
1464 cmd->cmd = SRC_CRCI_NAND_DATA;
1465 cmd->src = NAND_SFLASHC_STATUS;
1466 cmd->dst = paddr(&data->sfstat[7]);
1467 cmd->len = 4;
1468 cmd++;
1469
1470 /* Transfer nand ctlr buf contents to usr buf */
1471 cmd->cmd = 0;
1472 cmd->src = NAND_FLASH_BUFFER;
1473 cmd->dst = curr_addr;
1474 cmd->len = 64;
1475 curr_addr += 64;
1476 cmd++;
1477 }
1478
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001479 /*************************************************************/
1480 /* Restore the necessary registers to proper values */
1481 /*************************************************************/
1482
1483 /* Block on cmd ready and write CMD register */
1484 cmd->cmd = DST_CRCI_NAND_CMD;
1485 cmd->src = paddr(&data->sfcmd[8]);
1486 cmd->dst = NAND_SFLASHC_CMD;
1487 cmd->len = 4;
1488 cmd++;
1489
1490 /* Kick the execute command */
1491 cmd->cmd = 0;
1492 cmd->src = paddr(&data->sfexec);
1493 cmd->dst = NAND_SFLASHC_EXEC_CMD;
1494 cmd->len = 4;
1495 cmd++;
1496
1497 /* Block on data ready, and read the status register */
1498 cmd->cmd = SRC_CRCI_NAND_DATA | CMD_OCU | CMD_LC;
1499 cmd->src = NAND_SFLASHC_STATUS;
1500 cmd->dst = paddr(&data->sfstat[8]);
1501 cmd->len = 4;
1502 cmd++;
1503
1504
1505 ptr[0] = (paddr(cmdlist) >> 3) | CMD_PTR_LP;
1506
1507 dmov_exec_cmdptr(DMOV_NAND_CHAN, ptr);
1508
1509
1510 ecc_status = (data->data3 >> 16) &
1511 0x0000FFFF;
1512 interrupt_status = (data->data4 >> 0) &
1513 0x0000FFFF;
1514 controller_status = (data->data4 >> 16) &
1515 0x0000FFFF;
1516
1517#if VERBOSE
1518 dprintf(INFO, "\n%s: sflash status %x %x %x %x %x %x %x"
1519 "%x %x\n", __func__,
1520 data->sfstat[0],
1521 data->sfstat[1],
1522 data->sfstat[2],
1523 data->sfstat[3],
1524 data->sfstat[4],
1525 data->sfstat[5],
1526 data->sfstat[6],
1527 data->sfstat[7]);
1528
1529 dprintf(INFO, "%s: controller_status = %x\n", __func__,
1530 controller_status);
1531 dprintf(INFO, "%s: interrupt_status = %x\n", __func__,
1532 interrupt_status);
1533 dprintf(INFO, "%s: ecc_status = %x\n", __func__,
1534 ecc_status);
1535#endif
1536 /* Check for errors, protection violations etc */
1537 if ((controller_status != 0)
1538 || (data->sfstat[0] & 0x110)
1539 || (data->sfstat[1] & 0x110)
1540 || (data->sfstat[2] & 0x110)
1541 || ((data->sfstat[3] & 0x110) &&
1542 (addr))
1543 || ((data->sfstat[4] & 0x110) &&
1544 (addr))
1545 || ((data->sfstat[5] & 0x110) &&
1546 (addr))
1547 || ((data->sfstat[6] & 0x110) &&
1548 (addr))) {
1549 dprintf(INFO, "%s: ECC/MPU/OP error\n", __func__);
1550 return -1;
1551 }
1552
1553#if VERBOSE
1554 dprintf(INFO, "read page %d: status: %x %x %x %x\n",
1555 page, data[5], data[6], data[7], data[8]);
1556 for(n = 0; n < 4; n++) {
1557 ptr = (unsigned*)(addr + 512 * n);
1558 dprintf(INFO, "data%d: %x %x %x %x\n", n, ptr[0], ptr[1], ptr[2], ptr[3]);
1559 ptr = (unsigned*)(spareaddr + 16 * n);
1560 dprintf(INFO, "spare data%d %x %x %x %x\n", n, ptr[0], ptr[1], ptr[2], ptr[3]);
1561 }
1562#endif
1563
1564 return 0;
1565}
1566
1567
1568struct data_onenand_write {
1569 unsigned sfbcfg;
1570 unsigned sfcmd[9];
1571 unsigned sfexec;
1572 unsigned sfstat[9];
1573 unsigned addr0;
1574 unsigned addr1;
1575 unsigned addr2;
1576 unsigned addr3;
1577 unsigned addr4;
1578 unsigned addr5;
1579 unsigned addr6;
1580 unsigned data0;
1581 unsigned data1;
1582 unsigned data2;
1583 unsigned data3;
1584 unsigned data4;
1585 unsigned data5;
1586 unsigned data6;
1587 unsigned macro[5];
1588};
1589
1590static int _flash_onenand_write_page(dmov_s *cmdlist, unsigned *ptrlist,
1591 unsigned page, const void *_addr,
Shashank Mittald0c836d2009-11-20 10:31:18 -08001592 const void *_spareaddr, unsigned raw_mode)
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001593{
1594 dmov_s *cmd = cmdlist;
1595 unsigned *ptr = ptrlist;
1596 struct data_onenand_write *data = (void*) (ptrlist + 4);
1597 unsigned addr = (unsigned) _addr;
1598 unsigned addr_curr = (unsigned) _addr;
1599 char * spareaddr = (char *) _spareaddr;
1600 unsigned i, j, k;
1601
Shashank Mittaldcc2e352009-11-19 19:11:16 -08001602 unsigned erasesize = (flash_pagesize<<6);
1603 unsigned writesize = flash_pagesize;
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001604
Shashank Mittaldcc2e352009-11-19 19:11:16 -08001605 unsigned onenand_startaddr1 = (page * flash_pagesize) / erasesize;
1606 unsigned onenand_startaddr8 = (((unsigned)(page * flash_pagesize) &
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001607 (erasesize-1)) / writesize) << 2;
1608 unsigned onenand_startaddr2 = DEVICE_BUFFERRAM_0 << 15;
1609 unsigned onenand_startbuffer = DATARAM0_0 << 8;
Shashank Mittald0c836d2009-11-20 10:31:18 -08001610 unsigned onenand_sysconfig1 = (raw_mode == 1) ? ONENAND_SYSCFG1_ECCDIS :\
1611 ONENAND_SYSCFG1_ECCENA;
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001612
1613 unsigned controller_status;
1614 unsigned interrupt_status;
1615 unsigned ecc_status;
1616
1617 char flash_oob[64];
1618
1619 unsigned oobfree_offset[8] = {2, 14, 18, 30, 34, 46, 50, 62};
1620 unsigned oobfree_length[8] = {3, 2, 3, 2, 3, 2, 3, 2};
1621
1622 for (i = 0; i < 64; i++)
1623 flash_oob[i] = 0xFF;
1624
1625 data->sfbcfg = SFLASH_BCFG;
1626 data->sfcmd[0] = SFLASH_PREPCMD(256, 0, 0,
1627 NAND_SFCMD_CMDXS,
1628 NAND_SFCMD_ASYNC,
1629 NAND_SFCMD_DATWR);
1630 data->sfcmd[1] = SFLASH_PREPCMD(256, 0, 0,
1631 NAND_SFCMD_CMDXS,
1632 NAND_SFCMD_ASYNC,
1633 NAND_SFCMD_DATWR);
1634 data->sfcmd[2] = SFLASH_PREPCMD(256, 0, 0,
1635 NAND_SFCMD_CMDXS,
1636 NAND_SFCMD_ASYNC,
1637 NAND_SFCMD_DATWR);
1638 data->sfcmd[3] = SFLASH_PREPCMD(256, 0, 0,
1639 NAND_SFCMD_CMDXS,
1640 NAND_SFCMD_ASYNC,
1641 NAND_SFCMD_DATWR);
1642 data->sfcmd[4] = SFLASH_PREPCMD(32, 0, 0,
1643 NAND_SFCMD_CMDXS,
1644 NAND_SFCMD_ASYNC,
1645 NAND_SFCMD_DATWR);
1646 data->sfcmd[5] = SFLASH_PREPCMD(7, 0, 0,
1647 NAND_SFCMD_CMDXS,
1648 NAND_SFCMD_ASYNC,
1649 NAND_SFCMD_REGWR);
1650 data->sfcmd[6] = SFLASH_PREPCMD(0, 0, 32,
1651 NAND_SFCMD_CMDXS,
1652 NAND_SFCMD_ASYNC,
1653 NAND_SFCMD_INTHI);
1654 data->sfcmd[7] = SFLASH_PREPCMD(3, 7, 0,
1655 NAND_SFCMD_DATXS,
1656 NAND_SFCMD_ASYNC,
1657 NAND_SFCMD_REGRD);
1658 data->sfcmd[8] = SFLASH_PREPCMD(4, 10, 0,
1659 NAND_SFCMD_CMDXS,
1660 NAND_SFCMD_ASYNC,
1661 NAND_SFCMD_REGWR);
1662 data->sfexec = 1;
1663
1664 data->sfstat[0] = CLEAN_DATA_32;
1665 data->sfstat[1] = CLEAN_DATA_32;
1666 data->sfstat[2] = CLEAN_DATA_32;
1667 data->sfstat[3] = CLEAN_DATA_32;
1668 data->sfstat[4] = CLEAN_DATA_32;
1669 data->sfstat[5] = CLEAN_DATA_32;
1670 data->sfstat[6] = CLEAN_DATA_32;
1671 data->sfstat[7] = CLEAN_DATA_32;
1672 data->sfstat[8] = CLEAN_DATA_32;
1673 data->addr0 = (ONENAND_INTERRUPT_STATUS << 16) |
1674 (ONENAND_SYSTEM_CONFIG_1);
1675 data->addr1 = (ONENAND_START_ADDRESS_8 << 16) |
1676 (ONENAND_START_ADDRESS_1);
1677 data->addr2 = (ONENAND_START_BUFFER << 16) |
1678 (ONENAND_START_ADDRESS_2);
1679 data->addr3 = (ONENAND_ECC_STATUS << 16) |
1680 (ONENAND_COMMAND);
1681 data->addr4 = (ONENAND_CONTROLLER_STATUS << 16) |
1682 (ONENAND_INTERRUPT_STATUS);
1683 data->addr5 = (ONENAND_INTERRUPT_STATUS << 16) |
1684 (ONENAND_SYSTEM_CONFIG_1);
1685 data->addr6 = (ONENAND_START_ADDRESS_3 << 16) |
1686 (ONENAND_START_ADDRESS_1);
1687 data->data0 = (ONENAND_CLRINTR << 16) |
1688 (onenand_sysconfig1);
1689 data->data1 = (onenand_startaddr8 << 16) |
1690 (onenand_startaddr1);
1691 data->data2 = (onenand_startbuffer << 16) |
1692 (onenand_startaddr2);
1693 data->data3 = (CLEAN_DATA_16 << 16) |
1694 (ONENAND_CMDPROGSPARE);
1695 data->data3 = (CLEAN_DATA_16 << 16) |
1696 (ONENAND_CMDPROGSPARE);
1697 data->data4 = (CLEAN_DATA_16 << 16) |
1698 (CLEAN_DATA_16);
1699 data->data5 = (ONENAND_CLRINTR << 16) |
1700 (ONENAND_SYSCFG1_ECCENA);
1701 data->data6 = (ONENAND_STARTADDR3_RES << 16) |
1702 (ONENAND_STARTADDR1_RES);
1703 data->macro[0] = 0x0200;
1704 data->macro[1] = 0x0300;
1705 data->macro[2] = 0x0400;
1706 data->macro[3] = 0x0500;
1707 data->macro[4] = 0x8010;
1708
1709
1710 /*************************************************************/
1711 /* Write the data ram area in the onenand buffer ram */
1712 /*************************************************************/
1713
1714 /* Enable and configure the SFlash controller */
1715 cmd->cmd = 0 | CMD_OCB;
1716 cmd->src = paddr(&data->sfbcfg);
1717 cmd->dst = NAND_SFLASHC_BURST_CFG;
1718 cmd->len = 4;
1719 cmd++;
1720
1721 if (addr) {
1722 data->data3 = (CLEAN_DATA_16 << 16) |
1723 (ONENAND_CMDPROG);
1724
1725 for (i = 0; i < 4; i++) {
1726
1727 /* Block on cmd ready and write CMD register */
1728 cmd->cmd = DST_CRCI_NAND_CMD;
1729 cmd->src = paddr(&data->sfcmd[i]);
1730 cmd->dst = NAND_SFLASHC_CMD;
1731 cmd->len = 4;
1732 cmd++;
1733
1734 /* Trnsfr usr buf contents to nand ctlr buf */
1735 cmd->cmd = 0;
1736 cmd->src = paddr(addr_curr);
1737 cmd->dst = NAND_FLASH_BUFFER;
1738 cmd->len = 512;
Shashank Mittald0c836d2009-11-20 10:31:18 -08001739 if(!raw_mode)
1740 addr_curr += 512;
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001741 cmd++;
1742
1743 /* Write the MACRO1 register */
1744 cmd->cmd = 0;
1745 cmd->src = paddr(&data->macro[i]);
1746 cmd->dst = NAND_MACRO1_REG;
1747 cmd->len = 4;
1748 cmd++;
1749
1750 /* Kick the execute command */
1751 cmd->cmd = 0;
1752 cmd->src = paddr(&data->sfexec);
1753 cmd->dst = NAND_SFLASHC_EXEC_CMD;
1754 cmd->len = 4;
1755 cmd++;
1756
1757 /* Block on data rdy, & read status register */
1758 cmd->cmd = SRC_CRCI_NAND_DATA;
1759 cmd->src = NAND_SFLASHC_STATUS;
1760 cmd->dst = paddr(&data->sfstat[i]);
1761 cmd->len = 4;
1762 cmd++;
1763
1764 }
1765 }
1766
1767 /* Block on cmd ready and write CMD register */
1768 cmd->cmd = DST_CRCI_NAND_CMD;
1769 cmd->src = paddr(&data->sfcmd[4]);
1770 cmd->dst = NAND_SFLASHC_CMD;
1771 cmd->len = 4;
1772 cmd++;
1773
1774 if (spareaddr)
1775 {
1776 // Auto mode
1777 for (i = 0, k = 0; i < 8; i++) {
1778 for (j = 0; j < oobfree_length[i]; j++) {
1779 flash_oob[j+oobfree_offset[i]] = spareaddr[k];
1780 k++;
1781 }
1782 }
1783
1784 cmd->cmd = 0;
1785 cmd->src = paddr(&flash_oob);
1786 cmd->dst = NAND_FLASH_BUFFER;
1787 cmd->len = 64;
1788 cmd++;
1789 }
1790
Shashank Mittald0c836d2009-11-20 10:31:18 -08001791 if (raw_mode){
1792 cmd->cmd = 0;
1793 cmd->src = paddr(addr_curr);
1794 cmd->dst = NAND_FLASH_BUFFER;
1795 cmd->len = 64;
1796 cmd++;
1797 }
1798
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001799 /* Write the MACRO1 register */
1800 cmd->cmd = 0;
1801 cmd->src = paddr(&data->macro[4]);
1802 cmd->dst = NAND_MACRO1_REG;
1803 cmd->len = 4;
1804 cmd++;
1805
1806 /* Kick the execute command */
1807 cmd->cmd = 0;
1808 cmd->src = paddr(&data->sfexec);
1809 cmd->dst = NAND_SFLASHC_EXEC_CMD;
1810 cmd->len = 4;
1811 cmd++;
1812
1813 /* Block on data ready, and read the status register */
1814 cmd->cmd = SRC_CRCI_NAND_DATA;
1815 cmd->src = NAND_SFLASHC_STATUS;
1816 cmd->dst = paddr(&data->sfstat[4]);
1817 cmd->len = 4;
1818 cmd++;
1819
1820 /*************************************************************/
1821 /* Write necessary address registers in the onenand device */
1822 /*************************************************************/
1823
1824 /* Block on cmd ready and write CMD register */
1825 cmd->cmd = DST_CRCI_NAND_CMD;
1826 cmd->src = paddr(&data->sfcmd[5]);
1827 cmd->dst = NAND_SFLASHC_CMD;
1828 cmd->len = 4;
1829 cmd++;
1830
1831 /* Write the ADDR0 and ADDR1 registers */
1832 cmd->cmd = 0;
1833 cmd->src = paddr(&data->addr0);
1834 cmd->dst = NAND_ADDR0;
1835 cmd->len = 8;
1836 cmd++;
1837
1838 /* Write the ADDR2 ADDR3 ADDR4 ADDR5 registers */
1839 cmd->cmd = 0;
1840 cmd->src = paddr(&data->addr2);
1841 cmd->dst = NAND_ADDR2;
1842 cmd->len = 16;
1843 cmd++;
1844
1845 /* Write the ADDR6 registers */
1846 cmd->cmd = 0;
1847 cmd->src = paddr(&data->addr6);
1848 cmd->dst = NAND_ADDR6;
1849 cmd->len = 4;
1850 cmd++;
1851
1852 /* Write the GENP0, GENP1, GENP2, GENP3 registers */
1853 cmd->cmd = 0;
1854 cmd->src = paddr(&data->data0);
1855 cmd->dst = NAND_GENP_REG0;
1856 cmd->len = 16;
1857 cmd++;
1858
1859 /* Write the FLASH_DEV_CMD4,5,6 registers */
1860 cmd->cmd = 0;
1861 cmd->src = paddr(&data->data4);
1862 cmd->dst = NAND_DEV_CMD4;
1863 cmd->len = 12;
1864 cmd++;
1865
1866 /* Kick the execute command */
1867 cmd->cmd = 0;
1868 cmd->src = paddr(&data->sfexec);
1869 cmd->dst = NAND_SFLASHC_EXEC_CMD;
1870 cmd->len = 4;
1871 cmd++;
1872
1873 /* Block on data ready, and read the status register */
1874 cmd->cmd = SRC_CRCI_NAND_DATA;
1875 cmd->src = NAND_SFLASHC_STATUS;
1876 cmd->dst = paddr(&data->sfstat[5]);
1877 cmd->len = 4;
1878 cmd++;
1879
1880 /*************************************************************/
1881 /* Wait for the interrupt from the Onenand device controller */
1882 /*************************************************************/
1883
1884 /* Block on cmd ready and write CMD register */
1885 cmd->cmd = DST_CRCI_NAND_CMD;
1886 cmd->src = paddr(&data->sfcmd[6]);
1887 cmd->dst = NAND_SFLASHC_CMD;
1888 cmd->len = 4;
1889 cmd++;
1890
1891 /* Kick the execute command */
1892 cmd->cmd = 0;
1893 cmd->src = paddr(&data->sfexec);
1894 cmd->dst = NAND_SFLASHC_EXEC_CMD;
1895 cmd->len = 4;
1896 cmd++;
1897
1898 /* Block on data ready, and read the status register */
1899 cmd->cmd = SRC_CRCI_NAND_DATA;
1900 cmd->src = NAND_SFLASHC_STATUS;
1901 cmd->dst = paddr(&data->sfstat[6]);
1902 cmd->len = 4;
1903 cmd++;
1904
1905 /*************************************************************/
1906 /* Read necessary status registers from the onenand device */
1907 /*************************************************************/
1908
1909 /* Block on cmd ready and write CMD register */
1910 cmd->cmd = DST_CRCI_NAND_CMD;
1911 cmd->src = paddr(&data->sfcmd[7]);
1912 cmd->dst = NAND_SFLASHC_CMD;
1913 cmd->len = 4;
1914 cmd++;
1915
1916 /* Kick the execute command */
1917 cmd->cmd = 0;
1918 cmd->src = paddr(&data->sfexec);
1919 cmd->dst = NAND_SFLASHC_EXEC_CMD;
1920 cmd->len = 4;
1921 cmd++;
1922
1923 /* Block on data ready, and read the status register */
1924 cmd->cmd = SRC_CRCI_NAND_DATA;
1925 cmd->src = NAND_SFLASHC_STATUS;
1926 cmd->dst = paddr(&data->sfstat[7]);
1927 cmd->len = 4;
1928 cmd++;
1929
1930 /* Read the GENP3 register */
1931 cmd->cmd = 0;
1932 cmd->src = NAND_GENP_REG3;
1933 cmd->dst = paddr(&data->data3);
1934 cmd->len = 4;
1935 cmd++;
1936
1937 /* Read the DEVCMD4 register */
1938 cmd->cmd = 0;
1939 cmd->src = NAND_DEV_CMD4;
1940 cmd->dst = paddr(&data->data4);
1941 cmd->len = 4;
1942 cmd++;
1943
1944
1945 /*************************************************************/
1946 /* Restore the necessary registers to proper values */
1947 /*************************************************************/
1948
1949 /* Block on cmd ready and write CMD register */
1950 cmd->cmd = DST_CRCI_NAND_CMD;
1951 cmd->src = paddr(&data->sfcmd[8]);
1952 cmd->dst = NAND_SFLASHC_CMD;
1953 cmd->len = 4;
1954 cmd++;
1955
1956 /* Kick the execute command */
1957 cmd->cmd = 0;
1958 cmd->src = paddr(&data->sfexec);
1959 cmd->dst = NAND_SFLASHC_EXEC_CMD;
1960 cmd->len = 4;
1961 cmd++;
1962
1963 /* Block on data ready, and read the status register */
1964 cmd->cmd = SRC_CRCI_NAND_DATA | CMD_OCU | CMD_LC;
1965 cmd->src = NAND_SFLASHC_STATUS;
1966 cmd->dst = paddr(&data->sfstat[8]);
1967 cmd->len = 4;
1968 cmd++;
1969
1970
1971 ptr[0] = (paddr(cmdlist) >> 3) | CMD_PTR_LP;
1972
1973 dmov_exec_cmdptr(DMOV_NAND_CHAN, ptr);
1974
1975 ecc_status = (data->data3 >> 16) & 0x0000FFFF;
1976 interrupt_status = (data->data4 >> 0)&0x0000FFFF;
1977 controller_status = (data->data4 >> 16)&0x0000FFFF;
1978
1979#if VERBOSE
1980 dprintf(INFO, "\n%s: sflash status %x %x %x %x %x %x %x %x %x\n", __func__,
1981 data->sfstat[0],
1982 data->sfstat[1],
1983 data->sfstat[2],
1984 data->sfstat[3],
1985 data->sfstat[4],
1986 data->sfstat[5],
1987 data->sfstat[6],
1988 data->sfstat[7],
1989 data->sfstat[8]);
1990
1991 dprintf(INFO, "%s: controller_status = %x\n", __func__,
1992 controller_status);
1993 dprintf(INFO, "%s: interrupt_status = %x\n", __func__,
1994 interrupt_status);
1995 dprintf(INFO, "%s: ecc_status = %x\n", __func__,
1996 ecc_status);
1997#endif
1998 /* Check for errors, protection violations etc */
1999 if ((controller_status != 0)
2000 || (data->sfstat[5] & 0x110)
2001 || (data->sfstat[6] & 0x110)
2002 || (data->sfstat[7] & 0x110)
2003 || (data->sfstat[8] & 0x110)
2004 || ((data->sfstat[0] & 0x110) &&
2005 (addr))
2006 || ((data->sfstat[1] & 0x110) &&
2007 (addr))
2008 || ((data->sfstat[2] & 0x110) &&
2009 (addr))
2010 || ((data->sfstat[3] & 0x110) &&
2011 (addr))) {
2012 dprintf(CRITICAL, "%s: ECC/MPU/OP error\n", __func__);
2013 return -1;
2014 }
2015
2016
2017 return 0;
2018}
Shashank Mittald0c836d2009-11-20 10:31:18 -08002019
2020static int flash_onenand_mark_badblock(dmov_s *cmdlist, unsigned *ptrlist, unsigned page)
2021{
2022 memset(empty_buf,0,528);
2023 /* Going to first page of the block */
2024 if(page & 63)
2025 page = page - (page & 63);
2026 return _flash_onenand_write_page(cmdlist, ptrlist, page, empty_buf, 0, 1);
2027}
2028
2029static int flash_mark_badblock(dmov_s *cmdlist, unsigned *ptrlist, unsigned page)
2030{
2031 switch(flash_info.type) {
2032 case FLASH_8BIT_NAND_DEVICE:
2033 case FLASH_16BIT_NAND_DEVICE:
2034 return flash_nand_mark_badblock(cmdlist, ptrlist, page);
2035 case FLASH_ONENAND_DEVICE:
2036 return flash_onenand_mark_badblock(cmdlist, ptrlist, page);
2037 default:
2038 return -1;
2039 }
2040}
2041
2042
Shashank Mittalc20b5a12009-11-18 19:35:30 -08002043/* Wrapper functions */
2044static void flash_read_id(dmov_s *cmdlist, unsigned *ptrlist)
2045{
2046 int dev_found = 0;
2047 unsigned index;
2048
2049 // Try to read id
2050 flash_nand_read_id(cmdlist, ptrlist);
2051 // Check if we support the device
2052 for (index=1;
2053 index < (sizeof(supported_flash)/sizeof(struct flash_identification));
2054 index++)
2055 {
2056 if ((flash_info.id & supported_flash[index].mask) ==
2057 (supported_flash[index].flash_id &
2058 (supported_flash[index].mask))) {
2059 dev_found = 1;
2060 break;
2061 }
2062 }
2063
2064 if(!dev_found) {
2065 flash_onenand_read_id(cmdlist, ptrlist);
2066 for (index=1;
2067 index < (sizeof(supported_flash)/sizeof(struct flash_identification));
2068 index++)
2069 {
2070 if ((flash_info.id & supported_flash[index].mask) ==
2071 (supported_flash[index].flash_id &
2072 (supported_flash[index].mask))) {
2073 dev_found = 1;
2074 break;
2075 }
2076 }
2077 }
2078
2079
2080
2081 if(dev_found) {
2082 if (supported_flash[index].widebus)
2083 flash_info.type = FLASH_16BIT_NAND_DEVICE;
2084 else
2085 flash_info.type = FLASH_8BIT_NAND_DEVICE;
2086 if (supported_flash[index].onenand)
2087 flash_info.type = FLASH_ONENAND_DEVICE;
2088 flash_info.page_size = supported_flash[index].pagesize;
Shashank Mittaldcc2e352009-11-19 19:11:16 -08002089 flash_pagesize = flash_info.page_size;
Shashank Mittalc20b5a12009-11-18 19:35:30 -08002090 flash_info.block_size = supported_flash[index].blksize;
2091 flash_info.spare_size = supported_flash[index].oobsize;
2092 if (flash_info.block_size && flash_info.page_size)
2093 {
2094 flash_info.num_blocks = supported_flash[index].density;
2095 flash_info.num_blocks /= (flash_info.block_size * flash_info.page_size);
2096 }
2097 else
2098 {
2099 flash_info.num_blocks = 0;
2100 }
2101 ASSERT(flash_info.num_blocks);
2102 return;
2103 }
2104
2105 // Assume 8 bit nand device for backward compatability
2106 if (dev_found == 0) {
2107 dprintf(INFO, "Device not supported. Assuming 8 bit NAND device\n");
2108 flash_info.type = FLASH_8BIT_NAND_DEVICE;
2109 }
2110 dprintf(INFO, "nandid: 0x%x maker=0x%02x device=0x%02x page_size=%d\n",
2111 flash_info.id, flash_info.vendor, flash_info.device,
2112 flash_info.page_size);
2113 dprintf(INFO, " spare_size=%d block_size=%d num_blocks=%d\n",
2114 flash_info.spare_size, flash_info.block_size,
2115 flash_info.num_blocks);
2116}
2117
2118static int flash_erase_block(dmov_s *cmdlist, unsigned *ptrlist, unsigned page)
2119{
2120 switch(flash_info.type) {
2121 case FLASH_8BIT_NAND_DEVICE:
2122 case FLASH_16BIT_NAND_DEVICE:
2123 return flash_nand_erase_block(cmdlist, ptrlist, page);
2124 case FLASH_ONENAND_DEVICE:
2125 return flash_onenand_erase_block(cmdlist, ptrlist, page);
2126 default:
2127 return -1;
2128 }
2129}
2130
2131static int _flash_read_page(dmov_s *cmdlist, unsigned *ptrlist,
2132 unsigned page, void *_addr, void *_spareaddr)
2133{
2134 switch(flash_info.type) {
2135 case FLASH_8BIT_NAND_DEVICE:
2136 case FLASH_16BIT_NAND_DEVICE:
2137 return _flash_nand_read_page(cmdlist, ptrlist, page, _addr, _spareaddr);
2138 case FLASH_ONENAND_DEVICE:
Shashank Mittalad3d05c2009-11-19 15:53:57 -08002139 return _flash_onenand_read_page(cmdlist, ptrlist, page, _addr, _spareaddr, 0);
Shashank Mittalc20b5a12009-11-18 19:35:30 -08002140 default:
2141 return -1;
2142 }
2143}
2144
Shashank Mittalad3d05c2009-11-19 15:53:57 -08002145static int _flash_block_isbad(dmov_s *cmdlist, unsigned *ptrlist, unsigned page)
2146{
2147 switch(flash_info.type) {
2148 case FLASH_8BIT_NAND_DEVICE:
2149 case FLASH_16BIT_NAND_DEVICE:
2150 return flash_nand_block_isbad(cmdlist, ptrlist, page);
2151 case FLASH_ONENAND_DEVICE:
2152 return flash_onenand_block_isbad(cmdlist, ptrlist, page);
2153 default:
2154 return -1;
2155 }
2156}
Shashank Mittalc20b5a12009-11-18 19:35:30 -08002157
2158static int _flash_write_page(dmov_s *cmdlist, unsigned *ptrlist,
2159 unsigned page, const void *_addr,
2160 const void *_spareaddr)
2161{
2162 switch(flash_info.type) {
2163 case FLASH_8BIT_NAND_DEVICE:
2164 case FLASH_16BIT_NAND_DEVICE:
Shashank Mittald0c836d2009-11-20 10:31:18 -08002165 return _flash_nand_write_page(cmdlist, ptrlist, page, _addr, _spareaddr, 0);
Shashank Mittalc20b5a12009-11-18 19:35:30 -08002166 case FLASH_ONENAND_DEVICE:
Shashank Mittald0c836d2009-11-20 10:31:18 -08002167 return _flash_onenand_write_page(cmdlist, ptrlist, page, _addr, _spareaddr, 0);
Shashank Mittalc20b5a12009-11-18 19:35:30 -08002168 default:
2169 return -1;
2170 }
2171}
2172
Dima Zavin03cf4312009-01-23 16:38:30 -08002173static unsigned *flash_ptrlist;
2174static dmov_s *flash_cmdlist;
Dima Zavin03cf4312009-01-23 16:38:30 -08002175
2176static struct ptable *flash_ptable = NULL;
2177
Dima Zavine5f64352009-03-02 16:04:20 -08002178void flash_init(void)
Dima Zavin03cf4312009-01-23 16:38:30 -08002179{
Dima Zavine5f64352009-03-02 16:04:20 -08002180 ASSERT(flash_ptable == NULL);
Dima Zavin03cf4312009-01-23 16:38:30 -08002181
2182 flash_ptrlist = memalign(32, 1024);
2183 flash_cmdlist = memalign(32, 1024);
Dima Zavin5582c7d2009-03-03 15:17:59 -08002184 flash_data = memalign(32, 2048 + 64);
Dima Zavin03cf4312009-01-23 16:38:30 -08002185 flash_spare = memalign(32, 64);
2186
Dima Zavin03cf4312009-01-23 16:38:30 -08002187 flash_read_id(flash_cmdlist, flash_ptrlist);
Shashank Mittal83d16d02009-11-18 16:54:42 -08002188 if((FLASH_8BIT_NAND_DEVICE == flash_info.type)
2189 ||(FLASH_16BIT_NAND_DEVICE == flash_info.type)) {
Shashank Mittalc20b5a12009-11-18 19:35:30 -08002190 if(flash_nand_read_config(flash_cmdlist, flash_ptrlist)) {
Shashank Mittal83d16d02009-11-18 16:54:42 -08002191 dprintf(CRITICAL, "ERROR: could not read CFG0/CFG1 state\n");
2192 ASSERT(0);
2193 }
2194 }
Dima Zavin03cf4312009-01-23 16:38:30 -08002195}
2196
2197struct ptable *flash_get_ptable(void)
2198{
2199 return flash_ptable;
2200}
2201
Dima Zavine5f64352009-03-02 16:04:20 -08002202void flash_set_ptable(struct ptable *new_ptable)
2203{
2204 ASSERT(flash_ptable == NULL && new_ptable != NULL);
2205 flash_ptable = new_ptable;
2206}
2207
Dima Zavinca337f52009-03-02 16:41:44 -08002208struct flash_info *flash_get_info(void)
2209{
2210 return &flash_info;
2211}
2212
Dima Zavin03cf4312009-01-23 16:38:30 -08002213int flash_erase(struct ptentry *ptn)
2214{
2215 unsigned block = ptn->start;
2216 unsigned count = ptn->length;
2217
2218 while(count-- > 0) {
2219 if(flash_erase_block(flash_cmdlist, flash_ptrlist, block * 64)) {
2220 dprintf(INFO, "cannot erase @ %d (bad block?)\n", block);
2221 }
2222 block++;
2223 }
2224 return 0;
2225}
2226
2227int flash_read_ext(struct ptentry *ptn, unsigned extra_per_page,
Shashank Mittalc20b5a12009-11-18 19:35:30 -08002228 unsigned offset, void *data, unsigned bytes)
Dima Zavin03cf4312009-01-23 16:38:30 -08002229{
Shashank Mittaldcc2e352009-11-19 19:11:16 -08002230 unsigned page = (ptn->start * 64) + (offset / flash_pagesize);
Dima Zavin03cf4312009-01-23 16:38:30 -08002231 unsigned lastpage = (ptn->start + ptn->length) * 64;
Shashank Mittaldcc2e352009-11-19 19:11:16 -08002232 unsigned count = (bytes + flash_pagesize - 1 + extra_per_page) / (flash_pagesize + extra_per_page);
Dima Zavin03cf4312009-01-23 16:38:30 -08002233 unsigned *spare = (unsigned*) flash_spare;
2234 unsigned errors = 0;
2235 unsigned char *image = data;
Shashank Mittalad3d05c2009-11-19 15:53:57 -08002236 unsigned current_block = (page - (page & 63)) >> 6;
2237 unsigned start_block = ptn->start;
2238 int result = 0;
2239 int isbad = 0;
Dima Zavin03cf4312009-01-23 16:38:30 -08002240
Shashank Mittaldcc2e352009-11-19 19:11:16 -08002241 if(offset & (flash_pagesize - 1))
Dima Zavin03cf4312009-01-23 16:38:30 -08002242 return -1;
2243
Shashank Mittalad3d05c2009-11-19 15:53:57 -08002244 // Adjust page offset based on number of bad blocks from start to current page
2245 while (start_block < current_block) {
2246 isbad = _flash_block_isbad(flash_cmdlist, flash_ptrlist, start_block*64);
2247 if (isbad)
2248 page += 64;
2249
2250 start_block++;
2251 }
2252
Dima Zavin03cf4312009-01-23 16:38:30 -08002253 while(page < lastpage) {
2254 if(count == 0) {
2255 dprintf(INFO, "flash_read_image: success (%d errors)\n", errors);
2256 return 0;
2257 }
2258
Shashank Mittalad3d05c2009-11-19 15:53:57 -08002259 result = _flash_read_page(flash_cmdlist, flash_ptrlist, page, image, spare);
2260
2261 if (result == -1) {
2262 // bad page, go to next page
2263 page++;
Dima Zavin03cf4312009-01-23 16:38:30 -08002264 errors++;
2265 continue;
2266 }
Shashank Mittalad3d05c2009-11-19 15:53:57 -08002267 else if (result == -2) {
2268 // bad block, go to next block same offset
2269 page += 64;
2270 errors++;
2271 continue;
2272 }
2273
2274 page++;
Shashank Mittaldcc2e352009-11-19 19:11:16 -08002275 image += flash_pagesize;
Dima Zavin03cf4312009-01-23 16:38:30 -08002276 memcpy(image, spare, extra_per_page);
2277 image += extra_per_page;
2278 count -= 1;
2279 }
2280
2281 /* could not find enough valid pages before we hit the end */
2282 dprintf(INFO, "flash_read_image: failed (%d errors)\n", errors);
2283 return 0xffffffff;
2284}
2285
2286int flash_write(struct ptentry *ptn, unsigned extra_per_page, const void *data,
2287 unsigned bytes)
2288{
2289 unsigned page = ptn->start * 64;
2290 unsigned lastpage = (ptn->start + ptn->length) * 64;
2291 unsigned *spare = (unsigned*) flash_spare;
2292 const unsigned char *image = data;
Shashank Mittaldcc2e352009-11-19 19:11:16 -08002293 unsigned wsize = flash_pagesize + extra_per_page;
Dima Zavin03cf4312009-01-23 16:38:30 -08002294 unsigned n;
2295 int r;
2296
2297 for(n = 0; n < 16; n++) spare[n] = 0xffffffff;
2298
2299 while(bytes > 0) {
2300 if(bytes < wsize) {
2301 dprintf(CRITICAL, "flash_write_image: image undersized (%d < %d)\n", bytes, wsize);
2302 return -1;
2303 }
2304 if(page >= lastpage) {
2305 dprintf(CRITICAL, "flash_write_image: out of space\n");
2306 return -1;
2307 }
2308
2309 if((page & 63) == 0) {
2310 if(flash_erase_block(flash_cmdlist, flash_ptrlist, page)) {
2311 dprintf(INFO, "flash_write_image: bad block @ %d\n", page >> 6);
2312 page += 64;
2313 continue;
2314 }
2315 }
2316
2317 if(extra_per_page) {
Shashank Mittald0c836d2009-11-20 10:31:18 -08002318 r = _flash_write_page(flash_cmdlist, flash_ptrlist, page, image, image + flash_pagesize);
Dima Zavin03cf4312009-01-23 16:38:30 -08002319 } else {
Shashank Mittald0c836d2009-11-20 10:31:18 -08002320 r = _flash_write_page(flash_cmdlist, flash_ptrlist, page, image, spare);
Dima Zavin03cf4312009-01-23 16:38:30 -08002321 }
2322 if(r) {
2323 dprintf(INFO, "flash_write_image: write failure @ page %d (src %d)\n", page, image - (const unsigned char *)data);
2324 image -= (page & 63) * wsize;
2325 bytes += (page & 63) * wsize;
2326 page &= ~63;
2327 if(flash_erase_block(flash_cmdlist, flash_ptrlist, page)) {
2328 dprintf(INFO, "flash_write_image: erase failure @ page %d\n", page);
2329 }
Shashank Mittald0c836d2009-11-20 10:31:18 -08002330 flash_mark_badblock(flash_cmdlist, flash_ptrlist, page);
Dima Zavin03cf4312009-01-23 16:38:30 -08002331 dprintf(INFO, "flash_write_image: restart write @ page %d (src %d)\n", page, image - (const unsigned char *)data);
2332 page += 64;
2333 continue;
2334 }
Shashank Mittald0c836d2009-11-20 10:31:18 -08002335 page++;
Dima Zavin03cf4312009-01-23 16:38:30 -08002336 image += wsize;
2337 bytes -= wsize;
2338 }
2339
2340 /* erase any remaining pages in the partition */
2341 page = (page + 63) & (~63);
2342 while(page < lastpage){
2343 if(flash_erase_block(flash_cmdlist, flash_ptrlist, page)) {
2344 dprintf(INFO, "flash_write_image: bad block @ %d\n", page >> 6);
2345 }
2346 page += 64;
2347 }
2348
2349 dprintf(INFO, "flash_write_image: success\n");
2350 return 0;
2351}
2352
2353#if 0
2354static int flash_read_page(unsigned page, void *data, void *extra)
2355{
2356 return _flash_read_page(flash_cmdlist, flash_ptrlist,
2357 page, data, extra);
2358}
2359#endif
Shashank Mittaldcc2e352009-11-19 19:11:16 -08002360
2361unsigned flash_page_size(void)
2362{
2363 return flash_pagesize;
2364}