blob: 49bec329896df665bb77a11102fc5cce9acadf8f [file] [log] [blame]
Dima Zavin03cf4312009-01-23 16:38:30 -08001/*
2 * Copyright (c) 2008, Google Inc.
3 * All rights reserved.
Ajay Dudani86e1b422009-12-04 20:49:50 -08004 * Copyright (c) 2009, 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;
72
73#define CFG1_WIDE_FLASH (1U << 1)
74
75#define paddr(n) ((unsigned) (n))
76
77static int dmov_exec_cmdptr(unsigned id, unsigned *ptr)
78{
79 dmov_ch ch;
80 unsigned n;
81
82 dmov_prep_ch(&ch, id);
83
84 writel(DMOV_CMD_PTR_LIST | DMOV_CMD_ADDR(paddr(ptr)), ch.cmd);
85
86 while(!(readl(ch.status) & DMOV_STATUS_RSLT_VALID)) ;
87
88 n = readl(ch.status);
89 while(DMOV_STATUS_RSLT_COUNT(n)) {
90 n = readl(ch.result);
91 if(n != 0x80000002) {
92 dprintf(CRITICAL, "ERROR: result: %x\n", n);
93 dprintf(CRITICAL, "ERROR: flush: %x %x %x %x\n",
94 readl(DMOV_FLUSH0(DMOV_NAND_CHAN)),
95 readl(DMOV_FLUSH1(DMOV_NAND_CHAN)),
96 readl(DMOV_FLUSH2(DMOV_NAND_CHAN)),
97 readl(DMOV_FLUSH3(DMOV_NAND_CHAN)));
98 }
99 n = readl(ch.status);
100 }
101
102 return 0;
103}
104
Dima Zavinca337f52009-03-02 16:41:44 -0800105static struct flash_info flash_info;
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800106static unsigned flash_pagesize = 0;
Dima Zavin03cf4312009-01-23 16:38:30 -0800107
Shashank Mittal83d16d02009-11-18 16:54:42 -0800108struct flash_identification {
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800109 unsigned flash_id;
110 unsigned mask;
111 unsigned density;
112 unsigned widebus;
113 unsigned pagesize;
114 unsigned blksize;
115 unsigned oobsize;
116 unsigned onenand;
Shashank Mittal83d16d02009-11-18 16:54:42 -0800117};
118
119static struct flash_identification supported_flash[] =
120{
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800121 /* Flash ID ID Mask Density(MB) Wid Pgsz Blksz oobsz onenand Manuf */
122 {0x00000000, 0xFFFFFFFF, 0, 0, 0, 0, 0, 0}, /*ONFI*/
123 {0x1500aaec, 0xFF00FFFF, (256<<20), 0, 2048, (2048<<6), 64, 0}, /*Sams*/
124 {0x5500baec, 0xFF00FFFF, (256<<20), 1, 2048, (2048<<6), 64, 0}, /*Sams*/
125 {0x1500aa98, 0xFFFFFFFF, (256<<20), 0, 2048, (2048<<6), 64, 0}, /*Tosh*/
126 {0x5500ba98, 0xFFFFFFFF, (256<<20), 1, 2048, (2048<<6), 64, 0}, /*Tosh*/
Ajay Dudani86e1b422009-12-04 20:49:50 -0800127 {0xd580b12c, 0xFFFFFFFF, (256<<20), 1, 2048, (2048<<6), 64, 0}, /*Micr*/
128 {0x5590bc2c, 0xFFFFFFFF, (256<<20), 1, 2048, (2048<<6), 64, 0}, /*Micr*/
Chandan Uddaraju0ec234c2009-11-24 22:34:50 -0800129 {0x1580aa2c, 0xFFFFFFFF, (256<<20), 0, 2048, (2048<<6), 64, 0}, /*Micr*/
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800130 {0x5580baad, 0xFFFFFFFF, (256<<20), 1, 2048, (2048<<6), 64, 0}, /*Hynx*/
131 {0x5510baad, 0xFFFFFFFF, (256<<20), 1, 2048, (2048<<6), 64, 0}, /*Hynx*/
132 {0x004000ec, 0xFFFFFFFF, (256<<20), 0, 2048, (2048<<6), 64, 1}, /*Sams*/
133 {0x005c00ec, 0xFFFFFFFF, (256<<20), 0, 2048, (2048<<6), 64, 1}, /*Sams*/
134 {0x005800ec, 0xFFFFFFFF, (256<<20), 0, 2048, (2048<<6), 64, 1}, /*Sams*/
Ajay Dudani232ce812009-12-02 00:14:11 -0800135 {0x6600bcec, 0xFF00FFFF, (1024<<20), 1, 4096, (4096<<6), 128, 0}, /*Sams*/
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800136 /* Note: Width flag is 0 for 8 bit Flash and 1 for 16 bit flash */
137 /* Note: Onenand flag is 0 for NAND Flash and 1 for OneNAND flash */
138 /* Note: The First row will be filled at runtime during ONFI probe */
Shashank Mittal83d16d02009-11-18 16:54:42 -0800139};
140
141static void flash_nand_read_id(dmov_s *cmdlist, unsigned *ptrlist)
Dima Zavin03cf4312009-01-23 16:38:30 -0800142{
143 dmov_s *cmd = cmdlist;
144 unsigned *ptr = ptrlist;
145 unsigned *data = ptrlist + 4;
146
147 data[0] = 0 | 4;
148 data[1] = NAND_CMD_FETCH_ID;
149 data[2] = 1;
150 data[3] = 0;
151 data[4] = 0;
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800152 data[5] = 0;
153 data[6] = 0;
154 data[7] = 0xAAD40000; /* Default value for CFG0 for reading device id */
Dima Zavin03cf4312009-01-23 16:38:30 -0800155
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800156 /* Read NAND device id */
Dima Zavin03cf4312009-01-23 16:38:30 -0800157 cmd[0].cmd = 0 | CMD_OCB;
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800158 cmd[0].src = paddr(&data[7]);
159 cmd[0].dst = NAND_DEV0_CFG0;
Dima Zavin03cf4312009-01-23 16:38:30 -0800160 cmd[0].len = 4;
161
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800162 cmd[1].cmd = 0;
163 cmd[1].src = NAND_SFLASHC_BURST_CFG;
164 cmd[1].dst = paddr(&data[5]);
Dima Zavin03cf4312009-01-23 16:38:30 -0800165 cmd[1].len = 4;
166
167 cmd[2].cmd = 0;
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800168 cmd[2].src = paddr(&data[6]);
169 cmd[2].dst = NAND_SFLASHC_BURST_CFG;
Dima Zavin03cf4312009-01-23 16:38:30 -0800170 cmd[2].len = 4;
171
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800172 cmd[3].cmd = 0;
173 cmd[3].src = paddr(&data[0]);
174 cmd[3].dst = NAND_FLASH_CHIP_SELECT;
Dima Zavin03cf4312009-01-23 16:38:30 -0800175 cmd[3].len = 4;
176
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800177 cmd[4].cmd = DST_CRCI_NAND_CMD;
178 cmd[4].src = paddr(&data[1]);
179 cmd[4].dst = NAND_FLASH_CMD;
Dima Zavin03cf4312009-01-23 16:38:30 -0800180 cmd[4].len = 4;
181
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800182 cmd[5].cmd = 0;
183 cmd[5].src = paddr(&data[2]);
184 cmd[5].dst = NAND_EXEC_CMD;
185 cmd[5].len = 4;
186
187 cmd[6].cmd = SRC_CRCI_NAND_DATA;
188 cmd[6].src = NAND_FLASH_STATUS;
189 cmd[6].dst = paddr(&data[3]);
190 cmd[6].len = 4;
191
192 cmd[7].cmd = 0;
193 cmd[7].src = NAND_READ_ID;
194 cmd[7].dst = paddr(&data[4]);
195 cmd[7].len = 4;
196
197 cmd[8].cmd = CMD_OCU | CMD_LC;
198 cmd[8].src = paddr(&data[5]);
199 cmd[8].dst = NAND_SFLASHC_BURST_CFG;
200 cmd[8].len = 4;
201
Dima Zavin03cf4312009-01-23 16:38:30 -0800202 ptr[0] = (paddr(cmd) >> 3) | CMD_PTR_LP;
203
204 dmov_exec_cmdptr(DMOV_NAND_CHAN, ptr);
205
206#if VERBOSE
207 dprintf(INFO, "status: %x\n", data[3]);
208#endif
Dima Zavin03cf4312009-01-23 16:38:30 -0800209
Shashank Mittal83d16d02009-11-18 16:54:42 -0800210 flash_info.id = data[4];
Dima Zavinca337f52009-03-02 16:41:44 -0800211 flash_info.vendor = data[4] & 0xff;
212 flash_info.device = (data[4] >> 8) & 0xff;
Shashank Mittal83d16d02009-11-18 16:54:42 -0800213 return;
214}
Dima Zavinca337f52009-03-02 16:41:44 -0800215
Shashank Mittalad3d05c2009-11-19 15:53:57 -0800216static int flash_nand_block_isbad(dmov_s *cmdlist, unsigned *ptrlist,
217 unsigned page)
218{
219 dmov_s *cmd = cmdlist;
220 unsigned *ptr = ptrlist;
221 unsigned *data = ptrlist + 4;
222 char buf[4];
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800223 unsigned cwperpage;
224
225 cwperpage = (flash_pagesize >> 9);
Shashank Mittalad3d05c2009-11-19 15:53:57 -0800226
227 /* Check first page of this block */
228 if(page & 63)
229 page = page - (page & 63);
230
231 /* Check bad block marker */
232 data[0] = NAND_CMD_PAGE_READ; /* command */
233
234 /* addr0 */
235 if (CFG1 & CFG1_WIDE_FLASH)
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800236 data[1] = (page << 16) | ((528*(cwperpage-1)) >> 1);
Shashank Mittalad3d05c2009-11-19 15:53:57 -0800237 else
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800238 data[1] = (page << 16) | (528*(cwperpage-1));
Shashank Mittalad3d05c2009-11-19 15:53:57 -0800239
240 data[2] = (page >> 16) & 0xff; /* addr1 */
241 data[3] = 0 | 4; /* chipsel */
242 data[4] = NAND_CFG0_RAW & ~(7U << 6); /* cfg0 */
243 data[5] = NAND_CFG1_RAW | (CFG1 & CFG1_WIDE_FLASH); /* cfg1 */
244 data[6] = 1;
245 data[7] = CLEAN_DATA_32; /* flash status */
246 data[8] = CLEAN_DATA_32; /* buf status */
247
248 cmd[0].cmd = DST_CRCI_NAND_CMD | CMD_OCB;
249 cmd[0].src = paddr(&data[0]);
250 cmd[0].dst = NAND_FLASH_CMD;
251 cmd[0].len = 16;
252
253 cmd[1].cmd = 0;
254 cmd[1].src = paddr(&data[4]);
255 cmd[1].dst = NAND_DEV0_CFG0;
256 cmd[1].len = 8;
257
258 cmd[2].cmd = 0;
259 cmd[2].src = paddr(&data[6]);
260 cmd[2].dst = NAND_EXEC_CMD;
261 cmd[2].len = 4;
262
263 cmd[3].cmd = SRC_CRCI_NAND_DATA;
264 cmd[3].src = NAND_FLASH_STATUS;
265 cmd[3].dst = paddr(&data[7]);
266 cmd[3].len = 8;
267
268 cmd[4].cmd = CMD_OCU | CMD_LC;
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800269 cmd[4].src = NAND_FLASH_BUFFER + (flash_pagesize - (528*(cwperpage-1)));
Shashank Mittalad3d05c2009-11-19 15:53:57 -0800270 cmd[4].dst = paddr(&buf);
271 cmd[4].len = 4;
272
273 ptr[0] = (paddr(cmd) >> 3) | CMD_PTR_LP;
274
275 dmov_exec_cmdptr(DMOV_NAND_CHAN, ptr);
276
277#if VERBOSE
278 dprintf(INFO, "status: %x\n", data[7]);
279#endif
280
281 /* we fail if there was an operation error, a mpu error, or the
282 ** erase success bit was not set.
283 */
284 if(data[7] & 0x110) return -1;
285
286 /* Check for bad block marker byte */
287 if (CFG1 & CFG1_WIDE_FLASH) {
288 if (buf[0] != 0xFF || buf[1] != 0xFF)
289 return 1;
290 } else {
291 if (buf[0] != 0xFF)
292 return 1;
293 }
294
295 return 0;
296}
297
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800298static int flash_nand_erase_block(dmov_s *cmdlist, unsigned *ptrlist,
299 unsigned page)
Dima Zavin03cf4312009-01-23 16:38:30 -0800300{
301 dmov_s *cmd = cmdlist;
302 unsigned *ptr = ptrlist;
303 unsigned *data = ptrlist + 4;
Shashank Mittalad3d05c2009-11-19 15:53:57 -0800304 int isbad = 0;
Dima Zavin03cf4312009-01-23 16:38:30 -0800305
306 /* only allow erasing on block boundaries */
307 if(page & 63) return -1;
308
Shashank Mittalad3d05c2009-11-19 15:53:57 -0800309 /* Check for bad block and erase only if block is not marked bad */
310 isbad = flash_nand_block_isbad(cmdlist, ptrlist, page);
311
312 if (isbad) {
313 dprintf(INFO, "skipping @ %d (bad block)\n", page >> 6);
314 return -1;
315 }
316
317 /* Erase block */
Dima Zavin03cf4312009-01-23 16:38:30 -0800318 data[0] = NAND_CMD_BLOCK_ERASE;
319 data[1] = page;
320 data[2] = 0;
321 data[3] = 0 | 4;
322 data[4] = 1;
323 data[5] = 0xeeeeeeee;
324 data[6] = CFG0 & (~(7 << 6)); /* CW_PER_PAGE = 0 */
325 data[7] = CFG1;
326
327 cmd[0].cmd = DST_CRCI_NAND_CMD | CMD_OCB;
328 cmd[0].src = paddr(&data[0]);
329 cmd[0].dst = NAND_FLASH_CMD;
330 cmd[0].len = 16;
331
332 cmd[1].cmd = 0;
333 cmd[1].src = paddr(&data[6]);
334 cmd[1].dst = NAND_DEV0_CFG0;
335 cmd[1].len = 8;
336
337 cmd[2].cmd = 0;
338 cmd[2].src = paddr(&data[4]);
339 cmd[2].dst = NAND_EXEC_CMD;
340 cmd[2].len = 4;
341
342 cmd[3].cmd = SRC_CRCI_NAND_DATA | CMD_OCU | CMD_LC;
343 cmd[3].src = NAND_FLASH_STATUS;
344 cmd[3].dst = paddr(&data[5]);
345 cmd[3].len = 4;
346
347 ptr[0] = (paddr(cmd) >> 3) | CMD_PTR_LP;
348
349 dmov_exec_cmdptr(DMOV_NAND_CHAN, ptr);
350
351#if VERBOSE
352 dprintf(INFO, "status: %x\n", data[5]);
353#endif
354
355 /* we fail if there was an operation error, a mpu error, or the
356 ** erase success bit was not set.
357 */
358 if(data[5] & 0x110) return -1;
359 if(!(data[5] & 0x80)) return -1;
360
361 return 0;
362}
363
364struct data_flash_io {
365 unsigned cmd;
366 unsigned addr0;
367 unsigned addr1;
368 unsigned chipsel;
369 unsigned cfg0;
370 unsigned cfg1;
371 unsigned exec;
372 unsigned ecc_cfg;
373 unsigned ecc_cfg_save;
374 struct {
375 unsigned flash_status;
376 unsigned buffer_status;
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800377 } result[8];
Dima Zavin03cf4312009-01-23 16:38:30 -0800378};
379
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800380static int _flash_nand_read_page(dmov_s *cmdlist, unsigned *ptrlist,
381 unsigned page, void *_addr, void *_spareaddr)
Dima Zavin03cf4312009-01-23 16:38:30 -0800382{
383 dmov_s *cmd = cmdlist;
384 unsigned *ptr = ptrlist;
385 struct data_flash_io *data = (void*) (ptrlist + 4);
386 unsigned addr = (unsigned) _addr;
387 unsigned spareaddr = (unsigned) _spareaddr;
388 unsigned n;
Shashank Mittalad3d05c2009-11-19 15:53:57 -0800389 int isbad = 0;
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800390 unsigned cwperpage;
391 cwperpage = (flash_pagesize >> 9);
Shashank Mittalad3d05c2009-11-19 15:53:57 -0800392
393 /* Check for bad block and read only from a good block */
394 isbad = flash_nand_block_isbad(cmdlist, ptrlist, page);
395 if (isbad)
396 return -2;
Dima Zavin03cf4312009-01-23 16:38:30 -0800397
398 data->cmd = NAND_CMD_PAGE_READ_ECC;
399 data->addr0 = page << 16;
400 data->addr1 = (page >> 16) & 0xff;
401 data->chipsel = 0 | 4; /* flash0 + undoc bit */
402
403 /* GO bit for the EXEC register */
404 data->exec = 1;
405
406 data->cfg0 = CFG0;
407 data->cfg1 = CFG1;
408
409 data->ecc_cfg = 0x203;
410
411 /* save existing ecc config */
412 cmd->cmd = CMD_OCB;
413 cmd->src = NAND_EBI2_ECC_BUF_CFG;
414 cmd->dst = paddr(&data->ecc_cfg_save);
415 cmd->len = 4;
416 cmd++;
417
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800418 for(n = 0; n < cwperpage; n++) {
Dima Zavin03cf4312009-01-23 16:38:30 -0800419 /* write CMD / ADDR0 / ADDR1 / CHIPSEL regs in a burst */
420 cmd->cmd = DST_CRCI_NAND_CMD;
421 cmd->src = paddr(&data->cmd);
422 cmd->dst = NAND_FLASH_CMD;
423 cmd->len = ((n == 0) ? 16 : 4);
424 cmd++;
425
426 if (n == 0) {
427 /* block on cmd ready, set configuration */
428 cmd->cmd = 0;
429 cmd->src = paddr(&data->cfg0);
430 cmd->dst = NAND_DEV0_CFG0;
431 cmd->len = 8;
432 cmd++;
433
434 /* set our ecc config */
435 cmd->cmd = 0;
436 cmd->src = paddr(&data->ecc_cfg);
437 cmd->dst = NAND_EBI2_ECC_BUF_CFG;
438 cmd->len = 4;
439 cmd++;
440 }
441 /* kick the execute register */
442 cmd->cmd = 0;
443 cmd->src = paddr(&data->exec);
444 cmd->dst = NAND_EXEC_CMD;
445 cmd->len = 4;
446 cmd++;
447
448 /* block on data ready, then read the status register */
449 cmd->cmd = SRC_CRCI_NAND_DATA;
450 cmd->src = NAND_FLASH_STATUS;
451 cmd->dst = paddr(&data->result[n]);
452 cmd->len = 8;
453 cmd++;
454
455 /* read data block */
456 cmd->cmd = 0;
457 cmd->src = NAND_FLASH_BUFFER;
458 cmd->dst = addr + n * 516;
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800459 cmd->len = ((n < (cwperpage -1 )) ? 516 : (512 - ((cwperpage - 1) << 2)));
Dima Zavin03cf4312009-01-23 16:38:30 -0800460 cmd++;
461 }
462
463 /* read extra data */
464 cmd->cmd = 0;
465 cmd->src = NAND_FLASH_BUFFER + 500;
466 cmd->dst = spareaddr;
467 cmd->len = 16;
468 cmd++;
469
470 /* restore saved ecc config */
471 cmd->cmd = CMD_OCU | CMD_LC;
472 cmd->src = paddr(&data->ecc_cfg_save);
473 cmd->dst = NAND_EBI2_ECC_BUF_CFG;
474 cmd->len = 4;
475
476 ptr[0] = (paddr(cmdlist) >> 3) | CMD_PTR_LP;
477
478 dmov_exec_cmdptr(DMOV_NAND_CHAN, ptr);
479
480#if VERBOSE
481 dprintf(INFO, "read page %d: status: %x %x %x %x\n",
482 page, data[5], data[6], data[7], data[8]);
483 for(n = 0; n < 4; n++) {
484 ptr = (unsigned*)(addr + 512 * n);
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800485 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 -0800486 ptr = (unsigned*)(spareaddr + 16 * n);
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800487 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 -0800488 }
489#endif
490
491 /* if any of the writes failed (0x10), or there was a
492 ** protection violation (0x100), we lose
493 */
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800494 for(n = 0; n < cwperpage; n++) {
Dima Zavin03cf4312009-01-23 16:38:30 -0800495 if (data->result[n].flash_status & 0x110) {
496 return -1;
497 }
498 }
499
500 return 0;
501}
502
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800503static int _flash_nand_write_page(dmov_s *cmdlist, unsigned *ptrlist, unsigned page,
Shashank Mittald0c836d2009-11-20 10:31:18 -0800504 const void *_addr, const void *_spareaddr, unsigned raw_mode)
Dima Zavin03cf4312009-01-23 16:38:30 -0800505{
506 dmov_s *cmd = cmdlist;
507 unsigned *ptr = ptrlist;
508 struct data_flash_io *data = (void*) (ptrlist + 4);
509 unsigned addr = (unsigned) _addr;
510 unsigned spareaddr = (unsigned) _spareaddr;
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800511 unsigned n;
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800512 unsigned cwperpage;
513 cwperpage = (flash_pagesize >> 9);
Dima Zavin03cf4312009-01-23 16:38:30 -0800514
515 data->cmd = NAND_CMD_PRG_PAGE;
516 data->addr0 = page << 16;
517 data->addr1 = (page >> 16) & 0xff;
518 data->chipsel = 0 | 4; /* flash0 + undoc bit */
519
Shashank Mittald0c836d2009-11-20 10:31:18 -0800520 if (!raw_mode){
521 data->cfg0 = CFG0;
522 data->cfg1 = CFG1;
523 }else{
524 data->cfg0 = (NAND_CFG0_RAW & ~(7 << 6)) |((cwperpage-1) << 6);
525 data->cfg1 = NAND_CFG1_RAW | (CFG1 & CFG1_WIDE_FLASH);
526 }
Dima Zavin03cf4312009-01-23 16:38:30 -0800527
528 /* GO bit for the EXEC register */
529 data->exec = 1;
530
531 data->ecc_cfg = 0x203;
532
533 /* save existing ecc config */
534 cmd->cmd = CMD_OCB;
535 cmd->src = NAND_EBI2_ECC_BUF_CFG;
536 cmd->dst = paddr(&data->ecc_cfg_save);
537 cmd->len = 4;
538 cmd++;
539
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800540 for(n = 0; n < cwperpage; n++) {
541 /* write CMD / ADDR0 / ADDR1 / CHIPSEL regs in a burst */
Dima Zavin03cf4312009-01-23 16:38:30 -0800542 cmd->cmd = DST_CRCI_NAND_CMD;
543 cmd->src = paddr(&data->cmd);
544 cmd->dst = NAND_FLASH_CMD;
545 cmd->len = ((n == 0) ? 16 : 4);
546 cmd++;
547
548 if (n == 0) {
549 /* set configuration */
550 cmd->cmd = 0;
551 cmd->src = paddr(&data->cfg0);
552 cmd->dst = NAND_DEV0_CFG0;
553 cmd->len = 8;
554 cmd++;
555
556 /* set our ecc config */
557 cmd->cmd = 0;
558 cmd->src = paddr(&data->ecc_cfg);
559 cmd->dst = NAND_EBI2_ECC_BUF_CFG;
560 cmd->len = 4;
561 cmd++;
562 }
563
564 /* write data block */
565 cmd->cmd = 0;
Dima Zavin03cf4312009-01-23 16:38:30 -0800566 cmd->dst = NAND_FLASH_BUFFER;
Shashank Mittald0c836d2009-11-20 10:31:18 -0800567 if (!raw_mode){
568 cmd->src = addr + n * 516;
569 cmd->len = ((n < (cwperpage - 1)) ? 516 : (512 - ((cwperpage - 1) << 2)));
570 }else{
571 cmd->src = addr;
572 cmd->len = 528;
573 }
Dima Zavin03cf4312009-01-23 16:38:30 -0800574 cmd++;
575
Shashank Mittald0c836d2009-11-20 10:31:18 -0800576 if ((n == (cwperpage - 1)) && (!raw_mode)) {
Dima Zavin03cf4312009-01-23 16:38:30 -0800577 /* write extra data */
578 cmd->cmd = 0;
579 cmd->src = spareaddr;
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800580 cmd->dst = NAND_FLASH_BUFFER + (512 - ((cwperpage - 1) << 2));
581 cmd->len = (cwperpage << 2);
Dima Zavin03cf4312009-01-23 16:38:30 -0800582 cmd++;
583 }
584
585 /* kick the execute register */
586 cmd->cmd = 0;
587 cmd->src = paddr(&data->exec);
588 cmd->dst = NAND_EXEC_CMD;
589 cmd->len = 4;
590 cmd++;
591
592 /* block on data ready, then read the status register */
593 cmd->cmd = SRC_CRCI_NAND_DATA;
594 cmd->src = NAND_FLASH_STATUS;
595 cmd->dst = paddr(&data->result[n]);
596 cmd->len = 8;
597 cmd++;
598 }
599
600 /* restore saved ecc config */
601 cmd->cmd = CMD_OCU | CMD_LC;
602 cmd->src = paddr(&data->ecc_cfg_save);
603 cmd->dst = NAND_EBI2_ECC_BUF_CFG;
604 cmd->len = 4;
605
606 ptr[0] = (paddr(cmdlist) >> 3) | CMD_PTR_LP;
607
608 dmov_exec_cmdptr(DMOV_NAND_CHAN, ptr);
609
610#if VERBOSE
611 dprintf(INFO, "write page %d: status: %x %x %x %x\n",
612 page, data[5], data[6], data[7], data[8]);
613#endif
614
615 /* if any of the writes failed (0x10), or there was a
616 ** protection violation (0x100), or the program success
617 ** bit (0x80) is unset, we lose
618 */
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800619 for(n = 0; n < cwperpage; n++) {
Dima Zavin03cf4312009-01-23 16:38:30 -0800620 if(data->result[n].flash_status & 0x110) return -1;
621 if(!(data->result[n].flash_status & 0x80)) return -1;
622 }
623
Dima Zavin5582c7d2009-03-03 15:17:59 -0800624#if VERIFY_WRITE
625 n = _flash_read_page(cmdlist, ptrlist, page, flash_data,
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800626 flash_data + 2048);
Dima Zavin5582c7d2009-03-03 15:17:59 -0800627 if (n != 0)
628 return -1;
629 if (memcmp(flash_data, _addr, 2048) ||
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800630 memcmp(flash_data + 2048, _spareaddr, 16)) {
Dima Zavin5582c7d2009-03-03 15:17:59 -0800631 dprintf(CRITICAL, "verify error @ page %d\n", page);
632 return -1;
633 }
634#endif
Dima Zavin03cf4312009-01-23 16:38:30 -0800635 return 0;
636}
Shashank Mittald0c836d2009-11-20 10:31:18 -0800637char empty_buf[528];
638static int flash_nand_mark_badblock(dmov_s *cmdlist, unsigned *ptrlist, unsigned page)
639{
640 memset(empty_buf,0,528);
641 /* Going to first page of the block */
642 if(page & 63)
643 page = page - (page & 63);
644 return _flash_nand_write_page(cmdlist, ptrlist, page, empty_buf, 0, 1);
645}
Dima Zavin03cf4312009-01-23 16:38:30 -0800646
Shashank Mittal83d16d02009-11-18 16:54:42 -0800647unsigned nand_cfg0;
648unsigned nand_cfg1;
649
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800650static int flash_nand_read_config(dmov_s *cmdlist, unsigned *ptrlist)
Dima Zavin03cf4312009-01-23 16:38:30 -0800651{
652 cmdlist[0].cmd = CMD_OCB;
653 cmdlist[0].src = NAND_DEV0_CFG0;
654 cmdlist[0].dst = paddr(&CFG0);
655 cmdlist[0].len = 4;
656
657 cmdlist[1].cmd = CMD_OCU | CMD_LC;
658 cmdlist[1].src = NAND_DEV0_CFG1;
659 cmdlist[1].dst = paddr(&CFG1);
660 cmdlist[1].len = 4;
661
662 *ptrlist = (paddr(cmdlist) >> 3) | CMD_PTR_LP;
663
664 dmov_exec_cmdptr(DMOV_NAND_CHAN, ptrlist);
665
666 if((CFG0 == 0) || (CFG1 == 0)) {
667 return -1;
668 }
669
Shashank Mittal83d16d02009-11-18 16:54:42 -0800670 if (flash_info.type == FLASH_16BIT_NAND_DEVICE) {
671 nand_cfg1 |= CFG1_WIDE_FLASH;
672 }
Dima Zavin03cf4312009-01-23 16:38:30 -0800673 dprintf(INFO, "nandcfg: %x %x (initial)\n", CFG0, CFG1);
674
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800675 CFG0 = (((flash_pagesize >> 9) - 1) << 6) /* 4/8 cw/pg for 2/4k */
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800676 | (516 << 9) /* 516 user data bytes */
677 | (10 << 19) /* 10 parity bytes */
678 | (5 << 27) /* 5 address cycles */
679 | (1 << 30) /* Read status before data */
680 | (1 << 31) /* Send read cmd */
681 /* 0 spare bytes for 16 bit nand or 1 spare bytes for 8 bit */
682 | ((nand_cfg1 & CFG1_WIDE_FLASH) ? (0 << 23) : (1 << 23));
Dima Zavin03cf4312009-01-23 16:38:30 -0800683 CFG1 = (0 << 0) /* Enable ecc */
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800684 | (7 << 2) /* 8 recovery cycles */
685 | (0 << 5) /* Allow CS deassertion */
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800686 | ((flash_pagesize - (528 * ((flash_pagesize >> 9) - 1)) + 1) << 6) /* Bad block marker location */
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800687 | (0 << 16) /* Bad block in user data area */
688 | (2 << 17) /* 6 cycle tWB/tRB */
689 | (nand_cfg1 & CFG1_WIDE_FLASH); /* preserve wide flash flag */
Dima Zavin03cf4312009-01-23 16:38:30 -0800690
691 dprintf(INFO, "nandcfg: %x %x (used)\n", CFG0, CFG1);
692
693 return 0;
694}
695
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800696/* OneNAND programming functions */
697
698static void flash_onenand_read_id(dmov_s *cmdlist, unsigned *ptrlist)
699{
700 dmov_s *cmd = cmdlist;
701 unsigned *ptr = ptrlist;
702 unsigned *data = ptrlist + 4;
703
704 data[0] = SFLASH_BCFG;
705 data[1] = SFLASH_PREPCMD(8, 0, 0, NAND_SFCMD_DATXS, NAND_SFCMD_ASYNC, NAND_SFCMD_REGRD);
706 data[2] = (ONENAND_DEVICE_ID << 16) | (ONENAND_MANUFACTURER_ID);
707 data[3] = (ONENAND_DATA_BUFFER_SIZE << 16) | (ONENAND_VERSION_ID);
708 data[4] = (ONENAND_AMOUNT_OF_BUFFERS << 16) | (ONENAND_BOOT_BUFFER_SIZE);
709 data[5] = (CLEAN_DATA_16 << 16) | (ONENAND_TECHNOLOGY);
710 data[6] = CLEAN_DATA_32; //status
711 data[7] = CLEAN_DATA_32; //register read
712 data[8] = CLEAN_DATA_32; //register read
713 data[9] = CLEAN_DATA_32; //register read
714 data[10] = CLEAN_DATA_32; //register read
715 data[11] = 1;
716 data[12] = 0 | 4;
717
718 /* Setup controller in SFLASH mode */
719 cmd[0].cmd = 0 | CMD_OCB;
720 cmd[0].src = paddr(&data[0]);
721 cmd[0].dst = NAND_SFLASHC_BURST_CFG;
722 cmd[0].len = 4;
723
724 /* Enable data mover for controller */
725 cmd[1].cmd = 0;
726 cmd[1].src = paddr(&data[12]);
727 cmd[1].dst = NAND_FLASH_CHIP_SELECT;
728 cmd[1].len = 4;
729
730 /* Setup SFLASHC_CMD with xfers in async mode */
731 cmd[2].cmd = DST_CRCI_NAND_CMD;
732 cmd[2].src = paddr(&data[1]);
733 cmd[2].dst = NAND_SFLASHC_CMD;
734 cmd[2].len = 4;
735
736 /* Setup to read device information */
737 cmd[3].cmd = 0;
738 cmd[3].src = paddr(&data[2]);
739 cmd[3].dst = NAND_ADDR0;
740 cmd[3].len = 8;
741
742 cmd[4].cmd = 0;
743 cmd[4].src = paddr(&data[4]);
744 cmd[4].dst = NAND_ADDR2;
745 cmd[4].len = 8;
746
747 /* Set execute bit */
748 cmd[5].cmd = 0;
749 cmd[5].src = paddr(&data[11]);
750 cmd[5].dst = NAND_SFLASHC_EXEC_CMD;
751 cmd[5].len = 4;
752
753 /* Check status */
754 cmd[6].cmd = SRC_CRCI_NAND_DATA;
755 cmd[6].src = NAND_SFLASHC_STATUS;
756 cmd[6].dst = paddr(&data[6]);
757 cmd[6].len = 4;
758
759 /* Read result device registers */
760 cmd[7].cmd = 0 | CMD_OCU | CMD_LC;
761 cmd[7].src = NAND_GENP_REG0;
762 cmd[7].dst = paddr(&data[7]);
763 cmd[7].len = 16;
764
765 ptr[0] = (paddr(cmd) >> 3) | CMD_PTR_LP;
766
767 dmov_exec_cmdptr(DMOV_NAND_CHAN, ptr);
768
769#if VERBOSE
770 dprintf(INFO, "status: %x\n", data[6]);
771#endif
772
773 flash_info.id = data[7];
774 flash_info.vendor = data[7] & CLEAN_DATA_16;
775 flash_info.device = (data[7] >> 16) & CLEAN_DATA_16;
776 return;
777}
778
779
780struct data_onenand_erase {
781 unsigned sfbcfg;
782 unsigned sfcmd[4];
783 unsigned sfexec;
784 unsigned sfstat[4];
785 unsigned addr0;
786 unsigned addr1;
787 unsigned addr2;
788 unsigned addr3;
789 unsigned addr4;
790 unsigned addr5;
791 unsigned addr6;
792 unsigned data0;
793 unsigned data1;
794 unsigned data2;
795 unsigned data3;
796 unsigned data4;
797 unsigned data5;
798 unsigned data6;
799};
800
Shashank Mittalad3d05c2009-11-19 15:53:57 -0800801
802static int _flash_onenand_read_page(dmov_s *cmdlist, unsigned *ptrlist,
803 unsigned page, void *_addr,
804 void *_spareaddr, unsigned raw_mode);
805
806
807static int flash_onenand_block_isbad(dmov_s *cmdlist, unsigned *ptrlist,
808 unsigned page)
809{
810 unsigned char page_data[2112];
811 unsigned char *oobptr = &(page_data[2048]);
812
813 /* Going to first page of the block */
814 if(page & 63)
815 page = page - (page & 63);
816
817 /* Reading page in raw mode */
818 if (_flash_onenand_read_page(cmdlist, ptrlist,page, page_data, 0, 1))
819 return 1;
820
821 /* Checking if block is bad */
822 if ((oobptr[0] != 0xFF) || (oobptr[1] != 0xFF) ||
823 (oobptr[16] != 0xFF) || (oobptr[17] != 0xFF) ||
824 (oobptr[32] != 0xFF) || (oobptr[33] != 0xFF) ||
825 (oobptr[48] != 0xFF) || (oobptr[49] != 0xFF)
826 )
827 {
828 return 1;
829 }
830 return 0;
831}
832
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800833static int flash_onenand_erase_block(dmov_s *cmdlist, unsigned *ptrlist,
834 unsigned page)
835{
836 dmov_s *cmd = cmdlist;
837 unsigned *ptr = ptrlist;
838 struct data_onenand_erase *data = (void *)ptrlist + 4;
Shashank Mittalad3d05c2009-11-19 15:53:57 -0800839 int isbad = 0;
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800840 unsigned erasesize = (flash_pagesize << 6);
841 unsigned onenand_startaddr1 = DEVICE_FLASHCORE_0 | (page * flash_pagesize)/erasesize;
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800842 unsigned onenand_startaddr8 = 0x0000;
843 unsigned onenand_startaddr2 = DEVICE_BUFFERRAM_0 << 15;
844 unsigned onenand_startbuffer = DATARAM0_0 << 8;
845
846 unsigned controller_status;
847 unsigned interrupt_status;
848 unsigned ecc_status;
849
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800850 if((page * flash_pagesize) & (erasesize-1)) return -1;
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800851
Shashank Mittalad3d05c2009-11-19 15:53:57 -0800852 /* Check for bad block and erase only if block is not marked bad */
853 isbad = flash_onenand_block_isbad(cmdlist, ptrlist, page);
854 if (isbad)
855 {
856 dprintf(INFO, "skipping @ %d (bad block)\n", page >> 6);
857 return -1;
858 }
859
860 /*Erase block*/
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800861 onenand_startaddr1 = DEVICE_FLASHCORE_0 |
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800862 ((page * flash_pagesize) / (erasesize));
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800863 onenand_startaddr8 = 0x0000;
864 onenand_startaddr2 = DEVICE_BUFFERRAM_0 << 15;
865 onenand_startbuffer = DATARAM0_0 << 8;
866
867
868 data->sfbcfg = SFLASH_BCFG;
869 data->sfcmd[0] = SFLASH_PREPCMD(7, 0, 0,
870 NAND_SFCMD_CMDXS,
871 NAND_SFCMD_ASYNC,
872 NAND_SFCMD_REGWR);
873 data->sfcmd[1] = SFLASH_PREPCMD(0, 0, 32,
874 NAND_SFCMD_CMDXS,
875 NAND_SFCMD_ASYNC,
876 NAND_SFCMD_INTHI);
877 data->sfcmd[2] = SFLASH_PREPCMD(3, 7, 0,
878 NAND_SFCMD_DATXS,
879 NAND_SFCMD_ASYNC,
880 NAND_SFCMD_REGRD);
881 data->sfcmd[3] = SFLASH_PREPCMD(4, 10, 0,
882 NAND_SFCMD_CMDXS,
883 NAND_SFCMD_ASYNC,
884 NAND_SFCMD_REGWR);
885 data->sfexec = 1;
886 data->sfstat[0] = CLEAN_DATA_32;
887 data->sfstat[1] = CLEAN_DATA_32;
888 data->sfstat[2] = CLEAN_DATA_32;
889 data->sfstat[3] = CLEAN_DATA_32;
890 data->addr0 = (ONENAND_INTERRUPT_STATUS << 16) |
891 (ONENAND_SYSTEM_CONFIG_1);
892 data->addr1 = (ONENAND_START_ADDRESS_8 << 16) |
893 (ONENAND_START_ADDRESS_1);
894 data->addr2 = (ONENAND_START_BUFFER << 16) |
895 (ONENAND_START_ADDRESS_2);
896 data->addr3 = (ONENAND_ECC_STATUS << 16) |
897 (ONENAND_COMMAND);
898 data->addr4 = (ONENAND_CONTROLLER_STATUS << 16) |
899 (ONENAND_INTERRUPT_STATUS);
900 data->addr5 = (ONENAND_INTERRUPT_STATUS << 16) |
901 (ONENAND_SYSTEM_CONFIG_1);
902 data->addr6 = (ONENAND_START_ADDRESS_3 << 16) |
903 (ONENAND_START_ADDRESS_1);
904 data->data0 = (ONENAND_CLRINTR << 16) |
905 (ONENAND_SYSCFG1_ECCENA);
906 data->data1 = (onenand_startaddr8 << 16) |
907 (onenand_startaddr1);
908 data->data2 = (onenand_startbuffer << 16) |
909 (onenand_startaddr2);
910 data->data3 = (CLEAN_DATA_16 << 16) |
911 (ONENAND_CMDERAS);
912 data->data4 = (CLEAN_DATA_16 << 16) |
913 (CLEAN_DATA_16);
914 data->data5 = (ONENAND_CLRINTR << 16) |
915 (ONENAND_SYSCFG1_ECCENA);
916 data->data6 = (ONENAND_STARTADDR3_RES << 16) |
917 (ONENAND_STARTADDR1_RES);
918
919 /***************************************************************/
920 /* Write the necessary address registers in the onenand device */
921 /***************************************************************/
922
923 /* Enable and configure the SFlash controller */
924 cmd->cmd = 0 | CMD_OCB;
925 cmd->src = paddr(&data->sfbcfg);
926 cmd->dst = NAND_SFLASHC_BURST_CFG;
927 cmd->len = 4;
928 cmd++;
929
930 /* Block on cmd ready and write CMD register */
931 cmd->cmd = DST_CRCI_NAND_CMD;
932 cmd->src = paddr(&data->sfcmd[0]);
933 cmd->dst = NAND_SFLASHC_CMD;
934 cmd->len = 4;
935 cmd++;
936
937 /* Write the ADDR0 and ADDR1 registers */
938 cmd->cmd = 0;
939 cmd->src = paddr(&data->addr0);
940 cmd->dst = NAND_ADDR0;
941 cmd->len = 8;
942 cmd++;
943
944 /* Write the ADDR2 ADDR3 ADDR4 ADDR5 registers */
945 cmd->cmd = 0;
946 cmd->src = paddr(&data->addr2);
947 cmd->dst = NAND_ADDR2;
948 cmd->len = 16;
949 cmd++;
950
951 /* Write the ADDR6 registers */
952 cmd->cmd = 0;
953 cmd->src = paddr(&data->addr6);
954 cmd->dst = NAND_ADDR6;
955 cmd->len = 4;
956 cmd++;
957
958 /* Write the GENP0, GENP1, GENP2, GENP3, GENP4 registers */
959 cmd->cmd = 0;
960 cmd->src = paddr(&data->data0);
961 cmd->dst = NAND_GENP_REG0;
962 cmd->len = 16;
963 cmd++;
964
965 /* Write the FLASH_DEV_CMD4,5,6 registers */
966 cmd->cmd = 0;
967 cmd->src = paddr(&data->data4);
968 cmd->dst = NAND_DEV_CMD4;
969 cmd->len = 12;
970 cmd++;
971
972 /* Kick the execute command */
973 cmd->cmd = 0;
974 cmd->src = paddr(&data->sfexec);
975 cmd->dst = NAND_SFLASHC_EXEC_CMD;
976 cmd->len = 4;
977 cmd++;
978
979 /* Block on data ready, and read the status register */
980 cmd->cmd = SRC_CRCI_NAND_DATA;
981 cmd->src = NAND_SFLASHC_STATUS;
982 cmd->dst = paddr(&data->sfstat[0]);
983 cmd->len = 4;
984 cmd++;
985
986 /***************************************************************/
987 /* Wait for the interrupt from the Onenand device controller */
988 /***************************************************************/
989
990 /* Block on cmd ready and write CMD register */
991 cmd->cmd = DST_CRCI_NAND_CMD;
992 cmd->src = paddr(&data->sfcmd[1]);
993 cmd->dst = NAND_SFLASHC_CMD;
994 cmd->len = 4;
995 cmd++;
996
997 /* Kick the execute command */
998 cmd->cmd = 0;
999 cmd->src = paddr(&data->sfexec);
1000 cmd->dst = NAND_SFLASHC_EXEC_CMD;
1001 cmd->len = 4;
1002 cmd++;
1003
1004 /* Block on data ready, and read the status register */
1005 cmd->cmd = SRC_CRCI_NAND_DATA;
1006 cmd->src = NAND_SFLASHC_STATUS;
1007 cmd->dst = paddr(&data->sfstat[1]);
1008 cmd->len = 4;
1009 cmd++;
1010
1011 /***************************************************************/
1012 /* Read the necessary status registers from the onenand device */
1013 /***************************************************************/
1014
1015 /* Block on cmd ready and write CMD register */
1016 cmd->cmd = DST_CRCI_NAND_CMD;
1017 cmd->src = paddr(&data->sfcmd[2]);
1018 cmd->dst = NAND_SFLASHC_CMD;
1019 cmd->len = 4;
1020 cmd++;
1021
1022 /* Kick the execute command */
1023 cmd->cmd = 0;
1024 cmd->src = paddr(&data->sfexec);
1025 cmd->dst = NAND_SFLASHC_EXEC_CMD;
1026 cmd->len = 4;
1027 cmd++;
1028
1029 /* Block on data ready, and read the status register */
1030 cmd->cmd = SRC_CRCI_NAND_DATA;
1031 cmd->src = NAND_SFLASHC_STATUS;
1032 cmd->dst = paddr(&data->sfstat[2]);
1033 cmd->len = 4;
1034 cmd++;
1035
1036 /* Read the GENP3 register */
1037 cmd->cmd = 0;
1038 cmd->src = NAND_GENP_REG3;
1039 cmd->dst = paddr(&data->data3);
1040 cmd->len = 4;
1041 cmd++;
1042
1043 /* Read the DEVCMD4 register */
1044 cmd->cmd = 0;
1045 cmd->src = NAND_DEV_CMD4;
1046 cmd->dst = paddr(&data->data4);
1047 cmd->len = 4;
1048 cmd++;
1049
1050 /***************************************************************/
1051 /* Restore the necessary registers to proper values */
1052 /***************************************************************/
1053
1054 /* Block on cmd ready and write CMD register */
1055 cmd->cmd = DST_CRCI_NAND_CMD;
1056 cmd->src = paddr(&data->sfcmd[3]);
1057 cmd->dst = NAND_SFLASHC_CMD;
1058 cmd->len = 4;
1059 cmd++;
1060
1061 /* Kick the execute command */
1062 cmd->cmd = 0;
1063 cmd->src = paddr(&data->sfexec);
1064 cmd->dst = NAND_SFLASHC_EXEC_CMD;
1065 cmd->len = 4;
1066 cmd++;
1067
1068 /* Block on data ready, and read the status register */
1069 cmd->cmd = SRC_CRCI_NAND_DATA | CMD_OCU | CMD_LC;
1070 cmd->src = NAND_SFLASHC_STATUS;
1071 cmd->dst = paddr(&data->sfstat[3]);
1072 cmd->len = 4;
1073 cmd++;
1074
1075 ptr[0] = (paddr(cmdlist) >> 3) | CMD_PTR_LP;
1076
1077 dmov_exec_cmdptr(DMOV_NAND_CHAN, ptr);
1078
1079 ecc_status = (data->data3 >> 16) & 0x0000FFFF;
1080 interrupt_status = (data->data4 >> 0) & 0x0000FFFF;
1081 controller_status = (data->data4 >> 16) & 0x0000FFFF;
1082
1083#if VERBOSE
1084 dprintf(INFO, "\n%s: sflash status %x %x %x %x\n", __func__,
1085 data->sfstat[0],
1086 data->sfstat[1],
1087 data->sfstat[2],
1088 data->sfstat[3]);
1089
1090 dprintf(INFO, "%s: controller_status = %x\n", __func__,
1091 controller_status);
1092 dprintf(INFO, "%s: interrupt_status = %x\n", __func__,
1093 interrupt_status);
1094 dprintf(INFO, "%s: ecc_status = %x\n", __func__,
1095 ecc_status);
1096#endif
1097 /* Check for errors, protection violations etc */
1098 if ((controller_status != 0)
1099 || (data->sfstat[0] & 0x110)
1100 || (data->sfstat[1] & 0x110)
1101 || (data->sfstat[2] & 0x110)
1102 || (data->sfstat[3] & 0x110)) {
1103 dprintf(CRITICAL, "%s: ECC/MPU/OP error\n", __func__);
1104 return -1;
1105 }
1106
1107
1108#if VERBOSE
1109 dprintf(INFO, "status: %x\n", data[5]);
1110#endif
1111
1112 return 0;
1113}
1114
1115
1116struct data_onenand_read {
1117 unsigned sfbcfg;
1118 unsigned sfcmd[9];
1119 unsigned sfexec;
1120 unsigned sfstat[9];
1121 unsigned addr0;
1122 unsigned addr1;
1123 unsigned addr2;
1124 unsigned addr3;
1125 unsigned addr4;
1126 unsigned addr5;
1127 unsigned addr6;
1128 unsigned data0;
1129 unsigned data1;
1130 unsigned data2;
1131 unsigned data3;
1132 unsigned data4;
1133 unsigned data5;
1134 unsigned data6;
1135 unsigned macro[5];
1136};
1137
1138
1139static int _flash_onenand_read_page(dmov_s *cmdlist, unsigned *ptrlist,
Shashank Mittalad3d05c2009-11-19 15:53:57 -08001140 unsigned page, void *_addr, void *_spareaddr,
1141 unsigned raw_mode)
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001142{
1143 dmov_s *cmd = cmdlist;
1144 unsigned *ptr = ptrlist;
1145 struct data_onenand_read *data = (void*) (ptrlist + 4);
1146 unsigned addr = (unsigned) _addr;
1147 unsigned curr_addr = (unsigned) _addr;
1148 unsigned spareaddr = (unsigned) _spareaddr;
1149 unsigned i;
Shashank Mittaldcc2e352009-11-19 19:11:16 -08001150 unsigned erasesize = (flash_pagesize<<6);
1151 unsigned writesize = flash_pagesize;
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001152
1153 unsigned onenand_startaddr1 = DEVICE_FLASHCORE_0 |
Shashank Mittaldcc2e352009-11-19 19:11:16 -08001154 ((unsigned)(page * flash_pagesize) / erasesize);
1155 unsigned onenand_startaddr8 = (((unsigned)(page * flash_pagesize) &
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001156 (erasesize - 1)) / writesize) << 2;
1157 unsigned onenand_startaddr2 = DEVICE_BUFFERRAM_0 << 15;
1158 unsigned onenand_startbuffer = DATARAM0_0 << 8;
Shashank Mittalad3d05c2009-11-19 15:53:57 -08001159 unsigned onenand_sysconfig1 = (raw_mode == 1) ? ONENAND_SYSCFG1_ECCDIS :\
1160 ONENAND_SYSCFG1_ECCENA;
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001161
1162 unsigned controller_status;
1163 unsigned interrupt_status;
1164 unsigned ecc_status;
Shashank Mittalad3d05c2009-11-19 15:53:57 -08001165 if (raw_mode != 1)
1166 {
1167 int isbad = 0;
1168 isbad = flash_onenand_block_isbad(cmdlist, ptrlist, page);
1169 if (isbad)
1170 return -2;
1171 }
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001172
1173 //static int oobfree_offset[8] = {2, 14, 18, 30, 34, 46, 50, 62};
1174 //static int oobfree_length[8] = {3, 2, 3, 2, 3, 2, 3, 2};
1175
1176 data->sfbcfg = SFLASH_BCFG;
1177 data->sfcmd[0] = SFLASH_PREPCMD(7, 0, 0,
1178 NAND_SFCMD_CMDXS,
1179 NAND_SFCMD_ASYNC,
1180 NAND_SFCMD_REGWR);
1181 data->sfcmd[1] = SFLASH_PREPCMD(0, 0, 32,
1182 NAND_SFCMD_CMDXS,
1183 NAND_SFCMD_ASYNC,
1184 NAND_SFCMD_INTHI);
1185 data->sfcmd[2] = SFLASH_PREPCMD(3, 7, 0,
1186 NAND_SFCMD_DATXS,
1187 NAND_SFCMD_ASYNC,
1188 NAND_SFCMD_REGRD);
1189 data->sfcmd[3] = SFLASH_PREPCMD(256, 0, 0,
1190 NAND_SFCMD_DATXS,
1191 NAND_SFCMD_ASYNC,
1192 NAND_SFCMD_DATRD);
1193 data->sfcmd[4] = SFLASH_PREPCMD(256, 0, 0,
1194 NAND_SFCMD_DATXS,
1195 NAND_SFCMD_ASYNC,
1196 NAND_SFCMD_DATRD);
1197 data->sfcmd[5] = SFLASH_PREPCMD(256, 0, 0,
1198 NAND_SFCMD_DATXS,
1199 NAND_SFCMD_ASYNC,
1200 NAND_SFCMD_DATRD);
1201 data->sfcmd[6] = SFLASH_PREPCMD(256, 0, 0,
1202 NAND_SFCMD_DATXS,
1203 NAND_SFCMD_ASYNC,
1204 NAND_SFCMD_DATRD);
1205 data->sfcmd[7] = SFLASH_PREPCMD(32, 0, 0,
1206 NAND_SFCMD_DATXS,
1207 NAND_SFCMD_ASYNC,
1208 NAND_SFCMD_DATRD);
1209 data->sfcmd[8] = SFLASH_PREPCMD(4, 10, 0,
1210 NAND_SFCMD_CMDXS,
1211 NAND_SFCMD_ASYNC,
1212 NAND_SFCMD_REGWR);
1213 data->sfexec = 1;
1214 data->sfstat[0] = CLEAN_DATA_32;
1215 data->sfstat[1] = CLEAN_DATA_32;
1216 data->sfstat[2] = CLEAN_DATA_32;
1217 data->sfstat[3] = CLEAN_DATA_32;
1218 data->sfstat[4] = CLEAN_DATA_32;
1219 data->sfstat[5] = CLEAN_DATA_32;
1220 data->sfstat[6] = CLEAN_DATA_32;
1221 data->sfstat[7] = CLEAN_DATA_32;
1222 data->sfstat[8] = CLEAN_DATA_32;
1223
1224 data->addr0 = (ONENAND_INTERRUPT_STATUS << 16) |
1225 (ONENAND_SYSTEM_CONFIG_1);
1226 data->addr1 = (ONENAND_START_ADDRESS_8 << 16) |
1227 (ONENAND_START_ADDRESS_1);
1228 data->addr2 = (ONENAND_START_BUFFER << 16) |
1229 (ONENAND_START_ADDRESS_2);
1230 data->addr3 = (ONENAND_ECC_STATUS << 16) |
1231 (ONENAND_COMMAND);
1232 data->addr4 = (ONENAND_CONTROLLER_STATUS << 16) |
1233 (ONENAND_INTERRUPT_STATUS);
1234 data->addr5 = (ONENAND_INTERRUPT_STATUS << 16) |
1235 (ONENAND_SYSTEM_CONFIG_1);
1236 data->addr6 = (ONENAND_START_ADDRESS_3 << 16) |
1237 (ONENAND_START_ADDRESS_1);
1238 data->data0 = (ONENAND_CLRINTR << 16) |
1239 (onenand_sysconfig1);
1240 data->data1 = (onenand_startaddr8 << 16) |
1241 (onenand_startaddr1);
1242 data->data2 = (onenand_startbuffer << 16) |
1243 (onenand_startaddr2);
1244 data->data3 = (CLEAN_DATA_16 << 16) |
1245 (ONENAND_CMDLOADSPARE);
1246 data->data4 = (CLEAN_DATA_16 << 16) |
1247 (CLEAN_DATA_16);
1248 data->data5 = (ONENAND_CLRINTR << 16) |
1249 (ONENAND_SYSCFG1_ECCENA);
1250 data->data6 = (ONENAND_STARTADDR3_RES << 16) |
1251 (ONENAND_STARTADDR1_RES);
1252 data->macro[0] = 0x0200;
1253 data->macro[1] = 0x0300;
1254 data->macro[2] = 0x0400;
1255 data->macro[3] = 0x0500;
1256 data->macro[4] = 0x8010;
1257
1258 /*************************************************************/
1259 /* Write necessary address registers in the onenand device */
1260 /*************************************************************/
1261
1262 /* Enable and configure the SFlash controller */
1263 cmd->cmd = 0 | CMD_OCB;
1264 cmd->src = paddr(&data->sfbcfg);
1265 cmd->dst = NAND_SFLASHC_BURST_CFG;
1266 cmd->len = 4;
1267 cmd++;
1268
1269 /* Block on cmd ready and write CMD register */
1270 cmd->cmd = DST_CRCI_NAND_CMD;
1271 cmd->src = paddr(&data->sfcmd[0]);
1272 cmd->dst = NAND_SFLASHC_CMD;
1273 cmd->len = 4;
1274 cmd++;
1275
1276 /* Write the ADDR0 and ADDR1 registers */
1277 cmd->cmd = 0;
1278 cmd->src = paddr(&data->addr0);
1279 cmd->dst = NAND_ADDR0;
1280 cmd->len = 8;
1281 cmd++;
1282
1283 /* Write the ADDR2 ADDR3 ADDR4 ADDR5 registers */
1284 cmd->cmd = 0;
1285 cmd->src = paddr(&data->addr2);
1286 cmd->dst = NAND_ADDR2;
1287 cmd->len = 16;
1288 cmd++;
1289
1290 /* Write the ADDR6 registers */
1291 cmd->cmd = 0;
1292 cmd->src = paddr(&data->addr6);
1293 cmd->dst = NAND_ADDR6;
1294 cmd->len = 4;
1295 cmd++;
1296
1297 /* Write the GENP0, GENP1, GENP2, GENP3 registers */
1298 cmd->cmd = 0;
1299 cmd->src = paddr(&data->data0);
1300 cmd->dst = NAND_GENP_REG0;
1301 cmd->len = 16;
1302 cmd++;
1303
1304 /* Write the FLASH_DEV_CMD4,5,6 registers */
1305 cmd->cmd = 0;
1306 cmd->src = paddr(&data->data4);
1307 cmd->dst = NAND_DEV_CMD4;
1308 cmd->len = 12;
1309 cmd++;
1310
1311 /* Kick the execute command */
1312 cmd->cmd = 0;
1313 cmd->src = paddr(&data->sfexec);
1314 cmd->dst = NAND_SFLASHC_EXEC_CMD;
1315 cmd->len = 4;
1316 cmd++;
1317
1318 /* Block on data ready, and read the status register */
1319 cmd->cmd = SRC_CRCI_NAND_DATA;
1320 cmd->src = NAND_SFLASHC_STATUS;
1321 cmd->dst = paddr(&data->sfstat[0]);
1322 cmd->len = 4;
1323 cmd++;
1324
1325 /*************************************************************/
1326 /* Wait for the interrupt from the Onenand device controller */
1327 /*************************************************************/
1328
1329 /* Block on cmd ready and write CMD register */
1330 cmd->cmd = DST_CRCI_NAND_CMD;
1331 cmd->src = paddr(&data->sfcmd[1]);
1332 cmd->dst = NAND_SFLASHC_CMD;
1333 cmd->len = 4;
1334 cmd++;
1335
1336 /* Kick the execute command */
1337 cmd->cmd = 0;
1338 cmd->src = paddr(&data->sfexec);
1339 cmd->dst = NAND_SFLASHC_EXEC_CMD;
1340 cmd->len = 4;
1341 cmd++;
1342
1343 /* Block on data ready, and read the status register */
1344 cmd->cmd = SRC_CRCI_NAND_DATA;
1345 cmd->src = NAND_SFLASHC_STATUS;
1346 cmd->dst = paddr(&data->sfstat[1]);
1347 cmd->len = 4;
1348 cmd++;
1349
1350
1351 /*************************************************************/
1352 /* Read necessary status registers from the onenand device */
1353 /*************************************************************/
1354
1355 /* Block on cmd ready and write CMD register */
1356 cmd->cmd = DST_CRCI_NAND_CMD;
1357 cmd->src = paddr(&data->sfcmd[2]);
1358 cmd->dst = NAND_SFLASHC_CMD;
1359 cmd->len = 4;
1360 cmd++;
1361
1362 /* Kick the execute command */
1363 cmd->cmd = 0;
1364 cmd->src = paddr(&data->sfexec);
1365 cmd->dst = NAND_SFLASHC_EXEC_CMD;
1366 cmd->len = 4;
1367 cmd++;
1368
1369 /* Block on data ready, and read the status register */
1370 cmd->cmd = SRC_CRCI_NAND_DATA;
1371 cmd->src = NAND_SFLASHC_STATUS;
1372 cmd->dst = paddr(&data->sfstat[2]);
1373 cmd->len = 4;
1374 cmd++;
1375
1376 /* Read the GENP3 register */
1377 cmd->cmd = 0;
1378 cmd->src = NAND_GENP_REG3;
1379 cmd->dst = paddr(&data->data3);
1380 cmd->len = 4;
1381 cmd++;
1382
1383 /* Read the DEVCMD4 register */
1384 cmd->cmd = 0;
1385 cmd->src = NAND_DEV_CMD4;
1386 cmd->dst = paddr(&data->data4);
1387 cmd->len = 4;
1388 cmd++;
1389
1390
1391 /*************************************************************/
1392 /* Read the data ram area from the onenand buffer ram */
1393 /*************************************************************/
1394
1395 if (addr) {
1396
1397 data->data3 = (CLEAN_DATA_16 << 16) |
1398 (ONENAND_CMDLOAD);
1399
1400 for (i = 0; i < 4; i++) {
1401
1402 /* Block on cmd ready and write CMD register */
1403 cmd->cmd = DST_CRCI_NAND_CMD;
1404 cmd->src = paddr(&data->sfcmd[3+i]);
1405 cmd->dst = NAND_SFLASHC_CMD;
1406 cmd->len = 4;
1407 cmd++;
1408
1409 /* Write the MACRO1 register */
1410 cmd->cmd = 0;
1411 cmd->src = paddr(&data->macro[i]);
1412 cmd->dst = NAND_MACRO1_REG;
1413 cmd->len = 4;
1414 cmd++;
1415
1416 /* Kick the execute command */
1417 cmd->cmd = 0;
1418 cmd->src = paddr(&data->sfexec);
1419 cmd->dst = NAND_SFLASHC_EXEC_CMD;
1420 cmd->len = 4;
1421 cmd++;
1422
1423 /* Block on data rdy, & read status register */
1424 cmd->cmd = SRC_CRCI_NAND_DATA;
1425 cmd->src = NAND_SFLASHC_STATUS;
1426 cmd->dst = paddr(&data->sfstat[3+i]);
1427 cmd->len = 4;
1428 cmd++;
1429
1430 /* Transfer nand ctlr buf contents to usr buf */
1431 cmd->cmd = 0;
1432 cmd->src = NAND_FLASH_BUFFER;
1433 cmd->dst = curr_addr;
1434 cmd->len = 512;
1435 curr_addr += 512;
1436 cmd++;
1437 }
1438 }
1439
Shashank Mittalad3d05c2009-11-19 15:53:57 -08001440 /* Read oob bytes in Raw Mode */
1441 if (raw_mode == 1)
1442 {
1443 /* Block on cmd ready and write CMD register */
1444 cmd->cmd = DST_CRCI_NAND_CMD;
1445 cmd->src = paddr(&data->sfcmd[7]);
1446 cmd->dst = NAND_SFLASHC_CMD;
1447 cmd->len = 4;
1448 cmd++;
1449
1450 /* Write the MACRO1 register */
1451 cmd->cmd = 0;
1452 cmd->src = paddr(&data->macro[4]);
1453 cmd->dst = NAND_MACRO1_REG;
1454 cmd->len = 4;
1455 cmd++;
1456
1457 /* Kick the execute command */
1458 cmd->cmd = 0;
1459 cmd->src = paddr(&data->sfexec);
1460 cmd->dst = NAND_SFLASHC_EXEC_CMD;
1461 cmd->len = 4;
1462 cmd++;
1463
1464 /* Block on data rdy, & read status register */
1465 cmd->cmd = SRC_CRCI_NAND_DATA;
1466 cmd->src = NAND_SFLASHC_STATUS;
1467 cmd->dst = paddr(&data->sfstat[7]);
1468 cmd->len = 4;
1469 cmd++;
1470
1471 /* Transfer nand ctlr buf contents to usr buf */
1472 cmd->cmd = 0;
1473 cmd->src = NAND_FLASH_BUFFER;
1474 cmd->dst = curr_addr;
1475 cmd->len = 64;
1476 curr_addr += 64;
1477 cmd++;
1478 }
1479
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001480 /*************************************************************/
1481 /* Restore the necessary registers to proper values */
1482 /*************************************************************/
1483
1484 /* Block on cmd ready and write CMD register */
1485 cmd->cmd = DST_CRCI_NAND_CMD;
1486 cmd->src = paddr(&data->sfcmd[8]);
1487 cmd->dst = NAND_SFLASHC_CMD;
1488 cmd->len = 4;
1489 cmd++;
1490
1491 /* Kick the execute command */
1492 cmd->cmd = 0;
1493 cmd->src = paddr(&data->sfexec);
1494 cmd->dst = NAND_SFLASHC_EXEC_CMD;
1495 cmd->len = 4;
1496 cmd++;
1497
1498 /* Block on data ready, and read the status register */
1499 cmd->cmd = SRC_CRCI_NAND_DATA | CMD_OCU | CMD_LC;
1500 cmd->src = NAND_SFLASHC_STATUS;
1501 cmd->dst = paddr(&data->sfstat[8]);
1502 cmd->len = 4;
1503 cmd++;
1504
1505
1506 ptr[0] = (paddr(cmdlist) >> 3) | CMD_PTR_LP;
1507
1508 dmov_exec_cmdptr(DMOV_NAND_CHAN, ptr);
1509
1510
1511 ecc_status = (data->data3 >> 16) &
1512 0x0000FFFF;
1513 interrupt_status = (data->data4 >> 0) &
1514 0x0000FFFF;
1515 controller_status = (data->data4 >> 16) &
1516 0x0000FFFF;
1517
1518#if VERBOSE
1519 dprintf(INFO, "\n%s: sflash status %x %x %x %x %x %x %x"
1520 "%x %x\n", __func__,
1521 data->sfstat[0],
1522 data->sfstat[1],
1523 data->sfstat[2],
1524 data->sfstat[3],
1525 data->sfstat[4],
1526 data->sfstat[5],
1527 data->sfstat[6],
1528 data->sfstat[7]);
1529
1530 dprintf(INFO, "%s: controller_status = %x\n", __func__,
1531 controller_status);
1532 dprintf(INFO, "%s: interrupt_status = %x\n", __func__,
1533 interrupt_status);
1534 dprintf(INFO, "%s: ecc_status = %x\n", __func__,
1535 ecc_status);
1536#endif
1537 /* Check for errors, protection violations etc */
1538 if ((controller_status != 0)
1539 || (data->sfstat[0] & 0x110)
1540 || (data->sfstat[1] & 0x110)
1541 || (data->sfstat[2] & 0x110)
1542 || ((data->sfstat[3] & 0x110) &&
1543 (addr))
1544 || ((data->sfstat[4] & 0x110) &&
1545 (addr))
1546 || ((data->sfstat[5] & 0x110) &&
1547 (addr))
1548 || ((data->sfstat[6] & 0x110) &&
1549 (addr))) {
1550 dprintf(INFO, "%s: ECC/MPU/OP error\n", __func__);
1551 return -1;
1552 }
1553
1554#if VERBOSE
1555 dprintf(INFO, "read page %d: status: %x %x %x %x\n",
1556 page, data[5], data[6], data[7], data[8]);
1557 for(n = 0; n < 4; n++) {
1558 ptr = (unsigned*)(addr + 512 * n);
1559 dprintf(INFO, "data%d: %x %x %x %x\n", n, ptr[0], ptr[1], ptr[2], ptr[3]);
1560 ptr = (unsigned*)(spareaddr + 16 * n);
1561 dprintf(INFO, "spare data%d %x %x %x %x\n", n, ptr[0], ptr[1], ptr[2], ptr[3]);
1562 }
1563#endif
1564
1565 return 0;
1566}
1567
1568
1569struct data_onenand_write {
1570 unsigned sfbcfg;
1571 unsigned sfcmd[9];
1572 unsigned sfexec;
1573 unsigned sfstat[9];
1574 unsigned addr0;
1575 unsigned addr1;
1576 unsigned addr2;
1577 unsigned addr3;
1578 unsigned addr4;
1579 unsigned addr5;
1580 unsigned addr6;
1581 unsigned data0;
1582 unsigned data1;
1583 unsigned data2;
1584 unsigned data3;
1585 unsigned data4;
1586 unsigned data5;
1587 unsigned data6;
1588 unsigned macro[5];
1589};
1590
1591static int _flash_onenand_write_page(dmov_s *cmdlist, unsigned *ptrlist,
1592 unsigned page, const void *_addr,
Shashank Mittald0c836d2009-11-20 10:31:18 -08001593 const void *_spareaddr, unsigned raw_mode)
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001594{
1595 dmov_s *cmd = cmdlist;
1596 unsigned *ptr = ptrlist;
1597 struct data_onenand_write *data = (void*) (ptrlist + 4);
1598 unsigned addr = (unsigned) _addr;
1599 unsigned addr_curr = (unsigned) _addr;
1600 char * spareaddr = (char *) _spareaddr;
1601 unsigned i, j, k;
1602
Shashank Mittaldcc2e352009-11-19 19:11:16 -08001603 unsigned erasesize = (flash_pagesize<<6);
1604 unsigned writesize = flash_pagesize;
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001605
Shashank Mittaldcc2e352009-11-19 19:11:16 -08001606 unsigned onenand_startaddr1 = (page * flash_pagesize) / erasesize;
1607 unsigned onenand_startaddr8 = (((unsigned)(page * flash_pagesize) &
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001608 (erasesize-1)) / writesize) << 2;
1609 unsigned onenand_startaddr2 = DEVICE_BUFFERRAM_0 << 15;
1610 unsigned onenand_startbuffer = DATARAM0_0 << 8;
Shashank Mittald0c836d2009-11-20 10:31:18 -08001611 unsigned onenand_sysconfig1 = (raw_mode == 1) ? ONENAND_SYSCFG1_ECCDIS :\
1612 ONENAND_SYSCFG1_ECCENA;
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001613
1614 unsigned controller_status;
1615 unsigned interrupt_status;
1616 unsigned ecc_status;
1617
1618 char flash_oob[64];
1619
1620 unsigned oobfree_offset[8] = {2, 14, 18, 30, 34, 46, 50, 62};
1621 unsigned oobfree_length[8] = {3, 2, 3, 2, 3, 2, 3, 2};
1622
1623 for (i = 0; i < 64; i++)
1624 flash_oob[i] = 0xFF;
1625
1626 data->sfbcfg = SFLASH_BCFG;
1627 data->sfcmd[0] = SFLASH_PREPCMD(256, 0, 0,
1628 NAND_SFCMD_CMDXS,
1629 NAND_SFCMD_ASYNC,
1630 NAND_SFCMD_DATWR);
1631 data->sfcmd[1] = SFLASH_PREPCMD(256, 0, 0,
1632 NAND_SFCMD_CMDXS,
1633 NAND_SFCMD_ASYNC,
1634 NAND_SFCMD_DATWR);
1635 data->sfcmd[2] = SFLASH_PREPCMD(256, 0, 0,
1636 NAND_SFCMD_CMDXS,
1637 NAND_SFCMD_ASYNC,
1638 NAND_SFCMD_DATWR);
1639 data->sfcmd[3] = SFLASH_PREPCMD(256, 0, 0,
1640 NAND_SFCMD_CMDXS,
1641 NAND_SFCMD_ASYNC,
1642 NAND_SFCMD_DATWR);
1643 data->sfcmd[4] = SFLASH_PREPCMD(32, 0, 0,
1644 NAND_SFCMD_CMDXS,
1645 NAND_SFCMD_ASYNC,
1646 NAND_SFCMD_DATWR);
1647 data->sfcmd[5] = SFLASH_PREPCMD(7, 0, 0,
1648 NAND_SFCMD_CMDXS,
1649 NAND_SFCMD_ASYNC,
1650 NAND_SFCMD_REGWR);
1651 data->sfcmd[6] = SFLASH_PREPCMD(0, 0, 32,
1652 NAND_SFCMD_CMDXS,
1653 NAND_SFCMD_ASYNC,
1654 NAND_SFCMD_INTHI);
1655 data->sfcmd[7] = SFLASH_PREPCMD(3, 7, 0,
1656 NAND_SFCMD_DATXS,
1657 NAND_SFCMD_ASYNC,
1658 NAND_SFCMD_REGRD);
1659 data->sfcmd[8] = SFLASH_PREPCMD(4, 10, 0,
1660 NAND_SFCMD_CMDXS,
1661 NAND_SFCMD_ASYNC,
1662 NAND_SFCMD_REGWR);
1663 data->sfexec = 1;
1664
1665 data->sfstat[0] = CLEAN_DATA_32;
1666 data->sfstat[1] = CLEAN_DATA_32;
1667 data->sfstat[2] = CLEAN_DATA_32;
1668 data->sfstat[3] = CLEAN_DATA_32;
1669 data->sfstat[4] = CLEAN_DATA_32;
1670 data->sfstat[5] = CLEAN_DATA_32;
1671 data->sfstat[6] = CLEAN_DATA_32;
1672 data->sfstat[7] = CLEAN_DATA_32;
1673 data->sfstat[8] = CLEAN_DATA_32;
1674 data->addr0 = (ONENAND_INTERRUPT_STATUS << 16) |
1675 (ONENAND_SYSTEM_CONFIG_1);
1676 data->addr1 = (ONENAND_START_ADDRESS_8 << 16) |
1677 (ONENAND_START_ADDRESS_1);
1678 data->addr2 = (ONENAND_START_BUFFER << 16) |
1679 (ONENAND_START_ADDRESS_2);
1680 data->addr3 = (ONENAND_ECC_STATUS << 16) |
1681 (ONENAND_COMMAND);
1682 data->addr4 = (ONENAND_CONTROLLER_STATUS << 16) |
1683 (ONENAND_INTERRUPT_STATUS);
1684 data->addr5 = (ONENAND_INTERRUPT_STATUS << 16) |
1685 (ONENAND_SYSTEM_CONFIG_1);
1686 data->addr6 = (ONENAND_START_ADDRESS_3 << 16) |
1687 (ONENAND_START_ADDRESS_1);
1688 data->data0 = (ONENAND_CLRINTR << 16) |
1689 (onenand_sysconfig1);
1690 data->data1 = (onenand_startaddr8 << 16) |
1691 (onenand_startaddr1);
1692 data->data2 = (onenand_startbuffer << 16) |
1693 (onenand_startaddr2);
1694 data->data3 = (CLEAN_DATA_16 << 16) |
1695 (ONENAND_CMDPROGSPARE);
1696 data->data3 = (CLEAN_DATA_16 << 16) |
1697 (ONENAND_CMDPROGSPARE);
1698 data->data4 = (CLEAN_DATA_16 << 16) |
1699 (CLEAN_DATA_16);
1700 data->data5 = (ONENAND_CLRINTR << 16) |
1701 (ONENAND_SYSCFG1_ECCENA);
1702 data->data6 = (ONENAND_STARTADDR3_RES << 16) |
1703 (ONENAND_STARTADDR1_RES);
1704 data->macro[0] = 0x0200;
1705 data->macro[1] = 0x0300;
1706 data->macro[2] = 0x0400;
1707 data->macro[3] = 0x0500;
1708 data->macro[4] = 0x8010;
1709
1710
1711 /*************************************************************/
1712 /* Write the data ram area in the onenand buffer ram */
1713 /*************************************************************/
1714
1715 /* Enable and configure the SFlash controller */
1716 cmd->cmd = 0 | CMD_OCB;
1717 cmd->src = paddr(&data->sfbcfg);
1718 cmd->dst = NAND_SFLASHC_BURST_CFG;
1719 cmd->len = 4;
1720 cmd++;
1721
1722 if (addr) {
1723 data->data3 = (CLEAN_DATA_16 << 16) |
1724 (ONENAND_CMDPROG);
1725
1726 for (i = 0; i < 4; i++) {
1727
1728 /* Block on cmd ready and write CMD register */
1729 cmd->cmd = DST_CRCI_NAND_CMD;
1730 cmd->src = paddr(&data->sfcmd[i]);
1731 cmd->dst = NAND_SFLASHC_CMD;
1732 cmd->len = 4;
1733 cmd++;
1734
1735 /* Trnsfr usr buf contents to nand ctlr buf */
1736 cmd->cmd = 0;
1737 cmd->src = paddr(addr_curr);
1738 cmd->dst = NAND_FLASH_BUFFER;
1739 cmd->len = 512;
Shashank Mittald0c836d2009-11-20 10:31:18 -08001740 if(!raw_mode)
1741 addr_curr += 512;
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001742 cmd++;
1743
1744 /* Write the MACRO1 register */
1745 cmd->cmd = 0;
1746 cmd->src = paddr(&data->macro[i]);
1747 cmd->dst = NAND_MACRO1_REG;
1748 cmd->len = 4;
1749 cmd++;
1750
1751 /* Kick the execute command */
1752 cmd->cmd = 0;
1753 cmd->src = paddr(&data->sfexec);
1754 cmd->dst = NAND_SFLASHC_EXEC_CMD;
1755 cmd->len = 4;
1756 cmd++;
1757
1758 /* Block on data rdy, & read status register */
1759 cmd->cmd = SRC_CRCI_NAND_DATA;
1760 cmd->src = NAND_SFLASHC_STATUS;
1761 cmd->dst = paddr(&data->sfstat[i]);
1762 cmd->len = 4;
1763 cmd++;
1764
1765 }
1766 }
1767
1768 /* Block on cmd ready and write CMD register */
1769 cmd->cmd = DST_CRCI_NAND_CMD;
1770 cmd->src = paddr(&data->sfcmd[4]);
1771 cmd->dst = NAND_SFLASHC_CMD;
1772 cmd->len = 4;
1773 cmd++;
1774
1775 if (spareaddr)
1776 {
1777 // Auto mode
1778 for (i = 0, k = 0; i < 8; i++) {
1779 for (j = 0; j < oobfree_length[i]; j++) {
1780 flash_oob[j+oobfree_offset[i]] = spareaddr[k];
1781 k++;
1782 }
1783 }
1784
1785 cmd->cmd = 0;
1786 cmd->src = paddr(&flash_oob);
1787 cmd->dst = NAND_FLASH_BUFFER;
1788 cmd->len = 64;
1789 cmd++;
1790 }
1791
Shashank Mittald0c836d2009-11-20 10:31:18 -08001792 if (raw_mode){
1793 cmd->cmd = 0;
1794 cmd->src = paddr(addr_curr);
1795 cmd->dst = NAND_FLASH_BUFFER;
1796 cmd->len = 64;
1797 cmd++;
1798 }
1799
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001800 /* Write the MACRO1 register */
1801 cmd->cmd = 0;
1802 cmd->src = paddr(&data->macro[4]);
1803 cmd->dst = NAND_MACRO1_REG;
1804 cmd->len = 4;
1805 cmd++;
1806
1807 /* Kick the execute command */
1808 cmd->cmd = 0;
1809 cmd->src = paddr(&data->sfexec);
1810 cmd->dst = NAND_SFLASHC_EXEC_CMD;
1811 cmd->len = 4;
1812 cmd++;
1813
1814 /* Block on data ready, and read the status register */
1815 cmd->cmd = SRC_CRCI_NAND_DATA;
1816 cmd->src = NAND_SFLASHC_STATUS;
1817 cmd->dst = paddr(&data->sfstat[4]);
1818 cmd->len = 4;
1819 cmd++;
1820
1821 /*************************************************************/
1822 /* Write necessary address registers in the onenand device */
1823 /*************************************************************/
1824
1825 /* Block on cmd ready and write CMD register */
1826 cmd->cmd = DST_CRCI_NAND_CMD;
1827 cmd->src = paddr(&data->sfcmd[5]);
1828 cmd->dst = NAND_SFLASHC_CMD;
1829 cmd->len = 4;
1830 cmd++;
1831
1832 /* Write the ADDR0 and ADDR1 registers */
1833 cmd->cmd = 0;
1834 cmd->src = paddr(&data->addr0);
1835 cmd->dst = NAND_ADDR0;
1836 cmd->len = 8;
1837 cmd++;
1838
1839 /* Write the ADDR2 ADDR3 ADDR4 ADDR5 registers */
1840 cmd->cmd = 0;
1841 cmd->src = paddr(&data->addr2);
1842 cmd->dst = NAND_ADDR2;
1843 cmd->len = 16;
1844 cmd++;
1845
1846 /* Write the ADDR6 registers */
1847 cmd->cmd = 0;
1848 cmd->src = paddr(&data->addr6);
1849 cmd->dst = NAND_ADDR6;
1850 cmd->len = 4;
1851 cmd++;
1852
1853 /* Write the GENP0, GENP1, GENP2, GENP3 registers */
1854 cmd->cmd = 0;
1855 cmd->src = paddr(&data->data0);
1856 cmd->dst = NAND_GENP_REG0;
1857 cmd->len = 16;
1858 cmd++;
1859
1860 /* Write the FLASH_DEV_CMD4,5,6 registers */
1861 cmd->cmd = 0;
1862 cmd->src = paddr(&data->data4);
1863 cmd->dst = NAND_DEV_CMD4;
1864 cmd->len = 12;
1865 cmd++;
1866
1867 /* Kick the execute command */
1868 cmd->cmd = 0;
1869 cmd->src = paddr(&data->sfexec);
1870 cmd->dst = NAND_SFLASHC_EXEC_CMD;
1871 cmd->len = 4;
1872 cmd++;
1873
1874 /* Block on data ready, and read the status register */
1875 cmd->cmd = SRC_CRCI_NAND_DATA;
1876 cmd->src = NAND_SFLASHC_STATUS;
1877 cmd->dst = paddr(&data->sfstat[5]);
1878 cmd->len = 4;
1879 cmd++;
1880
1881 /*************************************************************/
1882 /* Wait for the interrupt from the Onenand device controller */
1883 /*************************************************************/
1884
1885 /* Block on cmd ready and write CMD register */
1886 cmd->cmd = DST_CRCI_NAND_CMD;
1887 cmd->src = paddr(&data->sfcmd[6]);
1888 cmd->dst = NAND_SFLASHC_CMD;
1889 cmd->len = 4;
1890 cmd++;
1891
1892 /* Kick the execute command */
1893 cmd->cmd = 0;
1894 cmd->src = paddr(&data->sfexec);
1895 cmd->dst = NAND_SFLASHC_EXEC_CMD;
1896 cmd->len = 4;
1897 cmd++;
1898
1899 /* Block on data ready, and read the status register */
1900 cmd->cmd = SRC_CRCI_NAND_DATA;
1901 cmd->src = NAND_SFLASHC_STATUS;
1902 cmd->dst = paddr(&data->sfstat[6]);
1903 cmd->len = 4;
1904 cmd++;
1905
1906 /*************************************************************/
1907 /* Read necessary status registers from the onenand device */
1908 /*************************************************************/
1909
1910 /* Block on cmd ready and write CMD register */
1911 cmd->cmd = DST_CRCI_NAND_CMD;
1912 cmd->src = paddr(&data->sfcmd[7]);
1913 cmd->dst = NAND_SFLASHC_CMD;
1914 cmd->len = 4;
1915 cmd++;
1916
1917 /* Kick the execute command */
1918 cmd->cmd = 0;
1919 cmd->src = paddr(&data->sfexec);
1920 cmd->dst = NAND_SFLASHC_EXEC_CMD;
1921 cmd->len = 4;
1922 cmd++;
1923
1924 /* Block on data ready, and read the status register */
1925 cmd->cmd = SRC_CRCI_NAND_DATA;
1926 cmd->src = NAND_SFLASHC_STATUS;
1927 cmd->dst = paddr(&data->sfstat[7]);
1928 cmd->len = 4;
1929 cmd++;
1930
1931 /* Read the GENP3 register */
1932 cmd->cmd = 0;
1933 cmd->src = NAND_GENP_REG3;
1934 cmd->dst = paddr(&data->data3);
1935 cmd->len = 4;
1936 cmd++;
1937
1938 /* Read the DEVCMD4 register */
1939 cmd->cmd = 0;
1940 cmd->src = NAND_DEV_CMD4;
1941 cmd->dst = paddr(&data->data4);
1942 cmd->len = 4;
1943 cmd++;
1944
1945
1946 /*************************************************************/
1947 /* Restore the necessary registers to proper values */
1948 /*************************************************************/
1949
1950 /* Block on cmd ready and write CMD register */
1951 cmd->cmd = DST_CRCI_NAND_CMD;
1952 cmd->src = paddr(&data->sfcmd[8]);
1953 cmd->dst = NAND_SFLASHC_CMD;
1954 cmd->len = 4;
1955 cmd++;
1956
1957 /* Kick the execute command */
1958 cmd->cmd = 0;
1959 cmd->src = paddr(&data->sfexec);
1960 cmd->dst = NAND_SFLASHC_EXEC_CMD;
1961 cmd->len = 4;
1962 cmd++;
1963
1964 /* Block on data ready, and read the status register */
1965 cmd->cmd = SRC_CRCI_NAND_DATA | CMD_OCU | CMD_LC;
1966 cmd->src = NAND_SFLASHC_STATUS;
1967 cmd->dst = paddr(&data->sfstat[8]);
1968 cmd->len = 4;
1969 cmd++;
1970
1971
1972 ptr[0] = (paddr(cmdlist) >> 3) | CMD_PTR_LP;
1973
1974 dmov_exec_cmdptr(DMOV_NAND_CHAN, ptr);
1975
1976 ecc_status = (data->data3 >> 16) & 0x0000FFFF;
1977 interrupt_status = (data->data4 >> 0)&0x0000FFFF;
1978 controller_status = (data->data4 >> 16)&0x0000FFFF;
1979
1980#if VERBOSE
1981 dprintf(INFO, "\n%s: sflash status %x %x %x %x %x %x %x %x %x\n", __func__,
1982 data->sfstat[0],
1983 data->sfstat[1],
1984 data->sfstat[2],
1985 data->sfstat[3],
1986 data->sfstat[4],
1987 data->sfstat[5],
1988 data->sfstat[6],
1989 data->sfstat[7],
1990 data->sfstat[8]);
1991
1992 dprintf(INFO, "%s: controller_status = %x\n", __func__,
1993 controller_status);
1994 dprintf(INFO, "%s: interrupt_status = %x\n", __func__,
1995 interrupt_status);
1996 dprintf(INFO, "%s: ecc_status = %x\n", __func__,
1997 ecc_status);
1998#endif
1999 /* Check for errors, protection violations etc */
2000 if ((controller_status != 0)
2001 || (data->sfstat[5] & 0x110)
2002 || (data->sfstat[6] & 0x110)
2003 || (data->sfstat[7] & 0x110)
2004 || (data->sfstat[8] & 0x110)
2005 || ((data->sfstat[0] & 0x110) &&
2006 (addr))
2007 || ((data->sfstat[1] & 0x110) &&
2008 (addr))
2009 || ((data->sfstat[2] & 0x110) &&
2010 (addr))
2011 || ((data->sfstat[3] & 0x110) &&
2012 (addr))) {
2013 dprintf(CRITICAL, "%s: ECC/MPU/OP error\n", __func__);
2014 return -1;
2015 }
2016
2017
2018 return 0;
2019}
Shashank Mittald0c836d2009-11-20 10:31:18 -08002020
2021static int flash_onenand_mark_badblock(dmov_s *cmdlist, unsigned *ptrlist, unsigned page)
2022{
2023 memset(empty_buf,0,528);
2024 /* Going to first page of the block */
2025 if(page & 63)
2026 page = page - (page & 63);
2027 return _flash_onenand_write_page(cmdlist, ptrlist, page, empty_buf, 0, 1);
2028}
2029
2030static int flash_mark_badblock(dmov_s *cmdlist, unsigned *ptrlist, unsigned page)
2031{
2032 switch(flash_info.type) {
2033 case FLASH_8BIT_NAND_DEVICE:
2034 case FLASH_16BIT_NAND_DEVICE:
2035 return flash_nand_mark_badblock(cmdlist, ptrlist, page);
2036 case FLASH_ONENAND_DEVICE:
2037 return flash_onenand_mark_badblock(cmdlist, ptrlist, page);
2038 default:
2039 return -1;
2040 }
2041}
2042
2043
Shashank Mittalc20b5a12009-11-18 19:35:30 -08002044/* Wrapper functions */
2045static void flash_read_id(dmov_s *cmdlist, unsigned *ptrlist)
2046{
2047 int dev_found = 0;
2048 unsigned index;
2049
2050 // Try to read id
2051 flash_nand_read_id(cmdlist, ptrlist);
2052 // Check if we support the device
2053 for (index=1;
2054 index < (sizeof(supported_flash)/sizeof(struct flash_identification));
2055 index++)
2056 {
2057 if ((flash_info.id & supported_flash[index].mask) ==
2058 (supported_flash[index].flash_id &
2059 (supported_flash[index].mask))) {
2060 dev_found = 1;
2061 break;
2062 }
2063 }
2064
2065 if(!dev_found) {
2066 flash_onenand_read_id(cmdlist, ptrlist);
2067 for (index=1;
2068 index < (sizeof(supported_flash)/sizeof(struct flash_identification));
2069 index++)
2070 {
2071 if ((flash_info.id & supported_flash[index].mask) ==
2072 (supported_flash[index].flash_id &
2073 (supported_flash[index].mask))) {
2074 dev_found = 1;
2075 break;
2076 }
2077 }
2078 }
2079
2080
2081
2082 if(dev_found) {
2083 if (supported_flash[index].widebus)
2084 flash_info.type = FLASH_16BIT_NAND_DEVICE;
2085 else
2086 flash_info.type = FLASH_8BIT_NAND_DEVICE;
2087 if (supported_flash[index].onenand)
2088 flash_info.type = FLASH_ONENAND_DEVICE;
2089 flash_info.page_size = supported_flash[index].pagesize;
Shashank Mittaldcc2e352009-11-19 19:11:16 -08002090 flash_pagesize = flash_info.page_size;
Shashank Mittalc20b5a12009-11-18 19:35:30 -08002091 flash_info.block_size = supported_flash[index].blksize;
2092 flash_info.spare_size = supported_flash[index].oobsize;
2093 if (flash_info.block_size && flash_info.page_size)
2094 {
2095 flash_info.num_blocks = supported_flash[index].density;
2096 flash_info.num_blocks /= (flash_info.block_size * flash_info.page_size);
2097 }
2098 else
2099 {
2100 flash_info.num_blocks = 0;
2101 }
2102 ASSERT(flash_info.num_blocks);
2103 return;
2104 }
2105
2106 // Assume 8 bit nand device for backward compatability
2107 if (dev_found == 0) {
2108 dprintf(INFO, "Device not supported. Assuming 8 bit NAND device\n");
2109 flash_info.type = FLASH_8BIT_NAND_DEVICE;
2110 }
2111 dprintf(INFO, "nandid: 0x%x maker=0x%02x device=0x%02x page_size=%d\n",
2112 flash_info.id, flash_info.vendor, flash_info.device,
2113 flash_info.page_size);
2114 dprintf(INFO, " spare_size=%d block_size=%d num_blocks=%d\n",
2115 flash_info.spare_size, flash_info.block_size,
2116 flash_info.num_blocks);
2117}
2118
2119static int flash_erase_block(dmov_s *cmdlist, unsigned *ptrlist, unsigned page)
2120{
2121 switch(flash_info.type) {
2122 case FLASH_8BIT_NAND_DEVICE:
2123 case FLASH_16BIT_NAND_DEVICE:
2124 return flash_nand_erase_block(cmdlist, ptrlist, page);
2125 case FLASH_ONENAND_DEVICE:
2126 return flash_onenand_erase_block(cmdlist, ptrlist, page);
2127 default:
2128 return -1;
2129 }
2130}
2131
2132static int _flash_read_page(dmov_s *cmdlist, unsigned *ptrlist,
2133 unsigned page, void *_addr, void *_spareaddr)
2134{
2135 switch(flash_info.type) {
2136 case FLASH_8BIT_NAND_DEVICE:
2137 case FLASH_16BIT_NAND_DEVICE:
2138 return _flash_nand_read_page(cmdlist, ptrlist, page, _addr, _spareaddr);
2139 case FLASH_ONENAND_DEVICE:
Shashank Mittalad3d05c2009-11-19 15:53:57 -08002140 return _flash_onenand_read_page(cmdlist, ptrlist, page, _addr, _spareaddr, 0);
Shashank Mittalc20b5a12009-11-18 19:35:30 -08002141 default:
2142 return -1;
2143 }
2144}
2145
Shashank Mittalad3d05c2009-11-19 15:53:57 -08002146static int _flash_block_isbad(dmov_s *cmdlist, unsigned *ptrlist, unsigned page)
2147{
2148 switch(flash_info.type) {
2149 case FLASH_8BIT_NAND_DEVICE:
2150 case FLASH_16BIT_NAND_DEVICE:
2151 return flash_nand_block_isbad(cmdlist, ptrlist, page);
2152 case FLASH_ONENAND_DEVICE:
2153 return flash_onenand_block_isbad(cmdlist, ptrlist, page);
2154 default:
2155 return -1;
2156 }
2157}
Shashank Mittalc20b5a12009-11-18 19:35:30 -08002158
2159static int _flash_write_page(dmov_s *cmdlist, unsigned *ptrlist,
2160 unsigned page, const void *_addr,
2161 const void *_spareaddr)
2162{
2163 switch(flash_info.type) {
2164 case FLASH_8BIT_NAND_DEVICE:
2165 case FLASH_16BIT_NAND_DEVICE:
Shashank Mittald0c836d2009-11-20 10:31:18 -08002166 return _flash_nand_write_page(cmdlist, ptrlist, page, _addr, _spareaddr, 0);
Shashank Mittalc20b5a12009-11-18 19:35:30 -08002167 case FLASH_ONENAND_DEVICE:
Shashank Mittald0c836d2009-11-20 10:31:18 -08002168 return _flash_onenand_write_page(cmdlist, ptrlist, page, _addr, _spareaddr, 0);
Shashank Mittalc20b5a12009-11-18 19:35:30 -08002169 default:
2170 return -1;
2171 }
2172}
2173
Dima Zavin03cf4312009-01-23 16:38:30 -08002174static unsigned *flash_ptrlist;
2175static dmov_s *flash_cmdlist;
Dima Zavin03cf4312009-01-23 16:38:30 -08002176
2177static struct ptable *flash_ptable = NULL;
2178
Dima Zavine5f64352009-03-02 16:04:20 -08002179void flash_init(void)
Dima Zavin03cf4312009-01-23 16:38:30 -08002180{
Dima Zavine5f64352009-03-02 16:04:20 -08002181 ASSERT(flash_ptable == NULL);
Dima Zavin03cf4312009-01-23 16:38:30 -08002182
2183 flash_ptrlist = memalign(32, 1024);
2184 flash_cmdlist = memalign(32, 1024);
Ajay Dudani232ce812009-12-02 00:14:11 -08002185 flash_data = memalign(32, 4096 + 128);
2186 flash_spare = memalign(32, 128);
Dima Zavin03cf4312009-01-23 16:38:30 -08002187
Dima Zavin03cf4312009-01-23 16:38:30 -08002188 flash_read_id(flash_cmdlist, flash_ptrlist);
Shashank Mittal83d16d02009-11-18 16:54:42 -08002189 if((FLASH_8BIT_NAND_DEVICE == flash_info.type)
2190 ||(FLASH_16BIT_NAND_DEVICE == flash_info.type)) {
Shashank Mittalc20b5a12009-11-18 19:35:30 -08002191 if(flash_nand_read_config(flash_cmdlist, flash_ptrlist)) {
Shashank Mittal83d16d02009-11-18 16:54:42 -08002192 dprintf(CRITICAL, "ERROR: could not read CFG0/CFG1 state\n");
2193 ASSERT(0);
2194 }
2195 }
Dima Zavin03cf4312009-01-23 16:38:30 -08002196}
2197
2198struct ptable *flash_get_ptable(void)
2199{
2200 return flash_ptable;
2201}
2202
Dima Zavine5f64352009-03-02 16:04:20 -08002203void flash_set_ptable(struct ptable *new_ptable)
2204{
2205 ASSERT(flash_ptable == NULL && new_ptable != NULL);
2206 flash_ptable = new_ptable;
2207}
2208
Dima Zavinca337f52009-03-02 16:41:44 -08002209struct flash_info *flash_get_info(void)
2210{
2211 return &flash_info;
2212}
2213
Dima Zavin03cf4312009-01-23 16:38:30 -08002214int flash_erase(struct ptentry *ptn)
2215{
2216 unsigned block = ptn->start;
2217 unsigned count = ptn->length;
2218
2219 while(count-- > 0) {
2220 if(flash_erase_block(flash_cmdlist, flash_ptrlist, block * 64)) {
2221 dprintf(INFO, "cannot erase @ %d (bad block?)\n", block);
2222 }
2223 block++;
2224 }
2225 return 0;
2226}
2227
2228int flash_read_ext(struct ptentry *ptn, unsigned extra_per_page,
Shashank Mittalc20b5a12009-11-18 19:35:30 -08002229 unsigned offset, void *data, unsigned bytes)
Dima Zavin03cf4312009-01-23 16:38:30 -08002230{
Shashank Mittaldcc2e352009-11-19 19:11:16 -08002231 unsigned page = (ptn->start * 64) + (offset / flash_pagesize);
Dima Zavin03cf4312009-01-23 16:38:30 -08002232 unsigned lastpage = (ptn->start + ptn->length) * 64;
Shashank Mittaldcc2e352009-11-19 19:11:16 -08002233 unsigned count = (bytes + flash_pagesize - 1 + extra_per_page) / (flash_pagesize + extra_per_page);
Dima Zavin03cf4312009-01-23 16:38:30 -08002234 unsigned *spare = (unsigned*) flash_spare;
2235 unsigned errors = 0;
2236 unsigned char *image = data;
Shashank Mittalad3d05c2009-11-19 15:53:57 -08002237 unsigned current_block = (page - (page & 63)) >> 6;
2238 unsigned start_block = ptn->start;
2239 int result = 0;
2240 int isbad = 0;
Dima Zavin03cf4312009-01-23 16:38:30 -08002241
Shashank Mittaldcc2e352009-11-19 19:11:16 -08002242 if(offset & (flash_pagesize - 1))
Dima Zavin03cf4312009-01-23 16:38:30 -08002243 return -1;
2244
Shashank Mittalad3d05c2009-11-19 15:53:57 -08002245 // Adjust page offset based on number of bad blocks from start to current page
2246 while (start_block < current_block) {
2247 isbad = _flash_block_isbad(flash_cmdlist, flash_ptrlist, start_block*64);
2248 if (isbad)
2249 page += 64;
2250
2251 start_block++;
2252 }
2253
Dima Zavin03cf4312009-01-23 16:38:30 -08002254 while(page < lastpage) {
2255 if(count == 0) {
2256 dprintf(INFO, "flash_read_image: success (%d errors)\n", errors);
2257 return 0;
2258 }
2259
Shashank Mittalad3d05c2009-11-19 15:53:57 -08002260 result = _flash_read_page(flash_cmdlist, flash_ptrlist, page, image, spare);
2261
2262 if (result == -1) {
2263 // bad page, go to next page
2264 page++;
Dima Zavin03cf4312009-01-23 16:38:30 -08002265 errors++;
2266 continue;
2267 }
Shashank Mittalad3d05c2009-11-19 15:53:57 -08002268 else if (result == -2) {
2269 // bad block, go to next block same offset
2270 page += 64;
2271 errors++;
2272 continue;
2273 }
2274
2275 page++;
Shashank Mittaldcc2e352009-11-19 19:11:16 -08002276 image += flash_pagesize;
Dima Zavin03cf4312009-01-23 16:38:30 -08002277 memcpy(image, spare, extra_per_page);
2278 image += extra_per_page;
2279 count -= 1;
2280 }
2281
2282 /* could not find enough valid pages before we hit the end */
2283 dprintf(INFO, "flash_read_image: failed (%d errors)\n", errors);
2284 return 0xffffffff;
2285}
2286
2287int flash_write(struct ptentry *ptn, unsigned extra_per_page, const void *data,
2288 unsigned bytes)
2289{
2290 unsigned page = ptn->start * 64;
2291 unsigned lastpage = (ptn->start + ptn->length) * 64;
2292 unsigned *spare = (unsigned*) flash_spare;
2293 const unsigned char *image = data;
Shashank Mittaldcc2e352009-11-19 19:11:16 -08002294 unsigned wsize = flash_pagesize + extra_per_page;
Dima Zavin03cf4312009-01-23 16:38:30 -08002295 unsigned n;
2296 int r;
2297
2298 for(n = 0; n < 16; n++) spare[n] = 0xffffffff;
2299
2300 while(bytes > 0) {
2301 if(bytes < wsize) {
2302 dprintf(CRITICAL, "flash_write_image: image undersized (%d < %d)\n", bytes, wsize);
2303 return -1;
2304 }
2305 if(page >= lastpage) {
2306 dprintf(CRITICAL, "flash_write_image: out of space\n");
2307 return -1;
2308 }
2309
2310 if((page & 63) == 0) {
2311 if(flash_erase_block(flash_cmdlist, flash_ptrlist, page)) {
2312 dprintf(INFO, "flash_write_image: bad block @ %d\n", page >> 6);
2313 page += 64;
2314 continue;
2315 }
2316 }
2317
2318 if(extra_per_page) {
Shashank Mittald0c836d2009-11-20 10:31:18 -08002319 r = _flash_write_page(flash_cmdlist, flash_ptrlist, page, image, image + flash_pagesize);
Dima Zavin03cf4312009-01-23 16:38:30 -08002320 } else {
Shashank Mittald0c836d2009-11-20 10:31:18 -08002321 r = _flash_write_page(flash_cmdlist, flash_ptrlist, page, image, spare);
Dima Zavin03cf4312009-01-23 16:38:30 -08002322 }
2323 if(r) {
2324 dprintf(INFO, "flash_write_image: write failure @ page %d (src %d)\n", page, image - (const unsigned char *)data);
2325 image -= (page & 63) * wsize;
2326 bytes += (page & 63) * wsize;
2327 page &= ~63;
2328 if(flash_erase_block(flash_cmdlist, flash_ptrlist, page)) {
2329 dprintf(INFO, "flash_write_image: erase failure @ page %d\n", page);
2330 }
Shashank Mittald0c836d2009-11-20 10:31:18 -08002331 flash_mark_badblock(flash_cmdlist, flash_ptrlist, page);
Dima Zavin03cf4312009-01-23 16:38:30 -08002332 dprintf(INFO, "flash_write_image: restart write @ page %d (src %d)\n", page, image - (const unsigned char *)data);
2333 page += 64;
2334 continue;
2335 }
Shashank Mittald0c836d2009-11-20 10:31:18 -08002336 page++;
Dima Zavin03cf4312009-01-23 16:38:30 -08002337 image += wsize;
2338 bytes -= wsize;
2339 }
2340
2341 /* erase any remaining pages in the partition */
2342 page = (page + 63) & (~63);
2343 while(page < lastpage){
2344 if(flash_erase_block(flash_cmdlist, flash_ptrlist, page)) {
2345 dprintf(INFO, "flash_write_image: bad block @ %d\n", page >> 6);
2346 }
2347 page += 64;
2348 }
2349
2350 dprintf(INFO, "flash_write_image: success\n");
2351 return 0;
2352}
2353
2354#if 0
2355static int flash_read_page(unsigned page, void *data, void *extra)
2356{
2357 return _flash_read_page(flash_cmdlist, flash_ptrlist,
2358 page, data, extra);
2359}
2360#endif
Shashank Mittaldcc2e352009-11-19 19:11:16 -08002361
2362unsigned flash_page_size(void)
2363{
2364 return flash_pagesize;
2365}