blob: 6e5a86f21c5e508aef0833f9ed335f84e814e13b [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*/
Chandan Uddaraju9e5ab962010-01-21 15:36:37 -0800135 {0x6600bcec, 0xFF00FFFF, (512<<20), 1, 4096, (2048<<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;
Murali Palnatic54d13a2010-01-15 19:50:19 +0530326 data[8] = 0x00000020;
327 data[9] = 0x000000C0;
Dima Zavin03cf4312009-01-23 16:38:30 -0800328
329 cmd[0].cmd = DST_CRCI_NAND_CMD | CMD_OCB;
330 cmd[0].src = paddr(&data[0]);
331 cmd[0].dst = NAND_FLASH_CMD;
332 cmd[0].len = 16;
333
334 cmd[1].cmd = 0;
335 cmd[1].src = paddr(&data[6]);
336 cmd[1].dst = NAND_DEV0_CFG0;
337 cmd[1].len = 8;
338
339 cmd[2].cmd = 0;
340 cmd[2].src = paddr(&data[4]);
341 cmd[2].dst = NAND_EXEC_CMD;
342 cmd[2].len = 4;
343
Murali Palnatic54d13a2010-01-15 19:50:19 +0530344 cmd[3].cmd = SRC_CRCI_NAND_DATA;
Dima Zavin03cf4312009-01-23 16:38:30 -0800345 cmd[3].src = NAND_FLASH_STATUS;
346 cmd[3].dst = paddr(&data[5]);
347 cmd[3].len = 4;
348
Murali Palnatic54d13a2010-01-15 19:50:19 +0530349 cmd[4].cmd = 0;
350 cmd[4].src = paddr(&data[8]);
351 cmd[4].dst = NAND_FLASH_STATUS;
352 cmd[4].len = 4;
353
354 cmd[5].cmd = CMD_OCU | CMD_LC;
355 cmd[5].src = paddr(&data[9]);
356 cmd[5].dst = NAND_READ_STATUS;
357 cmd[5].len = 4;
358
Dima Zavin03cf4312009-01-23 16:38:30 -0800359 ptr[0] = (paddr(cmd) >> 3) | CMD_PTR_LP;
360
361 dmov_exec_cmdptr(DMOV_NAND_CHAN, ptr);
362
363#if VERBOSE
364 dprintf(INFO, "status: %x\n", data[5]);
365#endif
366
367 /* we fail if there was an operation error, a mpu error, or the
368 ** erase success bit was not set.
369 */
370 if(data[5] & 0x110) return -1;
371 if(!(data[5] & 0x80)) return -1;
372
373 return 0;
374}
375
376struct data_flash_io {
377 unsigned cmd;
378 unsigned addr0;
379 unsigned addr1;
380 unsigned chipsel;
381 unsigned cfg0;
382 unsigned cfg1;
383 unsigned exec;
384 unsigned ecc_cfg;
385 unsigned ecc_cfg_save;
Murali Palnatic54d13a2010-01-15 19:50:19 +0530386 unsigned clrfstatus;
387 unsigned clrrstatus;
Dima Zavin03cf4312009-01-23 16:38:30 -0800388 struct {
389 unsigned flash_status;
390 unsigned buffer_status;
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800391 } result[8];
Dima Zavin03cf4312009-01-23 16:38:30 -0800392};
393
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800394static int _flash_nand_read_page(dmov_s *cmdlist, unsigned *ptrlist,
395 unsigned page, void *_addr, void *_spareaddr)
Dima Zavin03cf4312009-01-23 16:38:30 -0800396{
397 dmov_s *cmd = cmdlist;
398 unsigned *ptr = ptrlist;
399 struct data_flash_io *data = (void*) (ptrlist + 4);
400 unsigned addr = (unsigned) _addr;
401 unsigned spareaddr = (unsigned) _spareaddr;
402 unsigned n;
Shashank Mittalad3d05c2009-11-19 15:53:57 -0800403 int isbad = 0;
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800404 unsigned cwperpage;
405 cwperpage = (flash_pagesize >> 9);
Shashank Mittalad3d05c2009-11-19 15:53:57 -0800406
407 /* Check for bad block and read only from a good block */
408 isbad = flash_nand_block_isbad(cmdlist, ptrlist, page);
409 if (isbad)
410 return -2;
Dima Zavin03cf4312009-01-23 16:38:30 -0800411
412 data->cmd = NAND_CMD_PAGE_READ_ECC;
413 data->addr0 = page << 16;
414 data->addr1 = (page >> 16) & 0xff;
415 data->chipsel = 0 | 4; /* flash0 + undoc bit */
416
417 /* GO bit for the EXEC register */
418 data->exec = 1;
419
420 data->cfg0 = CFG0;
421 data->cfg1 = CFG1;
422
423 data->ecc_cfg = 0x203;
424
425 /* save existing ecc config */
426 cmd->cmd = CMD_OCB;
427 cmd->src = NAND_EBI2_ECC_BUF_CFG;
428 cmd->dst = paddr(&data->ecc_cfg_save);
429 cmd->len = 4;
430 cmd++;
431
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800432 for(n = 0; n < cwperpage; n++) {
Dima Zavin03cf4312009-01-23 16:38:30 -0800433 /* write CMD / ADDR0 / ADDR1 / CHIPSEL regs in a burst */
434 cmd->cmd = DST_CRCI_NAND_CMD;
435 cmd->src = paddr(&data->cmd);
436 cmd->dst = NAND_FLASH_CMD;
437 cmd->len = ((n == 0) ? 16 : 4);
438 cmd++;
439
440 if (n == 0) {
441 /* block on cmd ready, set configuration */
442 cmd->cmd = 0;
443 cmd->src = paddr(&data->cfg0);
444 cmd->dst = NAND_DEV0_CFG0;
445 cmd->len = 8;
446 cmd++;
447
448 /* set our ecc config */
449 cmd->cmd = 0;
450 cmd->src = paddr(&data->ecc_cfg);
451 cmd->dst = NAND_EBI2_ECC_BUF_CFG;
452 cmd->len = 4;
453 cmd++;
454 }
455 /* kick the execute register */
456 cmd->cmd = 0;
457 cmd->src = paddr(&data->exec);
458 cmd->dst = NAND_EXEC_CMD;
459 cmd->len = 4;
460 cmd++;
461
462 /* block on data ready, then read the status register */
463 cmd->cmd = SRC_CRCI_NAND_DATA;
464 cmd->src = NAND_FLASH_STATUS;
465 cmd->dst = paddr(&data->result[n]);
466 cmd->len = 8;
467 cmd++;
468
469 /* read data block */
470 cmd->cmd = 0;
471 cmd->src = NAND_FLASH_BUFFER;
472 cmd->dst = addr + n * 516;
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800473 cmd->len = ((n < (cwperpage -1 )) ? 516 : (512 - ((cwperpage - 1) << 2)));
Dima Zavin03cf4312009-01-23 16:38:30 -0800474 cmd++;
475 }
476
477 /* read extra data */
478 cmd->cmd = 0;
479 cmd->src = NAND_FLASH_BUFFER + 500;
480 cmd->dst = spareaddr;
481 cmd->len = 16;
482 cmd++;
483
484 /* restore saved ecc config */
485 cmd->cmd = CMD_OCU | CMD_LC;
486 cmd->src = paddr(&data->ecc_cfg_save);
487 cmd->dst = NAND_EBI2_ECC_BUF_CFG;
488 cmd->len = 4;
489
490 ptr[0] = (paddr(cmdlist) >> 3) | CMD_PTR_LP;
491
492 dmov_exec_cmdptr(DMOV_NAND_CHAN, ptr);
493
494#if VERBOSE
495 dprintf(INFO, "read page %d: status: %x %x %x %x\n",
496 page, data[5], data[6], data[7], data[8]);
497 for(n = 0; n < 4; n++) {
498 ptr = (unsigned*)(addr + 512 * n);
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800499 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 -0800500 ptr = (unsigned*)(spareaddr + 16 * n);
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800501 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 -0800502 }
503#endif
504
505 /* if any of the writes failed (0x10), or there was a
506 ** protection violation (0x100), we lose
507 */
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800508 for(n = 0; n < cwperpage; n++) {
Dima Zavin03cf4312009-01-23 16:38:30 -0800509 if (data->result[n].flash_status & 0x110) {
510 return -1;
511 }
512 }
513
514 return 0;
515}
516
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800517static int _flash_nand_write_page(dmov_s *cmdlist, unsigned *ptrlist, unsigned page,
Shashank Mittald0c836d2009-11-20 10:31:18 -0800518 const void *_addr, const void *_spareaddr, unsigned raw_mode)
Dima Zavin03cf4312009-01-23 16:38:30 -0800519{
520 dmov_s *cmd = cmdlist;
521 unsigned *ptr = ptrlist;
522 struct data_flash_io *data = (void*) (ptrlist + 4);
523 unsigned addr = (unsigned) _addr;
524 unsigned spareaddr = (unsigned) _spareaddr;
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800525 unsigned n;
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800526 unsigned cwperpage;
527 cwperpage = (flash_pagesize >> 9);
Dima Zavin03cf4312009-01-23 16:38:30 -0800528
529 data->cmd = NAND_CMD_PRG_PAGE;
530 data->addr0 = page << 16;
531 data->addr1 = (page >> 16) & 0xff;
532 data->chipsel = 0 | 4; /* flash0 + undoc bit */
Murali Palnatic54d13a2010-01-15 19:50:19 +0530533 data->clrfstatus = 0x00000020;
534 data->clrrstatus = 0x000000C0;
Dima Zavin03cf4312009-01-23 16:38:30 -0800535
Shashank Mittald0c836d2009-11-20 10:31:18 -0800536 if (!raw_mode){
537 data->cfg0 = CFG0;
538 data->cfg1 = CFG1;
539 }else{
540 data->cfg0 = (NAND_CFG0_RAW & ~(7 << 6)) |((cwperpage-1) << 6);
541 data->cfg1 = NAND_CFG1_RAW | (CFG1 & CFG1_WIDE_FLASH);
542 }
Dima Zavin03cf4312009-01-23 16:38:30 -0800543
544 /* GO bit for the EXEC register */
545 data->exec = 1;
546
547 data->ecc_cfg = 0x203;
548
549 /* save existing ecc config */
550 cmd->cmd = CMD_OCB;
551 cmd->src = NAND_EBI2_ECC_BUF_CFG;
552 cmd->dst = paddr(&data->ecc_cfg_save);
553 cmd->len = 4;
554 cmd++;
555
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800556 for(n = 0; n < cwperpage; n++) {
557 /* write CMD / ADDR0 / ADDR1 / CHIPSEL regs in a burst */
Dima Zavin03cf4312009-01-23 16:38:30 -0800558 cmd->cmd = DST_CRCI_NAND_CMD;
559 cmd->src = paddr(&data->cmd);
560 cmd->dst = NAND_FLASH_CMD;
561 cmd->len = ((n == 0) ? 16 : 4);
562 cmd++;
563
564 if (n == 0) {
565 /* set configuration */
566 cmd->cmd = 0;
567 cmd->src = paddr(&data->cfg0);
568 cmd->dst = NAND_DEV0_CFG0;
569 cmd->len = 8;
570 cmd++;
571
572 /* set our ecc config */
573 cmd->cmd = 0;
574 cmd->src = paddr(&data->ecc_cfg);
575 cmd->dst = NAND_EBI2_ECC_BUF_CFG;
576 cmd->len = 4;
577 cmd++;
578 }
579
580 /* write data block */
581 cmd->cmd = 0;
Dima Zavin03cf4312009-01-23 16:38:30 -0800582 cmd->dst = NAND_FLASH_BUFFER;
Shashank Mittald0c836d2009-11-20 10:31:18 -0800583 if (!raw_mode){
584 cmd->src = addr + n * 516;
585 cmd->len = ((n < (cwperpage - 1)) ? 516 : (512 - ((cwperpage - 1) << 2)));
586 }else{
587 cmd->src = addr;
588 cmd->len = 528;
589 }
Dima Zavin03cf4312009-01-23 16:38:30 -0800590 cmd++;
591
Shashank Mittald0c836d2009-11-20 10:31:18 -0800592 if ((n == (cwperpage - 1)) && (!raw_mode)) {
Dima Zavin03cf4312009-01-23 16:38:30 -0800593 /* write extra data */
594 cmd->cmd = 0;
595 cmd->src = spareaddr;
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800596 cmd->dst = NAND_FLASH_BUFFER + (512 - ((cwperpage - 1) << 2));
597 cmd->len = (cwperpage << 2);
Dima Zavin03cf4312009-01-23 16:38:30 -0800598 cmd++;
599 }
600
601 /* kick the execute register */
602 cmd->cmd = 0;
603 cmd->src = paddr(&data->exec);
604 cmd->dst = NAND_EXEC_CMD;
605 cmd->len = 4;
606 cmd++;
607
608 /* block on data ready, then read the status register */
609 cmd->cmd = SRC_CRCI_NAND_DATA;
610 cmd->src = NAND_FLASH_STATUS;
611 cmd->dst = paddr(&data->result[n]);
612 cmd->len = 8;
613 cmd++;
Murali Palnatic54d13a2010-01-15 19:50:19 +0530614
615 cmd->cmd = 0;
616 cmd->src = paddr(&data->clrfstatus);
617 cmd->dst = NAND_FLASH_STATUS;
618 cmd->len = 4;
619 cmd++;
620
621 cmd->cmd = 0;
622 cmd->src = paddr(&data->clrrstatus);
623 cmd->dst = NAND_READ_STATUS;
624 cmd->len = 4;
625 cmd++;
Dima Zavin03cf4312009-01-23 16:38:30 -0800626 }
627
628 /* restore saved ecc config */
629 cmd->cmd = CMD_OCU | CMD_LC;
630 cmd->src = paddr(&data->ecc_cfg_save);
631 cmd->dst = NAND_EBI2_ECC_BUF_CFG;
632 cmd->len = 4;
633
634 ptr[0] = (paddr(cmdlist) >> 3) | CMD_PTR_LP;
635
636 dmov_exec_cmdptr(DMOV_NAND_CHAN, ptr);
637
638#if VERBOSE
639 dprintf(INFO, "write page %d: status: %x %x %x %x\n",
640 page, data[5], data[6], data[7], data[8]);
641#endif
642
643 /* if any of the writes failed (0x10), or there was a
644 ** protection violation (0x100), or the program success
645 ** bit (0x80) is unset, we lose
646 */
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800647 for(n = 0; n < cwperpage; n++) {
Dima Zavin03cf4312009-01-23 16:38:30 -0800648 if(data->result[n].flash_status & 0x110) return -1;
649 if(!(data->result[n].flash_status & 0x80)) return -1;
650 }
651
Dima Zavin5582c7d2009-03-03 15:17:59 -0800652#if VERIFY_WRITE
653 n = _flash_read_page(cmdlist, ptrlist, page, flash_data,
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800654 flash_data + 2048);
Dima Zavin5582c7d2009-03-03 15:17:59 -0800655 if (n != 0)
656 return -1;
657 if (memcmp(flash_data, _addr, 2048) ||
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800658 memcmp(flash_data + 2048, _spareaddr, 16)) {
Dima Zavin5582c7d2009-03-03 15:17:59 -0800659 dprintf(CRITICAL, "verify error @ page %d\n", page);
660 return -1;
661 }
662#endif
Dima Zavin03cf4312009-01-23 16:38:30 -0800663 return 0;
664}
Shashank Mittald0c836d2009-11-20 10:31:18 -0800665char empty_buf[528];
666static int flash_nand_mark_badblock(dmov_s *cmdlist, unsigned *ptrlist, unsigned page)
667{
668 memset(empty_buf,0,528);
669 /* Going to first page of the block */
670 if(page & 63)
671 page = page - (page & 63);
672 return _flash_nand_write_page(cmdlist, ptrlist, page, empty_buf, 0, 1);
673}
Dima Zavin03cf4312009-01-23 16:38:30 -0800674
Shashank Mittal83d16d02009-11-18 16:54:42 -0800675unsigned nand_cfg0;
676unsigned nand_cfg1;
677
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800678static int flash_nand_read_config(dmov_s *cmdlist, unsigned *ptrlist)
Dima Zavin03cf4312009-01-23 16:38:30 -0800679{
680 cmdlist[0].cmd = CMD_OCB;
681 cmdlist[0].src = NAND_DEV0_CFG0;
682 cmdlist[0].dst = paddr(&CFG0);
683 cmdlist[0].len = 4;
684
685 cmdlist[1].cmd = CMD_OCU | CMD_LC;
686 cmdlist[1].src = NAND_DEV0_CFG1;
687 cmdlist[1].dst = paddr(&CFG1);
688 cmdlist[1].len = 4;
689
690 *ptrlist = (paddr(cmdlist) >> 3) | CMD_PTR_LP;
691
692 dmov_exec_cmdptr(DMOV_NAND_CHAN, ptrlist);
693
694 if((CFG0 == 0) || (CFG1 == 0)) {
695 return -1;
696 }
697
Shashank Mittal83d16d02009-11-18 16:54:42 -0800698 if (flash_info.type == FLASH_16BIT_NAND_DEVICE) {
699 nand_cfg1 |= CFG1_WIDE_FLASH;
700 }
Dima Zavin03cf4312009-01-23 16:38:30 -0800701 dprintf(INFO, "nandcfg: %x %x (initial)\n", CFG0, CFG1);
702
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800703 CFG0 = (((flash_pagesize >> 9) - 1) << 6) /* 4/8 cw/pg for 2/4k */
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800704 | (516 << 9) /* 516 user data bytes */
705 | (10 << 19) /* 10 parity bytes */
706 | (5 << 27) /* 5 address cycles */
Murali Palnatic54d13a2010-01-15 19:50:19 +0530707 | (0 << 30) /* Do not read status before data */
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800708 | (1 << 31) /* Send read cmd */
709 /* 0 spare bytes for 16 bit nand or 1 spare bytes for 8 bit */
710 | ((nand_cfg1 & CFG1_WIDE_FLASH) ? (0 << 23) : (1 << 23));
Dima Zavin03cf4312009-01-23 16:38:30 -0800711 CFG1 = (0 << 0) /* Enable ecc */
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800712 | (7 << 2) /* 8 recovery cycles */
713 | (0 << 5) /* Allow CS deassertion */
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800714 | ((flash_pagesize - (528 * ((flash_pagesize >> 9) - 1)) + 1) << 6) /* Bad block marker location */
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800715 | (0 << 16) /* Bad block in user data area */
716 | (2 << 17) /* 6 cycle tWB/tRB */
717 | (nand_cfg1 & CFG1_WIDE_FLASH); /* preserve wide flash flag */
Dima Zavin03cf4312009-01-23 16:38:30 -0800718
719 dprintf(INFO, "nandcfg: %x %x (used)\n", CFG0, CFG1);
720
721 return 0;
722}
723
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800724/* OneNAND programming functions */
725
726static void flash_onenand_read_id(dmov_s *cmdlist, unsigned *ptrlist)
727{
728 dmov_s *cmd = cmdlist;
729 unsigned *ptr = ptrlist;
730 unsigned *data = ptrlist + 4;
731
732 data[0] = SFLASH_BCFG;
733 data[1] = SFLASH_PREPCMD(8, 0, 0, NAND_SFCMD_DATXS, NAND_SFCMD_ASYNC, NAND_SFCMD_REGRD);
734 data[2] = (ONENAND_DEVICE_ID << 16) | (ONENAND_MANUFACTURER_ID);
735 data[3] = (ONENAND_DATA_BUFFER_SIZE << 16) | (ONENAND_VERSION_ID);
736 data[4] = (ONENAND_AMOUNT_OF_BUFFERS << 16) | (ONENAND_BOOT_BUFFER_SIZE);
737 data[5] = (CLEAN_DATA_16 << 16) | (ONENAND_TECHNOLOGY);
738 data[6] = CLEAN_DATA_32; //status
739 data[7] = CLEAN_DATA_32; //register read
740 data[8] = CLEAN_DATA_32; //register read
741 data[9] = CLEAN_DATA_32; //register read
742 data[10] = CLEAN_DATA_32; //register read
743 data[11] = 1;
744 data[12] = 0 | 4;
745
746 /* Setup controller in SFLASH mode */
747 cmd[0].cmd = 0 | CMD_OCB;
748 cmd[0].src = paddr(&data[0]);
749 cmd[0].dst = NAND_SFLASHC_BURST_CFG;
750 cmd[0].len = 4;
751
752 /* Enable data mover for controller */
753 cmd[1].cmd = 0;
754 cmd[1].src = paddr(&data[12]);
755 cmd[1].dst = NAND_FLASH_CHIP_SELECT;
756 cmd[1].len = 4;
757
758 /* Setup SFLASHC_CMD with xfers in async mode */
759 cmd[2].cmd = DST_CRCI_NAND_CMD;
760 cmd[2].src = paddr(&data[1]);
761 cmd[2].dst = NAND_SFLASHC_CMD;
762 cmd[2].len = 4;
763
764 /* Setup to read device information */
765 cmd[3].cmd = 0;
766 cmd[3].src = paddr(&data[2]);
767 cmd[3].dst = NAND_ADDR0;
768 cmd[3].len = 8;
769
770 cmd[4].cmd = 0;
771 cmd[4].src = paddr(&data[4]);
772 cmd[4].dst = NAND_ADDR2;
773 cmd[4].len = 8;
774
775 /* Set execute bit */
776 cmd[5].cmd = 0;
777 cmd[5].src = paddr(&data[11]);
778 cmd[5].dst = NAND_SFLASHC_EXEC_CMD;
779 cmd[5].len = 4;
780
781 /* Check status */
782 cmd[6].cmd = SRC_CRCI_NAND_DATA;
783 cmd[6].src = NAND_SFLASHC_STATUS;
784 cmd[6].dst = paddr(&data[6]);
785 cmd[6].len = 4;
786
787 /* Read result device registers */
788 cmd[7].cmd = 0 | CMD_OCU | CMD_LC;
789 cmd[7].src = NAND_GENP_REG0;
790 cmd[7].dst = paddr(&data[7]);
791 cmd[7].len = 16;
792
793 ptr[0] = (paddr(cmd) >> 3) | CMD_PTR_LP;
794
795 dmov_exec_cmdptr(DMOV_NAND_CHAN, ptr);
796
797#if VERBOSE
798 dprintf(INFO, "status: %x\n", data[6]);
799#endif
800
801 flash_info.id = data[7];
802 flash_info.vendor = data[7] & CLEAN_DATA_16;
803 flash_info.device = (data[7] >> 16) & CLEAN_DATA_16;
804 return;
805}
806
807
808struct data_onenand_erase {
809 unsigned sfbcfg;
810 unsigned sfcmd[4];
811 unsigned sfexec;
812 unsigned sfstat[4];
813 unsigned addr0;
814 unsigned addr1;
815 unsigned addr2;
816 unsigned addr3;
817 unsigned addr4;
818 unsigned addr5;
819 unsigned addr6;
820 unsigned data0;
821 unsigned data1;
822 unsigned data2;
823 unsigned data3;
824 unsigned data4;
825 unsigned data5;
826 unsigned data6;
827};
828
Shashank Mittalad3d05c2009-11-19 15:53:57 -0800829
830static int _flash_onenand_read_page(dmov_s *cmdlist, unsigned *ptrlist,
831 unsigned page, void *_addr,
832 void *_spareaddr, unsigned raw_mode);
833
834
835static int flash_onenand_block_isbad(dmov_s *cmdlist, unsigned *ptrlist,
836 unsigned page)
837{
838 unsigned char page_data[2112];
839 unsigned char *oobptr = &(page_data[2048]);
840
841 /* Going to first page of the block */
842 if(page & 63)
843 page = page - (page & 63);
844
845 /* Reading page in raw mode */
846 if (_flash_onenand_read_page(cmdlist, ptrlist,page, page_data, 0, 1))
847 return 1;
848
849 /* Checking if block is bad */
850 if ((oobptr[0] != 0xFF) || (oobptr[1] != 0xFF) ||
851 (oobptr[16] != 0xFF) || (oobptr[17] != 0xFF) ||
852 (oobptr[32] != 0xFF) || (oobptr[33] != 0xFF) ||
853 (oobptr[48] != 0xFF) || (oobptr[49] != 0xFF)
854 )
855 {
856 return 1;
857 }
858 return 0;
859}
860
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800861static int flash_onenand_erase_block(dmov_s *cmdlist, unsigned *ptrlist,
862 unsigned page)
863{
864 dmov_s *cmd = cmdlist;
865 unsigned *ptr = ptrlist;
866 struct data_onenand_erase *data = (void *)ptrlist + 4;
Shashank Mittalad3d05c2009-11-19 15:53:57 -0800867 int isbad = 0;
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800868 unsigned erasesize = (flash_pagesize << 6);
869 unsigned onenand_startaddr1 = DEVICE_FLASHCORE_0 | (page * flash_pagesize)/erasesize;
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800870 unsigned onenand_startaddr8 = 0x0000;
871 unsigned onenand_startaddr2 = DEVICE_BUFFERRAM_0 << 15;
872 unsigned onenand_startbuffer = DATARAM0_0 << 8;
873
874 unsigned controller_status;
875 unsigned interrupt_status;
876 unsigned ecc_status;
877
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800878 if((page * flash_pagesize) & (erasesize-1)) return -1;
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800879
Shashank Mittalad3d05c2009-11-19 15:53:57 -0800880 /* Check for bad block and erase only if block is not marked bad */
881 isbad = flash_onenand_block_isbad(cmdlist, ptrlist, page);
882 if (isbad)
883 {
884 dprintf(INFO, "skipping @ %d (bad block)\n", page >> 6);
885 return -1;
886 }
887
888 /*Erase block*/
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800889 onenand_startaddr1 = DEVICE_FLASHCORE_0 |
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800890 ((page * flash_pagesize) / (erasesize));
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800891 onenand_startaddr8 = 0x0000;
892 onenand_startaddr2 = DEVICE_BUFFERRAM_0 << 15;
893 onenand_startbuffer = DATARAM0_0 << 8;
894
895
896 data->sfbcfg = SFLASH_BCFG;
897 data->sfcmd[0] = SFLASH_PREPCMD(7, 0, 0,
898 NAND_SFCMD_CMDXS,
899 NAND_SFCMD_ASYNC,
900 NAND_SFCMD_REGWR);
901 data->sfcmd[1] = SFLASH_PREPCMD(0, 0, 32,
902 NAND_SFCMD_CMDXS,
903 NAND_SFCMD_ASYNC,
904 NAND_SFCMD_INTHI);
905 data->sfcmd[2] = SFLASH_PREPCMD(3, 7, 0,
906 NAND_SFCMD_DATXS,
907 NAND_SFCMD_ASYNC,
908 NAND_SFCMD_REGRD);
909 data->sfcmd[3] = SFLASH_PREPCMD(4, 10, 0,
910 NAND_SFCMD_CMDXS,
911 NAND_SFCMD_ASYNC,
912 NAND_SFCMD_REGWR);
913 data->sfexec = 1;
914 data->sfstat[0] = CLEAN_DATA_32;
915 data->sfstat[1] = CLEAN_DATA_32;
916 data->sfstat[2] = CLEAN_DATA_32;
917 data->sfstat[3] = CLEAN_DATA_32;
918 data->addr0 = (ONENAND_INTERRUPT_STATUS << 16) |
919 (ONENAND_SYSTEM_CONFIG_1);
920 data->addr1 = (ONENAND_START_ADDRESS_8 << 16) |
921 (ONENAND_START_ADDRESS_1);
922 data->addr2 = (ONENAND_START_BUFFER << 16) |
923 (ONENAND_START_ADDRESS_2);
924 data->addr3 = (ONENAND_ECC_STATUS << 16) |
925 (ONENAND_COMMAND);
926 data->addr4 = (ONENAND_CONTROLLER_STATUS << 16) |
927 (ONENAND_INTERRUPT_STATUS);
928 data->addr5 = (ONENAND_INTERRUPT_STATUS << 16) |
929 (ONENAND_SYSTEM_CONFIG_1);
930 data->addr6 = (ONENAND_START_ADDRESS_3 << 16) |
931 (ONENAND_START_ADDRESS_1);
932 data->data0 = (ONENAND_CLRINTR << 16) |
933 (ONENAND_SYSCFG1_ECCENA);
934 data->data1 = (onenand_startaddr8 << 16) |
935 (onenand_startaddr1);
936 data->data2 = (onenand_startbuffer << 16) |
937 (onenand_startaddr2);
938 data->data3 = (CLEAN_DATA_16 << 16) |
939 (ONENAND_CMDERAS);
940 data->data4 = (CLEAN_DATA_16 << 16) |
941 (CLEAN_DATA_16);
942 data->data5 = (ONENAND_CLRINTR << 16) |
943 (ONENAND_SYSCFG1_ECCENA);
944 data->data6 = (ONENAND_STARTADDR3_RES << 16) |
945 (ONENAND_STARTADDR1_RES);
946
947 /***************************************************************/
948 /* Write the necessary address registers in the onenand device */
949 /***************************************************************/
950
951 /* Enable and configure the SFlash controller */
952 cmd->cmd = 0 | CMD_OCB;
953 cmd->src = paddr(&data->sfbcfg);
954 cmd->dst = NAND_SFLASHC_BURST_CFG;
955 cmd->len = 4;
956 cmd++;
957
958 /* Block on cmd ready and write CMD register */
959 cmd->cmd = DST_CRCI_NAND_CMD;
960 cmd->src = paddr(&data->sfcmd[0]);
961 cmd->dst = NAND_SFLASHC_CMD;
962 cmd->len = 4;
963 cmd++;
964
965 /* Write the ADDR0 and ADDR1 registers */
966 cmd->cmd = 0;
967 cmd->src = paddr(&data->addr0);
968 cmd->dst = NAND_ADDR0;
969 cmd->len = 8;
970 cmd++;
971
972 /* Write the ADDR2 ADDR3 ADDR4 ADDR5 registers */
973 cmd->cmd = 0;
974 cmd->src = paddr(&data->addr2);
975 cmd->dst = NAND_ADDR2;
976 cmd->len = 16;
977 cmd++;
978
979 /* Write the ADDR6 registers */
980 cmd->cmd = 0;
981 cmd->src = paddr(&data->addr6);
982 cmd->dst = NAND_ADDR6;
983 cmd->len = 4;
984 cmd++;
985
986 /* Write the GENP0, GENP1, GENP2, GENP3, GENP4 registers */
987 cmd->cmd = 0;
988 cmd->src = paddr(&data->data0);
989 cmd->dst = NAND_GENP_REG0;
990 cmd->len = 16;
991 cmd++;
992
993 /* Write the FLASH_DEV_CMD4,5,6 registers */
994 cmd->cmd = 0;
995 cmd->src = paddr(&data->data4);
996 cmd->dst = NAND_DEV_CMD4;
997 cmd->len = 12;
998 cmd++;
999
1000 /* Kick the execute command */
1001 cmd->cmd = 0;
1002 cmd->src = paddr(&data->sfexec);
1003 cmd->dst = NAND_SFLASHC_EXEC_CMD;
1004 cmd->len = 4;
1005 cmd++;
1006
1007 /* Block on data ready, and read the status register */
1008 cmd->cmd = SRC_CRCI_NAND_DATA;
1009 cmd->src = NAND_SFLASHC_STATUS;
1010 cmd->dst = paddr(&data->sfstat[0]);
1011 cmd->len = 4;
1012 cmd++;
1013
1014 /***************************************************************/
1015 /* Wait for the interrupt from the Onenand device controller */
1016 /***************************************************************/
1017
1018 /* Block on cmd ready and write CMD register */
1019 cmd->cmd = DST_CRCI_NAND_CMD;
1020 cmd->src = paddr(&data->sfcmd[1]);
1021 cmd->dst = NAND_SFLASHC_CMD;
1022 cmd->len = 4;
1023 cmd++;
1024
1025 /* Kick the execute command */
1026 cmd->cmd = 0;
1027 cmd->src = paddr(&data->sfexec);
1028 cmd->dst = NAND_SFLASHC_EXEC_CMD;
1029 cmd->len = 4;
1030 cmd++;
1031
1032 /* Block on data ready, and read the status register */
1033 cmd->cmd = SRC_CRCI_NAND_DATA;
1034 cmd->src = NAND_SFLASHC_STATUS;
1035 cmd->dst = paddr(&data->sfstat[1]);
1036 cmd->len = 4;
1037 cmd++;
1038
1039 /***************************************************************/
1040 /* Read the necessary status registers from the onenand device */
1041 /***************************************************************/
1042
1043 /* Block on cmd ready and write CMD register */
1044 cmd->cmd = DST_CRCI_NAND_CMD;
1045 cmd->src = paddr(&data->sfcmd[2]);
1046 cmd->dst = NAND_SFLASHC_CMD;
1047 cmd->len = 4;
1048 cmd++;
1049
1050 /* Kick the execute command */
1051 cmd->cmd = 0;
1052 cmd->src = paddr(&data->sfexec);
1053 cmd->dst = NAND_SFLASHC_EXEC_CMD;
1054 cmd->len = 4;
1055 cmd++;
1056
1057 /* Block on data ready, and read the status register */
1058 cmd->cmd = SRC_CRCI_NAND_DATA;
1059 cmd->src = NAND_SFLASHC_STATUS;
1060 cmd->dst = paddr(&data->sfstat[2]);
1061 cmd->len = 4;
1062 cmd++;
1063
1064 /* Read the GENP3 register */
1065 cmd->cmd = 0;
1066 cmd->src = NAND_GENP_REG3;
1067 cmd->dst = paddr(&data->data3);
1068 cmd->len = 4;
1069 cmd++;
1070
1071 /* Read the DEVCMD4 register */
1072 cmd->cmd = 0;
1073 cmd->src = NAND_DEV_CMD4;
1074 cmd->dst = paddr(&data->data4);
1075 cmd->len = 4;
1076 cmd++;
1077
1078 /***************************************************************/
1079 /* Restore the necessary registers to proper values */
1080 /***************************************************************/
1081
1082 /* Block on cmd ready and write CMD register */
1083 cmd->cmd = DST_CRCI_NAND_CMD;
1084 cmd->src = paddr(&data->sfcmd[3]);
1085 cmd->dst = NAND_SFLASHC_CMD;
1086 cmd->len = 4;
1087 cmd++;
1088
1089 /* Kick the execute command */
1090 cmd->cmd = 0;
1091 cmd->src = paddr(&data->sfexec);
1092 cmd->dst = NAND_SFLASHC_EXEC_CMD;
1093 cmd->len = 4;
1094 cmd++;
1095
1096 /* Block on data ready, and read the status register */
1097 cmd->cmd = SRC_CRCI_NAND_DATA | CMD_OCU | CMD_LC;
1098 cmd->src = NAND_SFLASHC_STATUS;
1099 cmd->dst = paddr(&data->sfstat[3]);
1100 cmd->len = 4;
1101 cmd++;
1102
1103 ptr[0] = (paddr(cmdlist) >> 3) | CMD_PTR_LP;
1104
1105 dmov_exec_cmdptr(DMOV_NAND_CHAN, ptr);
1106
1107 ecc_status = (data->data3 >> 16) & 0x0000FFFF;
1108 interrupt_status = (data->data4 >> 0) & 0x0000FFFF;
1109 controller_status = (data->data4 >> 16) & 0x0000FFFF;
1110
1111#if VERBOSE
1112 dprintf(INFO, "\n%s: sflash status %x %x %x %x\n", __func__,
1113 data->sfstat[0],
1114 data->sfstat[1],
1115 data->sfstat[2],
1116 data->sfstat[3]);
1117
1118 dprintf(INFO, "%s: controller_status = %x\n", __func__,
1119 controller_status);
1120 dprintf(INFO, "%s: interrupt_status = %x\n", __func__,
1121 interrupt_status);
1122 dprintf(INFO, "%s: ecc_status = %x\n", __func__,
1123 ecc_status);
1124#endif
1125 /* Check for errors, protection violations etc */
1126 if ((controller_status != 0)
1127 || (data->sfstat[0] & 0x110)
1128 || (data->sfstat[1] & 0x110)
1129 || (data->sfstat[2] & 0x110)
1130 || (data->sfstat[3] & 0x110)) {
1131 dprintf(CRITICAL, "%s: ECC/MPU/OP error\n", __func__);
1132 return -1;
1133 }
1134
1135
1136#if VERBOSE
1137 dprintf(INFO, "status: %x\n", data[5]);
1138#endif
1139
1140 return 0;
1141}
1142
1143
1144struct data_onenand_read {
1145 unsigned sfbcfg;
1146 unsigned sfcmd[9];
1147 unsigned sfexec;
1148 unsigned sfstat[9];
1149 unsigned addr0;
1150 unsigned addr1;
1151 unsigned addr2;
1152 unsigned addr3;
1153 unsigned addr4;
1154 unsigned addr5;
1155 unsigned addr6;
1156 unsigned data0;
1157 unsigned data1;
1158 unsigned data2;
1159 unsigned data3;
1160 unsigned data4;
1161 unsigned data5;
1162 unsigned data6;
1163 unsigned macro[5];
1164};
1165
1166
1167static int _flash_onenand_read_page(dmov_s *cmdlist, unsigned *ptrlist,
Shashank Mittalad3d05c2009-11-19 15:53:57 -08001168 unsigned page, void *_addr, void *_spareaddr,
1169 unsigned raw_mode)
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001170{
1171 dmov_s *cmd = cmdlist;
1172 unsigned *ptr = ptrlist;
1173 struct data_onenand_read *data = (void*) (ptrlist + 4);
1174 unsigned addr = (unsigned) _addr;
1175 unsigned curr_addr = (unsigned) _addr;
1176 unsigned spareaddr = (unsigned) _spareaddr;
1177 unsigned i;
Shashank Mittaldcc2e352009-11-19 19:11:16 -08001178 unsigned erasesize = (flash_pagesize<<6);
1179 unsigned writesize = flash_pagesize;
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001180
1181 unsigned onenand_startaddr1 = DEVICE_FLASHCORE_0 |
Shashank Mittaldcc2e352009-11-19 19:11:16 -08001182 ((unsigned)(page * flash_pagesize) / erasesize);
1183 unsigned onenand_startaddr8 = (((unsigned)(page * flash_pagesize) &
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001184 (erasesize - 1)) / writesize) << 2;
1185 unsigned onenand_startaddr2 = DEVICE_BUFFERRAM_0 << 15;
1186 unsigned onenand_startbuffer = DATARAM0_0 << 8;
Shashank Mittalad3d05c2009-11-19 15:53:57 -08001187 unsigned onenand_sysconfig1 = (raw_mode == 1) ? ONENAND_SYSCFG1_ECCDIS :\
1188 ONENAND_SYSCFG1_ECCENA;
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001189
1190 unsigned controller_status;
1191 unsigned interrupt_status;
1192 unsigned ecc_status;
Shashank Mittalad3d05c2009-11-19 15:53:57 -08001193 if (raw_mode != 1)
1194 {
1195 int isbad = 0;
1196 isbad = flash_onenand_block_isbad(cmdlist, ptrlist, page);
1197 if (isbad)
1198 return -2;
1199 }
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001200
1201 //static int oobfree_offset[8] = {2, 14, 18, 30, 34, 46, 50, 62};
1202 //static int oobfree_length[8] = {3, 2, 3, 2, 3, 2, 3, 2};
1203
1204 data->sfbcfg = SFLASH_BCFG;
1205 data->sfcmd[0] = SFLASH_PREPCMD(7, 0, 0,
1206 NAND_SFCMD_CMDXS,
1207 NAND_SFCMD_ASYNC,
1208 NAND_SFCMD_REGWR);
1209 data->sfcmd[1] = SFLASH_PREPCMD(0, 0, 32,
1210 NAND_SFCMD_CMDXS,
1211 NAND_SFCMD_ASYNC,
1212 NAND_SFCMD_INTHI);
1213 data->sfcmd[2] = SFLASH_PREPCMD(3, 7, 0,
1214 NAND_SFCMD_DATXS,
1215 NAND_SFCMD_ASYNC,
1216 NAND_SFCMD_REGRD);
1217 data->sfcmd[3] = SFLASH_PREPCMD(256, 0, 0,
1218 NAND_SFCMD_DATXS,
1219 NAND_SFCMD_ASYNC,
1220 NAND_SFCMD_DATRD);
1221 data->sfcmd[4] = SFLASH_PREPCMD(256, 0, 0,
1222 NAND_SFCMD_DATXS,
1223 NAND_SFCMD_ASYNC,
1224 NAND_SFCMD_DATRD);
1225 data->sfcmd[5] = SFLASH_PREPCMD(256, 0, 0,
1226 NAND_SFCMD_DATXS,
1227 NAND_SFCMD_ASYNC,
1228 NAND_SFCMD_DATRD);
1229 data->sfcmd[6] = SFLASH_PREPCMD(256, 0, 0,
1230 NAND_SFCMD_DATXS,
1231 NAND_SFCMD_ASYNC,
1232 NAND_SFCMD_DATRD);
1233 data->sfcmd[7] = SFLASH_PREPCMD(32, 0, 0,
1234 NAND_SFCMD_DATXS,
1235 NAND_SFCMD_ASYNC,
1236 NAND_SFCMD_DATRD);
1237 data->sfcmd[8] = SFLASH_PREPCMD(4, 10, 0,
1238 NAND_SFCMD_CMDXS,
1239 NAND_SFCMD_ASYNC,
1240 NAND_SFCMD_REGWR);
1241 data->sfexec = 1;
1242 data->sfstat[0] = CLEAN_DATA_32;
1243 data->sfstat[1] = CLEAN_DATA_32;
1244 data->sfstat[2] = CLEAN_DATA_32;
1245 data->sfstat[3] = CLEAN_DATA_32;
1246 data->sfstat[4] = CLEAN_DATA_32;
1247 data->sfstat[5] = CLEAN_DATA_32;
1248 data->sfstat[6] = CLEAN_DATA_32;
1249 data->sfstat[7] = CLEAN_DATA_32;
1250 data->sfstat[8] = CLEAN_DATA_32;
1251
1252 data->addr0 = (ONENAND_INTERRUPT_STATUS << 16) |
1253 (ONENAND_SYSTEM_CONFIG_1);
1254 data->addr1 = (ONENAND_START_ADDRESS_8 << 16) |
1255 (ONENAND_START_ADDRESS_1);
1256 data->addr2 = (ONENAND_START_BUFFER << 16) |
1257 (ONENAND_START_ADDRESS_2);
1258 data->addr3 = (ONENAND_ECC_STATUS << 16) |
1259 (ONENAND_COMMAND);
1260 data->addr4 = (ONENAND_CONTROLLER_STATUS << 16) |
1261 (ONENAND_INTERRUPT_STATUS);
1262 data->addr5 = (ONENAND_INTERRUPT_STATUS << 16) |
1263 (ONENAND_SYSTEM_CONFIG_1);
1264 data->addr6 = (ONENAND_START_ADDRESS_3 << 16) |
1265 (ONENAND_START_ADDRESS_1);
1266 data->data0 = (ONENAND_CLRINTR << 16) |
1267 (onenand_sysconfig1);
1268 data->data1 = (onenand_startaddr8 << 16) |
1269 (onenand_startaddr1);
1270 data->data2 = (onenand_startbuffer << 16) |
1271 (onenand_startaddr2);
1272 data->data3 = (CLEAN_DATA_16 << 16) |
1273 (ONENAND_CMDLOADSPARE);
1274 data->data4 = (CLEAN_DATA_16 << 16) |
1275 (CLEAN_DATA_16);
1276 data->data5 = (ONENAND_CLRINTR << 16) |
1277 (ONENAND_SYSCFG1_ECCENA);
1278 data->data6 = (ONENAND_STARTADDR3_RES << 16) |
1279 (ONENAND_STARTADDR1_RES);
1280 data->macro[0] = 0x0200;
1281 data->macro[1] = 0x0300;
1282 data->macro[2] = 0x0400;
1283 data->macro[3] = 0x0500;
1284 data->macro[4] = 0x8010;
1285
1286 /*************************************************************/
1287 /* Write necessary address registers in the onenand device */
1288 /*************************************************************/
1289
1290 /* Enable and configure the SFlash controller */
1291 cmd->cmd = 0 | CMD_OCB;
1292 cmd->src = paddr(&data->sfbcfg);
1293 cmd->dst = NAND_SFLASHC_BURST_CFG;
1294 cmd->len = 4;
1295 cmd++;
1296
1297 /* Block on cmd ready and write CMD register */
1298 cmd->cmd = DST_CRCI_NAND_CMD;
1299 cmd->src = paddr(&data->sfcmd[0]);
1300 cmd->dst = NAND_SFLASHC_CMD;
1301 cmd->len = 4;
1302 cmd++;
1303
1304 /* Write the ADDR0 and ADDR1 registers */
1305 cmd->cmd = 0;
1306 cmd->src = paddr(&data->addr0);
1307 cmd->dst = NAND_ADDR0;
1308 cmd->len = 8;
1309 cmd++;
1310
1311 /* Write the ADDR2 ADDR3 ADDR4 ADDR5 registers */
1312 cmd->cmd = 0;
1313 cmd->src = paddr(&data->addr2);
1314 cmd->dst = NAND_ADDR2;
1315 cmd->len = 16;
1316 cmd++;
1317
1318 /* Write the ADDR6 registers */
1319 cmd->cmd = 0;
1320 cmd->src = paddr(&data->addr6);
1321 cmd->dst = NAND_ADDR6;
1322 cmd->len = 4;
1323 cmd++;
1324
1325 /* Write the GENP0, GENP1, GENP2, GENP3 registers */
1326 cmd->cmd = 0;
1327 cmd->src = paddr(&data->data0);
1328 cmd->dst = NAND_GENP_REG0;
1329 cmd->len = 16;
1330 cmd++;
1331
1332 /* Write the FLASH_DEV_CMD4,5,6 registers */
1333 cmd->cmd = 0;
1334 cmd->src = paddr(&data->data4);
1335 cmd->dst = NAND_DEV_CMD4;
1336 cmd->len = 12;
1337 cmd++;
1338
1339 /* Kick the execute command */
1340 cmd->cmd = 0;
1341 cmd->src = paddr(&data->sfexec);
1342 cmd->dst = NAND_SFLASHC_EXEC_CMD;
1343 cmd->len = 4;
1344 cmd++;
1345
1346 /* Block on data ready, and read the status register */
1347 cmd->cmd = SRC_CRCI_NAND_DATA;
1348 cmd->src = NAND_SFLASHC_STATUS;
1349 cmd->dst = paddr(&data->sfstat[0]);
1350 cmd->len = 4;
1351 cmd++;
1352
1353 /*************************************************************/
1354 /* Wait for the interrupt from the Onenand device controller */
1355 /*************************************************************/
1356
1357 /* Block on cmd ready and write CMD register */
1358 cmd->cmd = DST_CRCI_NAND_CMD;
1359 cmd->src = paddr(&data->sfcmd[1]);
1360 cmd->dst = NAND_SFLASHC_CMD;
1361 cmd->len = 4;
1362 cmd++;
1363
1364 /* Kick the execute command */
1365 cmd->cmd = 0;
1366 cmd->src = paddr(&data->sfexec);
1367 cmd->dst = NAND_SFLASHC_EXEC_CMD;
1368 cmd->len = 4;
1369 cmd++;
1370
1371 /* Block on data ready, and read the status register */
1372 cmd->cmd = SRC_CRCI_NAND_DATA;
1373 cmd->src = NAND_SFLASHC_STATUS;
1374 cmd->dst = paddr(&data->sfstat[1]);
1375 cmd->len = 4;
1376 cmd++;
1377
1378
1379 /*************************************************************/
1380 /* Read necessary status registers from the onenand device */
1381 /*************************************************************/
1382
1383 /* Block on cmd ready and write CMD register */
1384 cmd->cmd = DST_CRCI_NAND_CMD;
1385 cmd->src = paddr(&data->sfcmd[2]);
1386 cmd->dst = NAND_SFLASHC_CMD;
1387 cmd->len = 4;
1388 cmd++;
1389
1390 /* Kick the execute command */
1391 cmd->cmd = 0;
1392 cmd->src = paddr(&data->sfexec);
1393 cmd->dst = NAND_SFLASHC_EXEC_CMD;
1394 cmd->len = 4;
1395 cmd++;
1396
1397 /* Block on data ready, and read the status register */
1398 cmd->cmd = SRC_CRCI_NAND_DATA;
1399 cmd->src = NAND_SFLASHC_STATUS;
1400 cmd->dst = paddr(&data->sfstat[2]);
1401 cmd->len = 4;
1402 cmd++;
1403
1404 /* Read the GENP3 register */
1405 cmd->cmd = 0;
1406 cmd->src = NAND_GENP_REG3;
1407 cmd->dst = paddr(&data->data3);
1408 cmd->len = 4;
1409 cmd++;
1410
1411 /* Read the DEVCMD4 register */
1412 cmd->cmd = 0;
1413 cmd->src = NAND_DEV_CMD4;
1414 cmd->dst = paddr(&data->data4);
1415 cmd->len = 4;
1416 cmd++;
1417
1418
1419 /*************************************************************/
1420 /* Read the data ram area from the onenand buffer ram */
1421 /*************************************************************/
1422
1423 if (addr) {
1424
1425 data->data3 = (CLEAN_DATA_16 << 16) |
1426 (ONENAND_CMDLOAD);
1427
1428 for (i = 0; i < 4; i++) {
1429
1430 /* Block on cmd ready and write CMD register */
1431 cmd->cmd = DST_CRCI_NAND_CMD;
1432 cmd->src = paddr(&data->sfcmd[3+i]);
1433 cmd->dst = NAND_SFLASHC_CMD;
1434 cmd->len = 4;
1435 cmd++;
1436
1437 /* Write the MACRO1 register */
1438 cmd->cmd = 0;
1439 cmd->src = paddr(&data->macro[i]);
1440 cmd->dst = NAND_MACRO1_REG;
1441 cmd->len = 4;
1442 cmd++;
1443
1444 /* Kick the execute command */
1445 cmd->cmd = 0;
1446 cmd->src = paddr(&data->sfexec);
1447 cmd->dst = NAND_SFLASHC_EXEC_CMD;
1448 cmd->len = 4;
1449 cmd++;
1450
1451 /* Block on data rdy, & read status register */
1452 cmd->cmd = SRC_CRCI_NAND_DATA;
1453 cmd->src = NAND_SFLASHC_STATUS;
1454 cmd->dst = paddr(&data->sfstat[3+i]);
1455 cmd->len = 4;
1456 cmd++;
1457
1458 /* Transfer nand ctlr buf contents to usr buf */
1459 cmd->cmd = 0;
1460 cmd->src = NAND_FLASH_BUFFER;
1461 cmd->dst = curr_addr;
1462 cmd->len = 512;
1463 curr_addr += 512;
1464 cmd++;
1465 }
1466 }
1467
Shashank Mittalad3d05c2009-11-19 15:53:57 -08001468 /* Read oob bytes in Raw Mode */
1469 if (raw_mode == 1)
1470 {
1471 /* Block on cmd ready and write CMD register */
1472 cmd->cmd = DST_CRCI_NAND_CMD;
1473 cmd->src = paddr(&data->sfcmd[7]);
1474 cmd->dst = NAND_SFLASHC_CMD;
1475 cmd->len = 4;
1476 cmd++;
1477
1478 /* Write the MACRO1 register */
1479 cmd->cmd = 0;
1480 cmd->src = paddr(&data->macro[4]);
1481 cmd->dst = NAND_MACRO1_REG;
1482 cmd->len = 4;
1483 cmd++;
1484
1485 /* Kick the execute command */
1486 cmd->cmd = 0;
1487 cmd->src = paddr(&data->sfexec);
1488 cmd->dst = NAND_SFLASHC_EXEC_CMD;
1489 cmd->len = 4;
1490 cmd++;
1491
1492 /* Block on data rdy, & read status register */
1493 cmd->cmd = SRC_CRCI_NAND_DATA;
1494 cmd->src = NAND_SFLASHC_STATUS;
1495 cmd->dst = paddr(&data->sfstat[7]);
1496 cmd->len = 4;
1497 cmd++;
1498
1499 /* Transfer nand ctlr buf contents to usr buf */
1500 cmd->cmd = 0;
1501 cmd->src = NAND_FLASH_BUFFER;
1502 cmd->dst = curr_addr;
1503 cmd->len = 64;
1504 curr_addr += 64;
1505 cmd++;
1506 }
1507
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001508 /*************************************************************/
1509 /* Restore the necessary registers to proper values */
1510 /*************************************************************/
1511
1512 /* Block on cmd ready and write CMD register */
1513 cmd->cmd = DST_CRCI_NAND_CMD;
1514 cmd->src = paddr(&data->sfcmd[8]);
1515 cmd->dst = NAND_SFLASHC_CMD;
1516 cmd->len = 4;
1517 cmd++;
1518
1519 /* Kick the execute command */
1520 cmd->cmd = 0;
1521 cmd->src = paddr(&data->sfexec);
1522 cmd->dst = NAND_SFLASHC_EXEC_CMD;
1523 cmd->len = 4;
1524 cmd++;
1525
1526 /* Block on data ready, and read the status register */
1527 cmd->cmd = SRC_CRCI_NAND_DATA | CMD_OCU | CMD_LC;
1528 cmd->src = NAND_SFLASHC_STATUS;
1529 cmd->dst = paddr(&data->sfstat[8]);
1530 cmd->len = 4;
1531 cmd++;
1532
1533
1534 ptr[0] = (paddr(cmdlist) >> 3) | CMD_PTR_LP;
1535
1536 dmov_exec_cmdptr(DMOV_NAND_CHAN, ptr);
1537
1538
1539 ecc_status = (data->data3 >> 16) &
1540 0x0000FFFF;
1541 interrupt_status = (data->data4 >> 0) &
1542 0x0000FFFF;
1543 controller_status = (data->data4 >> 16) &
1544 0x0000FFFF;
1545
1546#if VERBOSE
1547 dprintf(INFO, "\n%s: sflash status %x %x %x %x %x %x %x"
1548 "%x %x\n", __func__,
1549 data->sfstat[0],
1550 data->sfstat[1],
1551 data->sfstat[2],
1552 data->sfstat[3],
1553 data->sfstat[4],
1554 data->sfstat[5],
1555 data->sfstat[6],
1556 data->sfstat[7]);
1557
1558 dprintf(INFO, "%s: controller_status = %x\n", __func__,
1559 controller_status);
1560 dprintf(INFO, "%s: interrupt_status = %x\n", __func__,
1561 interrupt_status);
1562 dprintf(INFO, "%s: ecc_status = %x\n", __func__,
1563 ecc_status);
1564#endif
1565 /* Check for errors, protection violations etc */
1566 if ((controller_status != 0)
1567 || (data->sfstat[0] & 0x110)
1568 || (data->sfstat[1] & 0x110)
1569 || (data->sfstat[2] & 0x110)
1570 || ((data->sfstat[3] & 0x110) &&
1571 (addr))
1572 || ((data->sfstat[4] & 0x110) &&
1573 (addr))
1574 || ((data->sfstat[5] & 0x110) &&
1575 (addr))
1576 || ((data->sfstat[6] & 0x110) &&
1577 (addr))) {
1578 dprintf(INFO, "%s: ECC/MPU/OP error\n", __func__);
1579 return -1;
1580 }
1581
1582#if VERBOSE
1583 dprintf(INFO, "read page %d: status: %x %x %x %x\n",
1584 page, data[5], data[6], data[7], data[8]);
1585 for(n = 0; n < 4; n++) {
1586 ptr = (unsigned*)(addr + 512 * n);
1587 dprintf(INFO, "data%d: %x %x %x %x\n", n, ptr[0], ptr[1], ptr[2], ptr[3]);
1588 ptr = (unsigned*)(spareaddr + 16 * n);
1589 dprintf(INFO, "spare data%d %x %x %x %x\n", n, ptr[0], ptr[1], ptr[2], ptr[3]);
1590 }
1591#endif
1592
1593 return 0;
1594}
1595
1596
1597struct data_onenand_write {
1598 unsigned sfbcfg;
1599 unsigned sfcmd[9];
1600 unsigned sfexec;
1601 unsigned sfstat[9];
1602 unsigned addr0;
1603 unsigned addr1;
1604 unsigned addr2;
1605 unsigned addr3;
1606 unsigned addr4;
1607 unsigned addr5;
1608 unsigned addr6;
1609 unsigned data0;
1610 unsigned data1;
1611 unsigned data2;
1612 unsigned data3;
1613 unsigned data4;
1614 unsigned data5;
1615 unsigned data6;
1616 unsigned macro[5];
1617};
1618
1619static int _flash_onenand_write_page(dmov_s *cmdlist, unsigned *ptrlist,
1620 unsigned page, const void *_addr,
Shashank Mittald0c836d2009-11-20 10:31:18 -08001621 const void *_spareaddr, unsigned raw_mode)
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001622{
1623 dmov_s *cmd = cmdlist;
1624 unsigned *ptr = ptrlist;
1625 struct data_onenand_write *data = (void*) (ptrlist + 4);
1626 unsigned addr = (unsigned) _addr;
1627 unsigned addr_curr = (unsigned) _addr;
1628 char * spareaddr = (char *) _spareaddr;
1629 unsigned i, j, k;
1630
Shashank Mittaldcc2e352009-11-19 19:11:16 -08001631 unsigned erasesize = (flash_pagesize<<6);
1632 unsigned writesize = flash_pagesize;
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001633
Shashank Mittaldcc2e352009-11-19 19:11:16 -08001634 unsigned onenand_startaddr1 = (page * flash_pagesize) / erasesize;
1635 unsigned onenand_startaddr8 = (((unsigned)(page * flash_pagesize) &
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001636 (erasesize-1)) / writesize) << 2;
1637 unsigned onenand_startaddr2 = DEVICE_BUFFERRAM_0 << 15;
1638 unsigned onenand_startbuffer = DATARAM0_0 << 8;
Shashank Mittald0c836d2009-11-20 10:31:18 -08001639 unsigned onenand_sysconfig1 = (raw_mode == 1) ? ONENAND_SYSCFG1_ECCDIS :\
1640 ONENAND_SYSCFG1_ECCENA;
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001641
1642 unsigned controller_status;
1643 unsigned interrupt_status;
1644 unsigned ecc_status;
1645
1646 char flash_oob[64];
1647
1648 unsigned oobfree_offset[8] = {2, 14, 18, 30, 34, 46, 50, 62};
1649 unsigned oobfree_length[8] = {3, 2, 3, 2, 3, 2, 3, 2};
1650
1651 for (i = 0; i < 64; i++)
1652 flash_oob[i] = 0xFF;
1653
1654 data->sfbcfg = SFLASH_BCFG;
1655 data->sfcmd[0] = SFLASH_PREPCMD(256, 0, 0,
1656 NAND_SFCMD_CMDXS,
1657 NAND_SFCMD_ASYNC,
1658 NAND_SFCMD_DATWR);
1659 data->sfcmd[1] = SFLASH_PREPCMD(256, 0, 0,
1660 NAND_SFCMD_CMDXS,
1661 NAND_SFCMD_ASYNC,
1662 NAND_SFCMD_DATWR);
1663 data->sfcmd[2] = SFLASH_PREPCMD(256, 0, 0,
1664 NAND_SFCMD_CMDXS,
1665 NAND_SFCMD_ASYNC,
1666 NAND_SFCMD_DATWR);
1667 data->sfcmd[3] = SFLASH_PREPCMD(256, 0, 0,
1668 NAND_SFCMD_CMDXS,
1669 NAND_SFCMD_ASYNC,
1670 NAND_SFCMD_DATWR);
1671 data->sfcmd[4] = SFLASH_PREPCMD(32, 0, 0,
1672 NAND_SFCMD_CMDXS,
1673 NAND_SFCMD_ASYNC,
1674 NAND_SFCMD_DATWR);
1675 data->sfcmd[5] = SFLASH_PREPCMD(7, 0, 0,
1676 NAND_SFCMD_CMDXS,
1677 NAND_SFCMD_ASYNC,
1678 NAND_SFCMD_REGWR);
1679 data->sfcmd[6] = SFLASH_PREPCMD(0, 0, 32,
1680 NAND_SFCMD_CMDXS,
1681 NAND_SFCMD_ASYNC,
1682 NAND_SFCMD_INTHI);
1683 data->sfcmd[7] = SFLASH_PREPCMD(3, 7, 0,
1684 NAND_SFCMD_DATXS,
1685 NAND_SFCMD_ASYNC,
1686 NAND_SFCMD_REGRD);
1687 data->sfcmd[8] = SFLASH_PREPCMD(4, 10, 0,
1688 NAND_SFCMD_CMDXS,
1689 NAND_SFCMD_ASYNC,
1690 NAND_SFCMD_REGWR);
1691 data->sfexec = 1;
1692
1693 data->sfstat[0] = CLEAN_DATA_32;
1694 data->sfstat[1] = CLEAN_DATA_32;
1695 data->sfstat[2] = CLEAN_DATA_32;
1696 data->sfstat[3] = CLEAN_DATA_32;
1697 data->sfstat[4] = CLEAN_DATA_32;
1698 data->sfstat[5] = CLEAN_DATA_32;
1699 data->sfstat[6] = CLEAN_DATA_32;
1700 data->sfstat[7] = CLEAN_DATA_32;
1701 data->sfstat[8] = CLEAN_DATA_32;
1702 data->addr0 = (ONENAND_INTERRUPT_STATUS << 16) |
1703 (ONENAND_SYSTEM_CONFIG_1);
1704 data->addr1 = (ONENAND_START_ADDRESS_8 << 16) |
1705 (ONENAND_START_ADDRESS_1);
1706 data->addr2 = (ONENAND_START_BUFFER << 16) |
1707 (ONENAND_START_ADDRESS_2);
1708 data->addr3 = (ONENAND_ECC_STATUS << 16) |
1709 (ONENAND_COMMAND);
1710 data->addr4 = (ONENAND_CONTROLLER_STATUS << 16) |
1711 (ONENAND_INTERRUPT_STATUS);
1712 data->addr5 = (ONENAND_INTERRUPT_STATUS << 16) |
1713 (ONENAND_SYSTEM_CONFIG_1);
1714 data->addr6 = (ONENAND_START_ADDRESS_3 << 16) |
1715 (ONENAND_START_ADDRESS_1);
1716 data->data0 = (ONENAND_CLRINTR << 16) |
1717 (onenand_sysconfig1);
1718 data->data1 = (onenand_startaddr8 << 16) |
1719 (onenand_startaddr1);
1720 data->data2 = (onenand_startbuffer << 16) |
1721 (onenand_startaddr2);
1722 data->data3 = (CLEAN_DATA_16 << 16) |
1723 (ONENAND_CMDPROGSPARE);
1724 data->data3 = (CLEAN_DATA_16 << 16) |
1725 (ONENAND_CMDPROGSPARE);
1726 data->data4 = (CLEAN_DATA_16 << 16) |
1727 (CLEAN_DATA_16);
1728 data->data5 = (ONENAND_CLRINTR << 16) |
1729 (ONENAND_SYSCFG1_ECCENA);
1730 data->data6 = (ONENAND_STARTADDR3_RES << 16) |
1731 (ONENAND_STARTADDR1_RES);
1732 data->macro[0] = 0x0200;
1733 data->macro[1] = 0x0300;
1734 data->macro[2] = 0x0400;
1735 data->macro[3] = 0x0500;
1736 data->macro[4] = 0x8010;
1737
1738
1739 /*************************************************************/
1740 /* Write the data ram area in the onenand buffer ram */
1741 /*************************************************************/
1742
1743 /* Enable and configure the SFlash controller */
1744 cmd->cmd = 0 | CMD_OCB;
1745 cmd->src = paddr(&data->sfbcfg);
1746 cmd->dst = NAND_SFLASHC_BURST_CFG;
1747 cmd->len = 4;
1748 cmd++;
1749
1750 if (addr) {
1751 data->data3 = (CLEAN_DATA_16 << 16) |
1752 (ONENAND_CMDPROG);
1753
1754 for (i = 0; i < 4; i++) {
1755
1756 /* Block on cmd ready and write CMD register */
1757 cmd->cmd = DST_CRCI_NAND_CMD;
1758 cmd->src = paddr(&data->sfcmd[i]);
1759 cmd->dst = NAND_SFLASHC_CMD;
1760 cmd->len = 4;
1761 cmd++;
1762
1763 /* Trnsfr usr buf contents to nand ctlr buf */
1764 cmd->cmd = 0;
1765 cmd->src = paddr(addr_curr);
1766 cmd->dst = NAND_FLASH_BUFFER;
1767 cmd->len = 512;
Shashank Mittald0c836d2009-11-20 10:31:18 -08001768 if(!raw_mode)
1769 addr_curr += 512;
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001770 cmd++;
1771
1772 /* Write the MACRO1 register */
1773 cmd->cmd = 0;
1774 cmd->src = paddr(&data->macro[i]);
1775 cmd->dst = NAND_MACRO1_REG;
1776 cmd->len = 4;
1777 cmd++;
1778
1779 /* Kick the execute command */
1780 cmd->cmd = 0;
1781 cmd->src = paddr(&data->sfexec);
1782 cmd->dst = NAND_SFLASHC_EXEC_CMD;
1783 cmd->len = 4;
1784 cmd++;
1785
1786 /* Block on data rdy, & read status register */
1787 cmd->cmd = SRC_CRCI_NAND_DATA;
1788 cmd->src = NAND_SFLASHC_STATUS;
1789 cmd->dst = paddr(&data->sfstat[i]);
1790 cmd->len = 4;
1791 cmd++;
1792
1793 }
1794 }
1795
1796 /* Block on cmd ready and write CMD register */
1797 cmd->cmd = DST_CRCI_NAND_CMD;
1798 cmd->src = paddr(&data->sfcmd[4]);
1799 cmd->dst = NAND_SFLASHC_CMD;
1800 cmd->len = 4;
1801 cmd++;
1802
1803 if (spareaddr)
1804 {
1805 // Auto mode
1806 for (i = 0, k = 0; i < 8; i++) {
1807 for (j = 0; j < oobfree_length[i]; j++) {
1808 flash_oob[j+oobfree_offset[i]] = spareaddr[k];
1809 k++;
1810 }
1811 }
1812
1813 cmd->cmd = 0;
1814 cmd->src = paddr(&flash_oob);
1815 cmd->dst = NAND_FLASH_BUFFER;
1816 cmd->len = 64;
1817 cmd++;
1818 }
1819
Shashank Mittald0c836d2009-11-20 10:31:18 -08001820 if (raw_mode){
1821 cmd->cmd = 0;
1822 cmd->src = paddr(addr_curr);
1823 cmd->dst = NAND_FLASH_BUFFER;
1824 cmd->len = 64;
1825 cmd++;
1826 }
1827
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001828 /* Write the MACRO1 register */
1829 cmd->cmd = 0;
1830 cmd->src = paddr(&data->macro[4]);
1831 cmd->dst = NAND_MACRO1_REG;
1832 cmd->len = 4;
1833 cmd++;
1834
1835 /* Kick the execute command */
1836 cmd->cmd = 0;
1837 cmd->src = paddr(&data->sfexec);
1838 cmd->dst = NAND_SFLASHC_EXEC_CMD;
1839 cmd->len = 4;
1840 cmd++;
1841
1842 /* Block on data ready, and read the status register */
1843 cmd->cmd = SRC_CRCI_NAND_DATA;
1844 cmd->src = NAND_SFLASHC_STATUS;
1845 cmd->dst = paddr(&data->sfstat[4]);
1846 cmd->len = 4;
1847 cmd++;
1848
1849 /*************************************************************/
1850 /* Write necessary address registers in the onenand device */
1851 /*************************************************************/
1852
1853 /* Block on cmd ready and write CMD register */
1854 cmd->cmd = DST_CRCI_NAND_CMD;
1855 cmd->src = paddr(&data->sfcmd[5]);
1856 cmd->dst = NAND_SFLASHC_CMD;
1857 cmd->len = 4;
1858 cmd++;
1859
1860 /* Write the ADDR0 and ADDR1 registers */
1861 cmd->cmd = 0;
1862 cmd->src = paddr(&data->addr0);
1863 cmd->dst = NAND_ADDR0;
1864 cmd->len = 8;
1865 cmd++;
1866
1867 /* Write the ADDR2 ADDR3 ADDR4 ADDR5 registers */
1868 cmd->cmd = 0;
1869 cmd->src = paddr(&data->addr2);
1870 cmd->dst = NAND_ADDR2;
1871 cmd->len = 16;
1872 cmd++;
1873
1874 /* Write the ADDR6 registers */
1875 cmd->cmd = 0;
1876 cmd->src = paddr(&data->addr6);
1877 cmd->dst = NAND_ADDR6;
1878 cmd->len = 4;
1879 cmd++;
1880
1881 /* Write the GENP0, GENP1, GENP2, GENP3 registers */
1882 cmd->cmd = 0;
1883 cmd->src = paddr(&data->data0);
1884 cmd->dst = NAND_GENP_REG0;
1885 cmd->len = 16;
1886 cmd++;
1887
1888 /* Write the FLASH_DEV_CMD4,5,6 registers */
1889 cmd->cmd = 0;
1890 cmd->src = paddr(&data->data4);
1891 cmd->dst = NAND_DEV_CMD4;
1892 cmd->len = 12;
1893 cmd++;
1894
1895 /* Kick the execute command */
1896 cmd->cmd = 0;
1897 cmd->src = paddr(&data->sfexec);
1898 cmd->dst = NAND_SFLASHC_EXEC_CMD;
1899 cmd->len = 4;
1900 cmd++;
1901
1902 /* Block on data ready, and read the status register */
1903 cmd->cmd = SRC_CRCI_NAND_DATA;
1904 cmd->src = NAND_SFLASHC_STATUS;
1905 cmd->dst = paddr(&data->sfstat[5]);
1906 cmd->len = 4;
1907 cmd++;
1908
1909 /*************************************************************/
1910 /* Wait for the interrupt from the Onenand device controller */
1911 /*************************************************************/
1912
1913 /* Block on cmd ready and write CMD register */
1914 cmd->cmd = DST_CRCI_NAND_CMD;
1915 cmd->src = paddr(&data->sfcmd[6]);
1916 cmd->dst = NAND_SFLASHC_CMD;
1917 cmd->len = 4;
1918 cmd++;
1919
1920 /* Kick the execute command */
1921 cmd->cmd = 0;
1922 cmd->src = paddr(&data->sfexec);
1923 cmd->dst = NAND_SFLASHC_EXEC_CMD;
1924 cmd->len = 4;
1925 cmd++;
1926
1927 /* Block on data ready, and read the status register */
1928 cmd->cmd = SRC_CRCI_NAND_DATA;
1929 cmd->src = NAND_SFLASHC_STATUS;
1930 cmd->dst = paddr(&data->sfstat[6]);
1931 cmd->len = 4;
1932 cmd++;
1933
1934 /*************************************************************/
1935 /* Read necessary status registers from the onenand device */
1936 /*************************************************************/
1937
1938 /* Block on cmd ready and write CMD register */
1939 cmd->cmd = DST_CRCI_NAND_CMD;
1940 cmd->src = paddr(&data->sfcmd[7]);
1941 cmd->dst = NAND_SFLASHC_CMD;
1942 cmd->len = 4;
1943 cmd++;
1944
1945 /* Kick the execute command */
1946 cmd->cmd = 0;
1947 cmd->src = paddr(&data->sfexec);
1948 cmd->dst = NAND_SFLASHC_EXEC_CMD;
1949 cmd->len = 4;
1950 cmd++;
1951
1952 /* Block on data ready, and read the status register */
1953 cmd->cmd = SRC_CRCI_NAND_DATA;
1954 cmd->src = NAND_SFLASHC_STATUS;
1955 cmd->dst = paddr(&data->sfstat[7]);
1956 cmd->len = 4;
1957 cmd++;
1958
1959 /* Read the GENP3 register */
1960 cmd->cmd = 0;
1961 cmd->src = NAND_GENP_REG3;
1962 cmd->dst = paddr(&data->data3);
1963 cmd->len = 4;
1964 cmd++;
1965
1966 /* Read the DEVCMD4 register */
1967 cmd->cmd = 0;
1968 cmd->src = NAND_DEV_CMD4;
1969 cmd->dst = paddr(&data->data4);
1970 cmd->len = 4;
1971 cmd++;
1972
1973
1974 /*************************************************************/
1975 /* Restore the necessary registers to proper values */
1976 /*************************************************************/
1977
1978 /* Block on cmd ready and write CMD register */
1979 cmd->cmd = DST_CRCI_NAND_CMD;
1980 cmd->src = paddr(&data->sfcmd[8]);
1981 cmd->dst = NAND_SFLASHC_CMD;
1982 cmd->len = 4;
1983 cmd++;
1984
1985 /* Kick the execute command */
1986 cmd->cmd = 0;
1987 cmd->src = paddr(&data->sfexec);
1988 cmd->dst = NAND_SFLASHC_EXEC_CMD;
1989 cmd->len = 4;
1990 cmd++;
1991
1992 /* Block on data ready, and read the status register */
1993 cmd->cmd = SRC_CRCI_NAND_DATA | CMD_OCU | CMD_LC;
1994 cmd->src = NAND_SFLASHC_STATUS;
1995 cmd->dst = paddr(&data->sfstat[8]);
1996 cmd->len = 4;
1997 cmd++;
1998
1999
2000 ptr[0] = (paddr(cmdlist) >> 3) | CMD_PTR_LP;
2001
2002 dmov_exec_cmdptr(DMOV_NAND_CHAN, ptr);
2003
2004 ecc_status = (data->data3 >> 16) & 0x0000FFFF;
2005 interrupt_status = (data->data4 >> 0)&0x0000FFFF;
2006 controller_status = (data->data4 >> 16)&0x0000FFFF;
2007
2008#if VERBOSE
2009 dprintf(INFO, "\n%s: sflash status %x %x %x %x %x %x %x %x %x\n", __func__,
2010 data->sfstat[0],
2011 data->sfstat[1],
2012 data->sfstat[2],
2013 data->sfstat[3],
2014 data->sfstat[4],
2015 data->sfstat[5],
2016 data->sfstat[6],
2017 data->sfstat[7],
2018 data->sfstat[8]);
2019
2020 dprintf(INFO, "%s: controller_status = %x\n", __func__,
2021 controller_status);
2022 dprintf(INFO, "%s: interrupt_status = %x\n", __func__,
2023 interrupt_status);
2024 dprintf(INFO, "%s: ecc_status = %x\n", __func__,
2025 ecc_status);
2026#endif
2027 /* Check for errors, protection violations etc */
2028 if ((controller_status != 0)
2029 || (data->sfstat[5] & 0x110)
2030 || (data->sfstat[6] & 0x110)
2031 || (data->sfstat[7] & 0x110)
2032 || (data->sfstat[8] & 0x110)
2033 || ((data->sfstat[0] & 0x110) &&
2034 (addr))
2035 || ((data->sfstat[1] & 0x110) &&
2036 (addr))
2037 || ((data->sfstat[2] & 0x110) &&
2038 (addr))
2039 || ((data->sfstat[3] & 0x110) &&
2040 (addr))) {
2041 dprintf(CRITICAL, "%s: ECC/MPU/OP error\n", __func__);
2042 return -1;
2043 }
2044
2045
2046 return 0;
2047}
Shashank Mittald0c836d2009-11-20 10:31:18 -08002048
2049static int flash_onenand_mark_badblock(dmov_s *cmdlist, unsigned *ptrlist, unsigned page)
2050{
2051 memset(empty_buf,0,528);
2052 /* Going to first page of the block */
2053 if(page & 63)
2054 page = page - (page & 63);
2055 return _flash_onenand_write_page(cmdlist, ptrlist, page, empty_buf, 0, 1);
2056}
2057
2058static int flash_mark_badblock(dmov_s *cmdlist, unsigned *ptrlist, unsigned page)
2059{
2060 switch(flash_info.type) {
2061 case FLASH_8BIT_NAND_DEVICE:
2062 case FLASH_16BIT_NAND_DEVICE:
2063 return flash_nand_mark_badblock(cmdlist, ptrlist, page);
2064 case FLASH_ONENAND_DEVICE:
2065 return flash_onenand_mark_badblock(cmdlist, ptrlist, page);
2066 default:
2067 return -1;
2068 }
2069}
2070
2071
Shashank Mittalc20b5a12009-11-18 19:35:30 -08002072/* Wrapper functions */
2073static void flash_read_id(dmov_s *cmdlist, unsigned *ptrlist)
2074{
2075 int dev_found = 0;
2076 unsigned index;
2077
2078 // Try to read id
2079 flash_nand_read_id(cmdlist, ptrlist);
2080 // Check if we support the device
2081 for (index=1;
2082 index < (sizeof(supported_flash)/sizeof(struct flash_identification));
2083 index++)
2084 {
2085 if ((flash_info.id & supported_flash[index].mask) ==
2086 (supported_flash[index].flash_id &
2087 (supported_flash[index].mask))) {
2088 dev_found = 1;
2089 break;
2090 }
2091 }
2092
2093 if(!dev_found) {
2094 flash_onenand_read_id(cmdlist, ptrlist);
2095 for (index=1;
2096 index < (sizeof(supported_flash)/sizeof(struct flash_identification));
2097 index++)
2098 {
2099 if ((flash_info.id & supported_flash[index].mask) ==
2100 (supported_flash[index].flash_id &
2101 (supported_flash[index].mask))) {
2102 dev_found = 1;
2103 break;
2104 }
2105 }
2106 }
2107
2108
2109
2110 if(dev_found) {
2111 if (supported_flash[index].widebus)
2112 flash_info.type = FLASH_16BIT_NAND_DEVICE;
2113 else
2114 flash_info.type = FLASH_8BIT_NAND_DEVICE;
2115 if (supported_flash[index].onenand)
2116 flash_info.type = FLASH_ONENAND_DEVICE;
2117 flash_info.page_size = supported_flash[index].pagesize;
Shashank Mittaldcc2e352009-11-19 19:11:16 -08002118 flash_pagesize = flash_info.page_size;
Shashank Mittalc20b5a12009-11-18 19:35:30 -08002119 flash_info.block_size = supported_flash[index].blksize;
2120 flash_info.spare_size = supported_flash[index].oobsize;
2121 if (flash_info.block_size && flash_info.page_size)
2122 {
2123 flash_info.num_blocks = supported_flash[index].density;
2124 flash_info.num_blocks /= (flash_info.block_size * flash_info.page_size);
2125 }
2126 else
2127 {
2128 flash_info.num_blocks = 0;
2129 }
2130 ASSERT(flash_info.num_blocks);
2131 return;
2132 }
2133
2134 // Assume 8 bit nand device for backward compatability
2135 if (dev_found == 0) {
2136 dprintf(INFO, "Device not supported. Assuming 8 bit NAND device\n");
2137 flash_info.type = FLASH_8BIT_NAND_DEVICE;
2138 }
2139 dprintf(INFO, "nandid: 0x%x maker=0x%02x device=0x%02x page_size=%d\n",
2140 flash_info.id, flash_info.vendor, flash_info.device,
2141 flash_info.page_size);
2142 dprintf(INFO, " spare_size=%d block_size=%d num_blocks=%d\n",
2143 flash_info.spare_size, flash_info.block_size,
2144 flash_info.num_blocks);
2145}
2146
2147static int flash_erase_block(dmov_s *cmdlist, unsigned *ptrlist, unsigned page)
2148{
2149 switch(flash_info.type) {
2150 case FLASH_8BIT_NAND_DEVICE:
2151 case FLASH_16BIT_NAND_DEVICE:
2152 return flash_nand_erase_block(cmdlist, ptrlist, page);
2153 case FLASH_ONENAND_DEVICE:
2154 return flash_onenand_erase_block(cmdlist, ptrlist, page);
2155 default:
2156 return -1;
2157 }
2158}
2159
2160static int _flash_read_page(dmov_s *cmdlist, unsigned *ptrlist,
2161 unsigned page, void *_addr, void *_spareaddr)
2162{
2163 switch(flash_info.type) {
2164 case FLASH_8BIT_NAND_DEVICE:
2165 case FLASH_16BIT_NAND_DEVICE:
2166 return _flash_nand_read_page(cmdlist, ptrlist, page, _addr, _spareaddr);
2167 case FLASH_ONENAND_DEVICE:
Shashank Mittalad3d05c2009-11-19 15:53:57 -08002168 return _flash_onenand_read_page(cmdlist, ptrlist, page, _addr, _spareaddr, 0);
Shashank Mittalc20b5a12009-11-18 19:35:30 -08002169 default:
2170 return -1;
2171 }
2172}
2173
Shashank Mittalad3d05c2009-11-19 15:53:57 -08002174static int _flash_block_isbad(dmov_s *cmdlist, unsigned *ptrlist, unsigned page)
2175{
2176 switch(flash_info.type) {
2177 case FLASH_8BIT_NAND_DEVICE:
2178 case FLASH_16BIT_NAND_DEVICE:
2179 return flash_nand_block_isbad(cmdlist, ptrlist, page);
2180 case FLASH_ONENAND_DEVICE:
2181 return flash_onenand_block_isbad(cmdlist, ptrlist, page);
2182 default:
2183 return -1;
2184 }
2185}
Shashank Mittalc20b5a12009-11-18 19:35:30 -08002186
2187static int _flash_write_page(dmov_s *cmdlist, unsigned *ptrlist,
2188 unsigned page, const void *_addr,
2189 const void *_spareaddr)
2190{
2191 switch(flash_info.type) {
2192 case FLASH_8BIT_NAND_DEVICE:
2193 case FLASH_16BIT_NAND_DEVICE:
Shashank Mittald0c836d2009-11-20 10:31:18 -08002194 return _flash_nand_write_page(cmdlist, ptrlist, page, _addr, _spareaddr, 0);
Shashank Mittalc20b5a12009-11-18 19:35:30 -08002195 case FLASH_ONENAND_DEVICE:
Shashank Mittald0c836d2009-11-20 10:31:18 -08002196 return _flash_onenand_write_page(cmdlist, ptrlist, page, _addr, _spareaddr, 0);
Shashank Mittalc20b5a12009-11-18 19:35:30 -08002197 default:
2198 return -1;
2199 }
2200}
2201
Dima Zavin03cf4312009-01-23 16:38:30 -08002202static unsigned *flash_ptrlist;
2203static dmov_s *flash_cmdlist;
Dima Zavin03cf4312009-01-23 16:38:30 -08002204
2205static struct ptable *flash_ptable = NULL;
2206
Dima Zavine5f64352009-03-02 16:04:20 -08002207void flash_init(void)
Dima Zavin03cf4312009-01-23 16:38:30 -08002208{
Dima Zavine5f64352009-03-02 16:04:20 -08002209 ASSERT(flash_ptable == NULL);
Dima Zavin03cf4312009-01-23 16:38:30 -08002210
2211 flash_ptrlist = memalign(32, 1024);
2212 flash_cmdlist = memalign(32, 1024);
Ajay Dudani232ce812009-12-02 00:14:11 -08002213 flash_data = memalign(32, 4096 + 128);
2214 flash_spare = memalign(32, 128);
Dima Zavin03cf4312009-01-23 16:38:30 -08002215
Dima Zavin03cf4312009-01-23 16:38:30 -08002216 flash_read_id(flash_cmdlist, flash_ptrlist);
Shashank Mittal83d16d02009-11-18 16:54:42 -08002217 if((FLASH_8BIT_NAND_DEVICE == flash_info.type)
2218 ||(FLASH_16BIT_NAND_DEVICE == flash_info.type)) {
Shashank Mittalc20b5a12009-11-18 19:35:30 -08002219 if(flash_nand_read_config(flash_cmdlist, flash_ptrlist)) {
Shashank Mittal83d16d02009-11-18 16:54:42 -08002220 dprintf(CRITICAL, "ERROR: could not read CFG0/CFG1 state\n");
2221 ASSERT(0);
2222 }
2223 }
Dima Zavin03cf4312009-01-23 16:38:30 -08002224}
2225
2226struct ptable *flash_get_ptable(void)
2227{
2228 return flash_ptable;
2229}
2230
Dima Zavine5f64352009-03-02 16:04:20 -08002231void flash_set_ptable(struct ptable *new_ptable)
2232{
2233 ASSERT(flash_ptable == NULL && new_ptable != NULL);
2234 flash_ptable = new_ptable;
2235}
2236
Dima Zavinca337f52009-03-02 16:41:44 -08002237struct flash_info *flash_get_info(void)
2238{
2239 return &flash_info;
2240}
2241
Dima Zavin03cf4312009-01-23 16:38:30 -08002242int flash_erase(struct ptentry *ptn)
2243{
2244 unsigned block = ptn->start;
2245 unsigned count = ptn->length;
2246
2247 while(count-- > 0) {
2248 if(flash_erase_block(flash_cmdlist, flash_ptrlist, block * 64)) {
2249 dprintf(INFO, "cannot erase @ %d (bad block?)\n", block);
2250 }
2251 block++;
2252 }
2253 return 0;
2254}
2255
2256int flash_read_ext(struct ptentry *ptn, unsigned extra_per_page,
Shashank Mittalc20b5a12009-11-18 19:35:30 -08002257 unsigned offset, void *data, unsigned bytes)
Dima Zavin03cf4312009-01-23 16:38:30 -08002258{
Shashank Mittaldcc2e352009-11-19 19:11:16 -08002259 unsigned page = (ptn->start * 64) + (offset / flash_pagesize);
Dima Zavin03cf4312009-01-23 16:38:30 -08002260 unsigned lastpage = (ptn->start + ptn->length) * 64;
Shashank Mittaldcc2e352009-11-19 19:11:16 -08002261 unsigned count = (bytes + flash_pagesize - 1 + extra_per_page) / (flash_pagesize + extra_per_page);
Dima Zavin03cf4312009-01-23 16:38:30 -08002262 unsigned *spare = (unsigned*) flash_spare;
2263 unsigned errors = 0;
2264 unsigned char *image = data;
Shashank Mittalad3d05c2009-11-19 15:53:57 -08002265 unsigned current_block = (page - (page & 63)) >> 6;
2266 unsigned start_block = ptn->start;
2267 int result = 0;
2268 int isbad = 0;
Dima Zavin03cf4312009-01-23 16:38:30 -08002269
Shashank Mittaldcc2e352009-11-19 19:11:16 -08002270 if(offset & (flash_pagesize - 1))
Dima Zavin03cf4312009-01-23 16:38:30 -08002271 return -1;
2272
Shashank Mittalad3d05c2009-11-19 15:53:57 -08002273 // Adjust page offset based on number of bad blocks from start to current page
2274 while (start_block < current_block) {
2275 isbad = _flash_block_isbad(flash_cmdlist, flash_ptrlist, start_block*64);
2276 if (isbad)
2277 page += 64;
2278
2279 start_block++;
2280 }
2281
Dima Zavin03cf4312009-01-23 16:38:30 -08002282 while(page < lastpage) {
2283 if(count == 0) {
2284 dprintf(INFO, "flash_read_image: success (%d errors)\n", errors);
2285 return 0;
2286 }
2287
Shashank Mittalad3d05c2009-11-19 15:53:57 -08002288 result = _flash_read_page(flash_cmdlist, flash_ptrlist, page, image, spare);
2289
2290 if (result == -1) {
2291 // bad page, go to next page
2292 page++;
Dima Zavin03cf4312009-01-23 16:38:30 -08002293 errors++;
2294 continue;
2295 }
Shashank Mittalad3d05c2009-11-19 15:53:57 -08002296 else if (result == -2) {
2297 // bad block, go to next block same offset
2298 page += 64;
2299 errors++;
2300 continue;
2301 }
2302
2303 page++;
Shashank Mittaldcc2e352009-11-19 19:11:16 -08002304 image += flash_pagesize;
Dima Zavin03cf4312009-01-23 16:38:30 -08002305 memcpy(image, spare, extra_per_page);
2306 image += extra_per_page;
2307 count -= 1;
2308 }
2309
2310 /* could not find enough valid pages before we hit the end */
2311 dprintf(INFO, "flash_read_image: failed (%d errors)\n", errors);
2312 return 0xffffffff;
2313}
2314
2315int flash_write(struct ptentry *ptn, unsigned extra_per_page, const void *data,
2316 unsigned bytes)
2317{
2318 unsigned page = ptn->start * 64;
2319 unsigned lastpage = (ptn->start + ptn->length) * 64;
2320 unsigned *spare = (unsigned*) flash_spare;
2321 const unsigned char *image = data;
Shashank Mittaldcc2e352009-11-19 19:11:16 -08002322 unsigned wsize = flash_pagesize + extra_per_page;
Dima Zavin03cf4312009-01-23 16:38:30 -08002323 unsigned n;
2324 int r;
2325
2326 for(n = 0; n < 16; n++) spare[n] = 0xffffffff;
2327
2328 while(bytes > 0) {
2329 if(bytes < wsize) {
2330 dprintf(CRITICAL, "flash_write_image: image undersized (%d < %d)\n", bytes, wsize);
2331 return -1;
2332 }
2333 if(page >= lastpage) {
2334 dprintf(CRITICAL, "flash_write_image: out of space\n");
2335 return -1;
2336 }
2337
2338 if((page & 63) == 0) {
2339 if(flash_erase_block(flash_cmdlist, flash_ptrlist, page)) {
2340 dprintf(INFO, "flash_write_image: bad block @ %d\n", page >> 6);
2341 page += 64;
2342 continue;
2343 }
2344 }
2345
2346 if(extra_per_page) {
Shashank Mittald0c836d2009-11-20 10:31:18 -08002347 r = _flash_write_page(flash_cmdlist, flash_ptrlist, page, image, image + flash_pagesize);
Dima Zavin03cf4312009-01-23 16:38:30 -08002348 } else {
Shashank Mittald0c836d2009-11-20 10:31:18 -08002349 r = _flash_write_page(flash_cmdlist, flash_ptrlist, page, image, spare);
Dima Zavin03cf4312009-01-23 16:38:30 -08002350 }
2351 if(r) {
2352 dprintf(INFO, "flash_write_image: write failure @ page %d (src %d)\n", page, image - (const unsigned char *)data);
2353 image -= (page & 63) * wsize;
2354 bytes += (page & 63) * wsize;
2355 page &= ~63;
2356 if(flash_erase_block(flash_cmdlist, flash_ptrlist, page)) {
2357 dprintf(INFO, "flash_write_image: erase failure @ page %d\n", page);
2358 }
Shashank Mittald0c836d2009-11-20 10:31:18 -08002359 flash_mark_badblock(flash_cmdlist, flash_ptrlist, page);
Dima Zavin03cf4312009-01-23 16:38:30 -08002360 dprintf(INFO, "flash_write_image: restart write @ page %d (src %d)\n", page, image - (const unsigned char *)data);
2361 page += 64;
2362 continue;
2363 }
Shashank Mittald0c836d2009-11-20 10:31:18 -08002364 page++;
Dima Zavin03cf4312009-01-23 16:38:30 -08002365 image += wsize;
2366 bytes -= wsize;
2367 }
2368
2369 /* erase any remaining pages in the partition */
2370 page = (page + 63) & (~63);
2371 while(page < lastpage){
2372 if(flash_erase_block(flash_cmdlist, flash_ptrlist, page)) {
2373 dprintf(INFO, "flash_write_image: bad block @ %d\n", page >> 6);
2374 }
2375 page += 64;
2376 }
2377
2378 dprintf(INFO, "flash_write_image: success\n");
2379 return 0;
2380}
2381
2382#if 0
2383static int flash_read_page(unsigned page, void *data, void *extra)
2384{
2385 return _flash_read_page(flash_cmdlist, flash_ptrlist,
2386 page, data, extra);
2387}
2388#endif
Shashank Mittaldcc2e352009-11-19 19:11:16 -08002389
2390unsigned flash_page_size(void)
2391{
2392 return flash_pagesize;
2393}