blob: 02be4c91611c1a8039b6d962f3b91334cceea9aa [file] [log] [blame]
Dima Zavin03cf4312009-01-23 16:38:30 -08001/*
2 * Copyright (c) 2008, Google Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in
12 * the documentation and/or other materials provided with the
13 * distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29#include <debug.h>
30#include <reg.h>
31#include <stdlib.h>
32#include <string.h>
33#include <dev/flash.h>
34#include <lib/ptable.h>
35
36#include "dmov.h"
37#include "nand.h"
38
39#define VERBOSE 0
Dima Zavin5582c7d2009-03-03 15:17:59 -080040#define VERIFY_WRITE 0
41
42static void *flash_spare;
43static void *flash_data;
Dima Zavin03cf4312009-01-23 16:38:30 -080044
45typedef struct dmov_ch dmov_ch;
46struct dmov_ch
47{
48 volatile unsigned cmd;
49 volatile unsigned result;
50 volatile unsigned status;
51 volatile unsigned config;
52};
53
54static void dmov_prep_ch(dmov_ch *ch, unsigned id)
55{
56 ch->cmd = DMOV_CMD_PTR(id);
57 ch->result = DMOV_RSLT(id);
58 ch->status = DMOV_STATUS(id);
59 ch->config = DMOV_CONFIG(id);
60}
61
62#define SRC_CRCI_NAND_CMD CMD_SRC_CRCI(DMOV_NAND_CRCI_CMD)
63#define DST_CRCI_NAND_CMD CMD_DST_CRCI(DMOV_NAND_CRCI_CMD)
64#define SRC_CRCI_NAND_DATA CMD_SRC_CRCI(DMOV_NAND_CRCI_DATA)
65#define DST_CRCI_NAND_DATA CMD_DST_CRCI(DMOV_NAND_CRCI_DATA)
66
67static unsigned CFG0, CFG1;
68
69#define CFG1_WIDE_FLASH (1U << 1)
70
71#define paddr(n) ((unsigned) (n))
72
73static int dmov_exec_cmdptr(unsigned id, unsigned *ptr)
74{
75 dmov_ch ch;
76 unsigned n;
77
78 dmov_prep_ch(&ch, id);
79
80 writel(DMOV_CMD_PTR_LIST | DMOV_CMD_ADDR(paddr(ptr)), ch.cmd);
81
82 while(!(readl(ch.status) & DMOV_STATUS_RSLT_VALID)) ;
83
84 n = readl(ch.status);
85 while(DMOV_STATUS_RSLT_COUNT(n)) {
86 n = readl(ch.result);
87 if(n != 0x80000002) {
88 dprintf(CRITICAL, "ERROR: result: %x\n", n);
89 dprintf(CRITICAL, "ERROR: flush: %x %x %x %x\n",
90 readl(DMOV_FLUSH0(DMOV_NAND_CHAN)),
91 readl(DMOV_FLUSH1(DMOV_NAND_CHAN)),
92 readl(DMOV_FLUSH2(DMOV_NAND_CHAN)),
93 readl(DMOV_FLUSH3(DMOV_NAND_CHAN)));
94 }
95 n = readl(ch.status);
96 }
97
98 return 0;
99}
100
Dima Zavinca337f52009-03-02 16:41:44 -0800101static struct flash_info flash_info;
Dima Zavin03cf4312009-01-23 16:38:30 -0800102
Shashank Mittal83d16d02009-11-18 16:54:42 -0800103struct flash_identification {
104 unsigned flash_id;
105 unsigned mask;
106 unsigned density;
107 unsigned widebus;
108 unsigned pagesize;
109 unsigned blksize;
110 unsigned oobsize;
111 unsigned onenand;
112};
113
114static struct flash_identification supported_flash[] =
115{
116 /* Flash ID ID Mask Density(MB) Wid Pgsz Blksz oobsz onenand Manuf */
117 {0x00000000, 0xFFFFFFFF, 0, 0, 0, 0, 0, 0}, /*ONFI*/
118 {0x1500aaec, 0xFF00FFFF, (256<<20), 0, 2048, (2048<<6), 64, 0}, /*Sams*/
119 {0x5500baec, 0xFF00FFFF, (256<<20), 1, 2048, (2048<<6), 64, 0}, /*Sams*/
120 {0x1500aa98, 0xFFFFFFFF, (256<<20), 0, 2048, (2048<<6), 64, 0}, /*Tosh*/
121 {0x5500ba98, 0xFFFFFFFF, (256<<20), 1, 2048, (2048<<6), 64, 0}, /*Tosh*/
122 {0xd580b12c, 0xFFFFFFFF, (128<<20), 1, 2048, (2048<<6), 64, 0}, /*Micr*/
123 {0x5590bc2c, 0xFFFFFFFF, (128<<20), 1, 2048, (2048<<6), 64, 0}, /*Micr*/
124 {0x5580baad, 0xFFFFFFFF, (256<<20), 1, 2048, (2048<<6), 64, 0}, /*Hynx*/
125 {0x5510baad, 0xFFFFFFFF, (256<<20), 1, 2048, (2048<<6), 64, 0}, /*Hynx*/
126 {0x004000ec, 0xFFFFFFFF, (256<<20), 0, 2048, (2048<<6), 64, 1}, /*Hynx*/
127 /* Note: Width flag is 0 for 8 bit Flash and 1 for 16 bit flash */
128 /* Note: Onenand flag is 0 for NAND Flash and 1 for OneNAND flash */
129 /* Note: The First row will be filled at runtime during ONFI probe */
130};
131
132static void flash_nand_read_id(dmov_s *cmdlist, unsigned *ptrlist)
Dima Zavin03cf4312009-01-23 16:38:30 -0800133{
134 dmov_s *cmd = cmdlist;
135 unsigned *ptr = ptrlist;
136 unsigned *data = ptrlist + 4;
137
138 data[0] = 0 | 4;
139 data[1] = NAND_CMD_FETCH_ID;
140 data[2] = 1;
141 data[3] = 0;
142 data[4] = 0;
143
144 cmd[0].cmd = 0 | CMD_OCB;
145 cmd[0].src = paddr(&data[0]);
146 cmd[0].dst = NAND_FLASH_CHIP_SELECT;
147 cmd[0].len = 4;
148
149 cmd[1].cmd = DST_CRCI_NAND_CMD;
150 cmd[1].src = paddr(&data[1]);
151 cmd[1].dst = NAND_FLASH_CMD;
152 cmd[1].len = 4;
153
154 cmd[2].cmd = 0;
155 cmd[2].src = paddr(&data[2]);
156 cmd[2].dst = NAND_EXEC_CMD;
157 cmd[2].len = 4;
158
159 cmd[3].cmd = SRC_CRCI_NAND_DATA;
160 cmd[3].src = NAND_FLASH_STATUS;
161 cmd[3].dst = paddr(&data[3]);
162 cmd[3].len = 4;
163
164 cmd[4].cmd = CMD_OCU | CMD_LC;
165 cmd[4].src = NAND_READ_ID;
166 cmd[4].dst = paddr(&data[4]);
167 cmd[4].len = 4;
168
169 ptr[0] = (paddr(cmd) >> 3) | CMD_PTR_LP;
170
171 dmov_exec_cmdptr(DMOV_NAND_CHAN, ptr);
172
173#if VERBOSE
174 dprintf(INFO, "status: %x\n", data[3]);
175#endif
Dima Zavin03cf4312009-01-23 16:38:30 -0800176
Shashank Mittal83d16d02009-11-18 16:54:42 -0800177 flash_info.id = data[4];
Dima Zavinca337f52009-03-02 16:41:44 -0800178 flash_info.vendor = data[4] & 0xff;
179 flash_info.device = (data[4] >> 8) & 0xff;
Shashank Mittal83d16d02009-11-18 16:54:42 -0800180 return;
181}
Dima Zavinca337f52009-03-02 16:41:44 -0800182
Shashank Mittal83d16d02009-11-18 16:54:42 -0800183static void flash_read_id(dmov_s *cmdlist, unsigned *ptrlist)
184{
185 int dev_found = 0;
186 unsigned index;
Dima Zavinca337f52009-03-02 16:41:44 -0800187
Shashank Mittal83d16d02009-11-18 16:54:42 -0800188 // TODO: support for OneNAND detection
Dima Zavinca337f52009-03-02 16:41:44 -0800189
Shashank Mittal83d16d02009-11-18 16:54:42 -0800190 // Try to read id
191 flash_nand_read_id(cmdlist, ptrlist);
192 // Check if we support the device
193 for (index=1;
194 index < (sizeof(supported_flash)/sizeof(struct flash_identification));
195 index++)
196 {
197 if ((flash_info.id & supported_flash[index].mask) ==
198 (supported_flash[index].flash_id &
199 (supported_flash[index].mask))) {
200 dev_found = 1;
201 break;
202 }
203 }
204
205 if(dev_found) {
206 if (supported_flash[index].widebus)
207 flash_info.type = FLASH_16BIT_NAND_DEVICE;
208 else
209 flash_info.type = FLASH_8BIT_NAND_DEVICE;
210
211 flash_info.page_size = supported_flash[index].pagesize;
212 flash_info.block_size = supported_flash[index].blksize;
213 flash_info.spare_size = supported_flash[index].oobsize;
214 if (flash_info.block_size && flash_info.page_size)
215 {
216 flash_info.num_blocks = supported_flash[index].density;
217 flash_info.num_blocks /= (flash_info.block_size * flash_info.page_size);
218 }
219 else
220 {
221 flash_info.num_blocks = 0;
222 }
223 ASSERT(flash_info.num_blocks);
224 return;
225 }
226
227 // Assume 8 bit nand device for backward compatability
228 if (dev_found == 0) {
229 dprintf(INFO, "Device not supported. Assuming 8 bit NAND device\n");
230 flash_info.type = FLASH_8BIT_NAND_DEVICE;
231 }
Dima Zavinca337f52009-03-02 16:41:44 -0800232 dprintf(INFO, "nandid: 0x%x maker=0x%02x device=0x%02x page_size=%d\n",
Shashank Mittal83d16d02009-11-18 16:54:42 -0800233 flash_info.id, flash_info.vendor, flash_info.device,
Dima Zavinca337f52009-03-02 16:41:44 -0800234 flash_info.page_size);
235 dprintf(INFO, " spare_size=%d block_size=%d num_blocks=%d\n",
236 flash_info.spare_size, flash_info.block_size,
237 flash_info.num_blocks);
Dima Zavin03cf4312009-01-23 16:38:30 -0800238}
239
240static int flash_erase_block(dmov_s *cmdlist, unsigned *ptrlist, unsigned page)
241{
242 dmov_s *cmd = cmdlist;
243 unsigned *ptr = ptrlist;
244 unsigned *data = ptrlist + 4;
245
246 /* only allow erasing on block boundaries */
247 if(page & 63) return -1;
248
249 data[0] = NAND_CMD_BLOCK_ERASE;
250 data[1] = page;
251 data[2] = 0;
252 data[3] = 0 | 4;
253 data[4] = 1;
254 data[5] = 0xeeeeeeee;
255 data[6] = CFG0 & (~(7 << 6)); /* CW_PER_PAGE = 0 */
256 data[7] = CFG1;
257
258 cmd[0].cmd = DST_CRCI_NAND_CMD | CMD_OCB;
259 cmd[0].src = paddr(&data[0]);
260 cmd[0].dst = NAND_FLASH_CMD;
261 cmd[0].len = 16;
262
263 cmd[1].cmd = 0;
264 cmd[1].src = paddr(&data[6]);
265 cmd[1].dst = NAND_DEV0_CFG0;
266 cmd[1].len = 8;
267
268 cmd[2].cmd = 0;
269 cmd[2].src = paddr(&data[4]);
270 cmd[2].dst = NAND_EXEC_CMD;
271 cmd[2].len = 4;
272
273 cmd[3].cmd = SRC_CRCI_NAND_DATA | CMD_OCU | CMD_LC;
274 cmd[3].src = NAND_FLASH_STATUS;
275 cmd[3].dst = paddr(&data[5]);
276 cmd[3].len = 4;
277
278 ptr[0] = (paddr(cmd) >> 3) | CMD_PTR_LP;
279
280 dmov_exec_cmdptr(DMOV_NAND_CHAN, ptr);
281
282#if VERBOSE
283 dprintf(INFO, "status: %x\n", data[5]);
284#endif
285
286 /* we fail if there was an operation error, a mpu error, or the
287 ** erase success bit was not set.
288 */
289 if(data[5] & 0x110) return -1;
290 if(!(data[5] & 0x80)) return -1;
291
292 return 0;
293}
294
295struct data_flash_io {
296 unsigned cmd;
297 unsigned addr0;
298 unsigned addr1;
299 unsigned chipsel;
300 unsigned cfg0;
301 unsigned cfg1;
302 unsigned exec;
303 unsigned ecc_cfg;
304 unsigned ecc_cfg_save;
305 struct {
306 unsigned flash_status;
307 unsigned buffer_status;
308 } result[4];
309};
310
311static int _flash_read_page(dmov_s *cmdlist, unsigned *ptrlist, unsigned page, void *_addr, void *_spareaddr)
312{
313 dmov_s *cmd = cmdlist;
314 unsigned *ptr = ptrlist;
315 struct data_flash_io *data = (void*) (ptrlist + 4);
316 unsigned addr = (unsigned) _addr;
317 unsigned spareaddr = (unsigned) _spareaddr;
318 unsigned n;
319
320 data->cmd = NAND_CMD_PAGE_READ_ECC;
321 data->addr0 = page << 16;
322 data->addr1 = (page >> 16) & 0xff;
323 data->chipsel = 0 | 4; /* flash0 + undoc bit */
324
325 /* GO bit for the EXEC register */
326 data->exec = 1;
327
328 data->cfg0 = CFG0;
329 data->cfg1 = CFG1;
330
331 data->ecc_cfg = 0x203;
332
333 /* save existing ecc config */
334 cmd->cmd = CMD_OCB;
335 cmd->src = NAND_EBI2_ECC_BUF_CFG;
336 cmd->dst = paddr(&data->ecc_cfg_save);
337 cmd->len = 4;
338 cmd++;
339
340 for(n = 0; n < 4; n++) {
341 /* write CMD / ADDR0 / ADDR1 / CHIPSEL regs in a burst */
342 cmd->cmd = DST_CRCI_NAND_CMD;
343 cmd->src = paddr(&data->cmd);
344 cmd->dst = NAND_FLASH_CMD;
345 cmd->len = ((n == 0) ? 16 : 4);
346 cmd++;
347
348 if (n == 0) {
349 /* block on cmd ready, set configuration */
350 cmd->cmd = 0;
351 cmd->src = paddr(&data->cfg0);
352 cmd->dst = NAND_DEV0_CFG0;
353 cmd->len = 8;
354 cmd++;
355
356 /* set our ecc config */
357 cmd->cmd = 0;
358 cmd->src = paddr(&data->ecc_cfg);
359 cmd->dst = NAND_EBI2_ECC_BUF_CFG;
360 cmd->len = 4;
361 cmd++;
362 }
363 /* kick the execute register */
364 cmd->cmd = 0;
365 cmd->src = paddr(&data->exec);
366 cmd->dst = NAND_EXEC_CMD;
367 cmd->len = 4;
368 cmd++;
369
370 /* block on data ready, then read the status register */
371 cmd->cmd = SRC_CRCI_NAND_DATA;
372 cmd->src = NAND_FLASH_STATUS;
373 cmd->dst = paddr(&data->result[n]);
374 cmd->len = 8;
375 cmd++;
376
377 /* read data block */
378 cmd->cmd = 0;
379 cmd->src = NAND_FLASH_BUFFER;
380 cmd->dst = addr + n * 516;
381 cmd->len = ((n < 3) ? 516 : 500);
382 cmd++;
383 }
384
385 /* read extra data */
386 cmd->cmd = 0;
387 cmd->src = NAND_FLASH_BUFFER + 500;
388 cmd->dst = spareaddr;
389 cmd->len = 16;
390 cmd++;
391
392 /* restore saved ecc config */
393 cmd->cmd = CMD_OCU | CMD_LC;
394 cmd->src = paddr(&data->ecc_cfg_save);
395 cmd->dst = NAND_EBI2_ECC_BUF_CFG;
396 cmd->len = 4;
397
398 ptr[0] = (paddr(cmdlist) >> 3) | CMD_PTR_LP;
399
400 dmov_exec_cmdptr(DMOV_NAND_CHAN, ptr);
401
402#if VERBOSE
403 dprintf(INFO, "read page %d: status: %x %x %x %x\n",
404 page, data[5], data[6], data[7], data[8]);
405 for(n = 0; n < 4; n++) {
406 ptr = (unsigned*)(addr + 512 * n);
407 dprintf(INFO, "data%d: %x %x %x %x\n", n, ptr[0], ptr[1], ptr[2], ptr[3]);
408 ptr = (unsigned*)(spareaddr + 16 * n);
409 dprintf(INFO, "spare data%d %x %x %x %x\n", n, ptr[0], ptr[1], ptr[2], ptr[3]);
410 }
411#endif
412
413 /* if any of the writes failed (0x10), or there was a
414 ** protection violation (0x100), we lose
415 */
416 for(n = 0; n < 4; n++) {
417 if (data->result[n].flash_status & 0x110) {
418 return -1;
419 }
420 }
421
422 return 0;
423}
424
425static int _flash_write_page(dmov_s *cmdlist, unsigned *ptrlist, unsigned page,
426 const void *_addr, const void *_spareaddr)
427{
428 dmov_s *cmd = cmdlist;
429 unsigned *ptr = ptrlist;
430 struct data_flash_io *data = (void*) (ptrlist + 4);
431 unsigned addr = (unsigned) _addr;
432 unsigned spareaddr = (unsigned) _spareaddr;
433 unsigned n;
434
435 data->cmd = NAND_CMD_PRG_PAGE;
436 data->addr0 = page << 16;
437 data->addr1 = (page >> 16) & 0xff;
438 data->chipsel = 0 | 4; /* flash0 + undoc bit */
439
440 data->cfg0 = CFG0;
441 data->cfg1 = CFG1;
442
443 /* GO bit for the EXEC register */
444 data->exec = 1;
445
446 data->ecc_cfg = 0x203;
447
448 /* save existing ecc config */
449 cmd->cmd = CMD_OCB;
450 cmd->src = NAND_EBI2_ECC_BUF_CFG;
451 cmd->dst = paddr(&data->ecc_cfg_save);
452 cmd->len = 4;
453 cmd++;
454
455 for(n = 0; n < 4; n++) {
456 /* write CMD / ADDR0 / ADDR1 / CHIPSEL regs in a burst */
457 cmd->cmd = DST_CRCI_NAND_CMD;
458 cmd->src = paddr(&data->cmd);
459 cmd->dst = NAND_FLASH_CMD;
460 cmd->len = ((n == 0) ? 16 : 4);
461 cmd++;
462
463 if (n == 0) {
464 /* set configuration */
465 cmd->cmd = 0;
466 cmd->src = paddr(&data->cfg0);
467 cmd->dst = NAND_DEV0_CFG0;
468 cmd->len = 8;
469 cmd++;
470
471 /* set our ecc config */
472 cmd->cmd = 0;
473 cmd->src = paddr(&data->ecc_cfg);
474 cmd->dst = NAND_EBI2_ECC_BUF_CFG;
475 cmd->len = 4;
476 cmd++;
477 }
478
479 /* write data block */
480 cmd->cmd = 0;
481 cmd->src = addr + n * 516;
482 cmd->dst = NAND_FLASH_BUFFER;
483 cmd->len = ((n < 3) ? 516 : 510);
484 cmd++;
485
486 if (n == 3) {
487 /* write extra data */
488 cmd->cmd = 0;
489 cmd->src = spareaddr;
490 cmd->dst = NAND_FLASH_BUFFER + 500;
491 cmd->len = 16;
492 cmd++;
493 }
494
495 /* kick the execute register */
496 cmd->cmd = 0;
497 cmd->src = paddr(&data->exec);
498 cmd->dst = NAND_EXEC_CMD;
499 cmd->len = 4;
500 cmd++;
501
502 /* block on data ready, then read the status register */
503 cmd->cmd = SRC_CRCI_NAND_DATA;
504 cmd->src = NAND_FLASH_STATUS;
505 cmd->dst = paddr(&data->result[n]);
506 cmd->len = 8;
507 cmd++;
508 }
509
510 /* restore saved ecc config */
511 cmd->cmd = CMD_OCU | CMD_LC;
512 cmd->src = paddr(&data->ecc_cfg_save);
513 cmd->dst = NAND_EBI2_ECC_BUF_CFG;
514 cmd->len = 4;
515
516 ptr[0] = (paddr(cmdlist) >> 3) | CMD_PTR_LP;
517
518 dmov_exec_cmdptr(DMOV_NAND_CHAN, ptr);
519
520#if VERBOSE
521 dprintf(INFO, "write page %d: status: %x %x %x %x\n",
522 page, data[5], data[6], data[7], data[8]);
523#endif
524
525 /* if any of the writes failed (0x10), or there was a
526 ** protection violation (0x100), or the program success
527 ** bit (0x80) is unset, we lose
528 */
529 for(n = 0; n < 4; n++) {
530 if(data->result[n].flash_status & 0x110) return -1;
531 if(!(data->result[n].flash_status & 0x80)) return -1;
532 }
533
Dima Zavin5582c7d2009-03-03 15:17:59 -0800534#if VERIFY_WRITE
535 n = _flash_read_page(cmdlist, ptrlist, page, flash_data,
536 flash_data + 2048);
537 if (n != 0)
538 return -1;
539 if (memcmp(flash_data, _addr, 2048) ||
540 memcmp(flash_data + 2048, _spareaddr, 16)) {
541 dprintf(CRITICAL, "verify error @ page %d\n", page);
542 return -1;
543 }
544#endif
Dima Zavin03cf4312009-01-23 16:38:30 -0800545 return 0;
546}
547
Shashank Mittal83d16d02009-11-18 16:54:42 -0800548unsigned nand_cfg0;
549unsigned nand_cfg1;
550
Dima Zavin03cf4312009-01-23 16:38:30 -0800551static int flash_read_config(dmov_s *cmdlist, unsigned *ptrlist)
552{
553 cmdlist[0].cmd = CMD_OCB;
554 cmdlist[0].src = NAND_DEV0_CFG0;
555 cmdlist[0].dst = paddr(&CFG0);
556 cmdlist[0].len = 4;
557
558 cmdlist[1].cmd = CMD_OCU | CMD_LC;
559 cmdlist[1].src = NAND_DEV0_CFG1;
560 cmdlist[1].dst = paddr(&CFG1);
561 cmdlist[1].len = 4;
562
563 *ptrlist = (paddr(cmdlist) >> 3) | CMD_PTR_LP;
564
565 dmov_exec_cmdptr(DMOV_NAND_CHAN, ptrlist);
566
567 if((CFG0 == 0) || (CFG1 == 0)) {
568 return -1;
569 }
570
Shashank Mittal83d16d02009-11-18 16:54:42 -0800571 if (flash_info.type == FLASH_16BIT_NAND_DEVICE) {
572 nand_cfg1 |= CFG1_WIDE_FLASH;
573 }
Dima Zavin03cf4312009-01-23 16:38:30 -0800574 dprintf(INFO, "nandcfg: %x %x (initial)\n", CFG0, CFG1);
575
576 CFG0 = (3 << 6) /* 4 codeword per page for 2k nand */
577 | (516 << 9) /* 516 user data bytes */
578 | (10 << 19) /* 10 parity bytes */
579 | (5 << 27) /* 5 address cycles */
580 | (1 << 30) /* Read status before data */
581 | (1 << 31) /* Send read cmd */
Shashank Mittal83d16d02009-11-18 16:54:42 -0800582 /* 0 spare bytes for 16 bit nand or 1 spare bytes for 8 bit */
583 | ((nand_cfg1 & CFG1_WIDE_FLASH) ? (0 << 23) : (1 << 23));
Dima Zavin03cf4312009-01-23 16:38:30 -0800584 CFG1 = (0 << 0) /* Enable ecc */
585 | (7 << 2) /* 8 recovery cycles */
586 | (0 << 5) /* Allow CS deassertion */
587 | (465 << 6) /* Bad block marker location */
588 | (0 << 16) /* Bad block in user data area */
589 | (2 << 17) /* 6 cycle tWB/tRB */
Shashank Mittal83d16d02009-11-18 16:54:42 -0800590 | (nand_cfg1 & CFG1_WIDE_FLASH); /* preserve wide flash flag */
Dima Zavin03cf4312009-01-23 16:38:30 -0800591
592 dprintf(INFO, "nandcfg: %x %x (used)\n", CFG0, CFG1);
593
594 return 0;
595}
596
597static unsigned *flash_ptrlist;
598static dmov_s *flash_cmdlist;
Dima Zavin03cf4312009-01-23 16:38:30 -0800599
600static struct ptable *flash_ptable = NULL;
601
Dima Zavine5f64352009-03-02 16:04:20 -0800602void flash_init(void)
Dima Zavin03cf4312009-01-23 16:38:30 -0800603{
Dima Zavine5f64352009-03-02 16:04:20 -0800604 ASSERT(flash_ptable == NULL);
Dima Zavin03cf4312009-01-23 16:38:30 -0800605
606 flash_ptrlist = memalign(32, 1024);
607 flash_cmdlist = memalign(32, 1024);
Dima Zavin5582c7d2009-03-03 15:17:59 -0800608 flash_data = memalign(32, 2048 + 64);
Dima Zavin03cf4312009-01-23 16:38:30 -0800609 flash_spare = memalign(32, 64);
610
Dima Zavin03cf4312009-01-23 16:38:30 -0800611 flash_read_id(flash_cmdlist, flash_ptrlist);
Shashank Mittal83d16d02009-11-18 16:54:42 -0800612 if((FLASH_8BIT_NAND_DEVICE == flash_info.type)
613 ||(FLASH_16BIT_NAND_DEVICE == flash_info.type)) {
614 if(flash_read_config(flash_cmdlist, flash_ptrlist)) {
615 dprintf(CRITICAL, "ERROR: could not read CFG0/CFG1 state\n");
616 ASSERT(0);
617 }
618 }
Dima Zavin03cf4312009-01-23 16:38:30 -0800619}
620
621struct ptable *flash_get_ptable(void)
622{
623 return flash_ptable;
624}
625
Dima Zavine5f64352009-03-02 16:04:20 -0800626void flash_set_ptable(struct ptable *new_ptable)
627{
628 ASSERT(flash_ptable == NULL && new_ptable != NULL);
629 flash_ptable = new_ptable;
630}
631
Dima Zavinca337f52009-03-02 16:41:44 -0800632struct flash_info *flash_get_info(void)
633{
634 return &flash_info;
635}
636
Dima Zavin03cf4312009-01-23 16:38:30 -0800637int flash_erase(struct ptentry *ptn)
638{
639 unsigned block = ptn->start;
640 unsigned count = ptn->length;
641
642 while(count-- > 0) {
643 if(flash_erase_block(flash_cmdlist, flash_ptrlist, block * 64)) {
644 dprintf(INFO, "cannot erase @ %d (bad block?)\n", block);
645 }
646 block++;
647 }
648 return 0;
649}
650
651int flash_read_ext(struct ptentry *ptn, unsigned extra_per_page,
652 unsigned offset, void *data, unsigned bytes)
653{
654 unsigned page = (ptn->start * 64) + (offset / 2048);
655 unsigned lastpage = (ptn->start + ptn->length) * 64;
656 unsigned count = (bytes + 2047 + extra_per_page) / (2048 + extra_per_page);
657 unsigned *spare = (unsigned*) flash_spare;
658 unsigned errors = 0;
659 unsigned char *image = data;
660
661 if(offset & 2047)
662 return -1;
663
664 while(page < lastpage) {
665 if(count == 0) {
666 dprintf(INFO, "flash_read_image: success (%d errors)\n", errors);
667 return 0;
668 }
669
670 if(_flash_read_page(flash_cmdlist, flash_ptrlist, page++, image, spare)) {
671 errors++;
672 continue;
673 }
674 image += 2048;
675 memcpy(image, spare, extra_per_page);
676 image += extra_per_page;
677 count -= 1;
678 }
679
680 /* could not find enough valid pages before we hit the end */
681 dprintf(INFO, "flash_read_image: failed (%d errors)\n", errors);
682 return 0xffffffff;
683}
684
685int flash_write(struct ptentry *ptn, unsigned extra_per_page, const void *data,
686 unsigned bytes)
687{
688 unsigned page = ptn->start * 64;
689 unsigned lastpage = (ptn->start + ptn->length) * 64;
690 unsigned *spare = (unsigned*) flash_spare;
691 const unsigned char *image = data;
692 unsigned wsize = 2048 + extra_per_page;
693 unsigned n;
694 int r;
695
696 for(n = 0; n < 16; n++) spare[n] = 0xffffffff;
697
698 while(bytes > 0) {
699 if(bytes < wsize) {
700 dprintf(CRITICAL, "flash_write_image: image undersized (%d < %d)\n", bytes, wsize);
701 return -1;
702 }
703 if(page >= lastpage) {
704 dprintf(CRITICAL, "flash_write_image: out of space\n");
705 return -1;
706 }
707
708 if((page & 63) == 0) {
709 if(flash_erase_block(flash_cmdlist, flash_ptrlist, page)) {
710 dprintf(INFO, "flash_write_image: bad block @ %d\n", page >> 6);
711 page += 64;
712 continue;
713 }
714 }
715
716 if(extra_per_page) {
717 r = _flash_write_page(flash_cmdlist, flash_ptrlist, page++, image, image + 2048);
718 } else {
719 r = _flash_write_page(flash_cmdlist, flash_ptrlist, page++, image, spare);
720 }
721 if(r) {
722 dprintf(INFO, "flash_write_image: write failure @ page %d (src %d)\n", page, image - (const unsigned char *)data);
723 image -= (page & 63) * wsize;
724 bytes += (page & 63) * wsize;
725 page &= ~63;
726 if(flash_erase_block(flash_cmdlist, flash_ptrlist, page)) {
727 dprintf(INFO, "flash_write_image: erase failure @ page %d\n", page);
728 }
729 dprintf(INFO, "flash_write_image: restart write @ page %d (src %d)\n", page, image - (const unsigned char *)data);
730 page += 64;
731 continue;
732 }
733
734 image += wsize;
735 bytes -= wsize;
736 }
737
738 /* erase any remaining pages in the partition */
739 page = (page + 63) & (~63);
740 while(page < lastpage){
741 if(flash_erase_block(flash_cmdlist, flash_ptrlist, page)) {
742 dprintf(INFO, "flash_write_image: bad block @ %d\n", page >> 6);
743 }
744 page += 64;
745 }
746
747 dprintf(INFO, "flash_write_image: success\n");
748 return 0;
749}
750
751#if 0
752static int flash_read_page(unsigned page, void *data, void *extra)
753{
754 return _flash_read_page(flash_cmdlist, flash_ptrlist,
755 page, data, extra);
756}
757#endif