blob: af6d3ffe80f14c7bbbb7fc1e28b0f823913e5b3e [file] [log] [blame]
Dima Zavin03cf4312009-01-23 16:38:30 -08001/*
2 * Copyright (c) 2008, Google Inc.
3 * All rights reserved.
Shashank Mittal246f8d02011-01-21 17:12:27 -08004 * Copyright (c) 2009-2011, 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;
Chandan Uddaraju14e57eb2010-06-28 12:11:06 -070045void platform_config_interleaved_mode_gpios(void);
Dima Zavin03cf4312009-01-23 16:38:30 -080046
47typedef struct dmov_ch dmov_ch;
Shashank Mittalc20b5a12009-11-18 19:35:30 -080048struct dmov_ch
Dima Zavin03cf4312009-01-23 16:38:30 -080049{
50 volatile unsigned cmd;
51 volatile unsigned result;
52 volatile unsigned status;
53 volatile unsigned config;
54};
55
56static void dmov_prep_ch(dmov_ch *ch, unsigned id)
57{
58 ch->cmd = DMOV_CMD_PTR(id);
59 ch->result = DMOV_RSLT(id);
60 ch->status = DMOV_STATUS(id);
61 ch->config = DMOV_CONFIG(id);
62}
63
64#define SRC_CRCI_NAND_CMD CMD_SRC_CRCI(DMOV_NAND_CRCI_CMD)
65#define DST_CRCI_NAND_CMD CMD_DST_CRCI(DMOV_NAND_CRCI_CMD)
66#define SRC_CRCI_NAND_DATA CMD_SRC_CRCI(DMOV_NAND_CRCI_DATA)
67#define DST_CRCI_NAND_DATA CMD_DST_CRCI(DMOV_NAND_CRCI_DATA)
68
Shashank Mittalad3d05c2009-11-19 15:53:57 -080069#define NAND_CFG0_RAW 0xA80420C0
70#define NAND_CFG1_RAW 0x5045D
71
Dima Zavin03cf4312009-01-23 16:38:30 -080072static unsigned CFG0, CFG1;
Shashank Mittal8e49dec2010-03-01 15:19:04 -080073static unsigned CFG0_M, CFG1_M;
74static unsigned CFG0_A, CFG1_A;
Dima Zavin03cf4312009-01-23 16:38:30 -080075
76#define CFG1_WIDE_FLASH (1U << 1)
77
78#define paddr(n) ((unsigned) (n))
79
80static int dmov_exec_cmdptr(unsigned id, unsigned *ptr)
81{
82 dmov_ch ch;
83 unsigned n;
84
85 dmov_prep_ch(&ch, id);
86
87 writel(DMOV_CMD_PTR_LIST | DMOV_CMD_ADDR(paddr(ptr)), ch.cmd);
88
89 while(!(readl(ch.status) & DMOV_STATUS_RSLT_VALID)) ;
90
91 n = readl(ch.status);
92 while(DMOV_STATUS_RSLT_COUNT(n)) {
93 n = readl(ch.result);
94 if(n != 0x80000002) {
95 dprintf(CRITICAL, "ERROR: result: %x\n", n);
96 dprintf(CRITICAL, "ERROR: flush: %x %x %x %x\n",
97 readl(DMOV_FLUSH0(DMOV_NAND_CHAN)),
98 readl(DMOV_FLUSH1(DMOV_NAND_CHAN)),
99 readl(DMOV_FLUSH2(DMOV_NAND_CHAN)),
100 readl(DMOV_FLUSH3(DMOV_NAND_CHAN)));
101 }
102 n = readl(ch.status);
103 }
104
105 return 0;
106}
107
Dima Zavinca337f52009-03-02 16:41:44 -0800108static struct flash_info flash_info;
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800109static unsigned flash_pagesize = 0;
Chandan Uddaraju14e57eb2010-06-28 12:11:06 -0700110static int interleaved_mode = 0;
Dima Zavin03cf4312009-01-23 16:38:30 -0800111
Shashank Mittal83d16d02009-11-18 16:54:42 -0800112struct flash_identification {
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800113 unsigned flash_id;
114 unsigned mask;
115 unsigned density;
116 unsigned widebus;
117 unsigned pagesize;
118 unsigned blksize;
119 unsigned oobsize;
120 unsigned onenand;
Shashank Mittal83d16d02009-11-18 16:54:42 -0800121};
122
123static struct flash_identification supported_flash[] =
124{
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800125 /* Flash ID ID Mask Density(MB) Wid Pgsz Blksz oobsz onenand Manuf */
126 {0x00000000, 0xFFFFFFFF, 0, 0, 0, 0, 0, 0}, /*ONFI*/
127 {0x1500aaec, 0xFF00FFFF, (256<<20), 0, 2048, (2048<<6), 64, 0}, /*Sams*/
128 {0x5500baec, 0xFF00FFFF, (256<<20), 1, 2048, (2048<<6), 64, 0}, /*Sams*/
129 {0x1500aa98, 0xFFFFFFFF, (256<<20), 0, 2048, (2048<<6), 64, 0}, /*Tosh*/
130 {0x5500ba98, 0xFFFFFFFF, (256<<20), 1, 2048, (2048<<6), 64, 0}, /*Tosh*/
Ajay Dudani86e1b422009-12-04 20:49:50 -0800131 {0xd580b12c, 0xFFFFFFFF, (256<<20), 1, 2048, (2048<<6), 64, 0}, /*Micr*/
Chandan Uddaraju40605112010-08-09 14:25:08 -0700132 {0x5590bc2c, 0xFFFFFFFF, (512<<20), 1, 2048, (2048<<6), 64, 0}, /*Micr*/
Chandan Uddaraju0ec234c2009-11-24 22:34:50 -0800133 {0x1580aa2c, 0xFFFFFFFF, (256<<20), 0, 2048, (2048<<6), 64, 0}, /*Micr*/
Shashank Mittalab958e52010-12-03 17:57:22 -0800134 {0x1590aa2c, 0xFFFFFFFF, (256<<20), 0, 2048, (2048<<6), 64, 0}, /*Micr*/
Ajay Dudani513fb742010-05-24 20:39:26 -0700135 {0x1590ac2c, 0xFFFFFFFF, (512<<20), 0, 2048, (2048<<6), 64, 0}, /*Micr*/
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800136 {0x5580baad, 0xFFFFFFFF, (256<<20), 1, 2048, (2048<<6), 64, 0}, /*Hynx*/
137 {0x5510baad, 0xFFFFFFFF, (256<<20), 1, 2048, (2048<<6), 64, 0}, /*Hynx*/
138 {0x004000ec, 0xFFFFFFFF, (256<<20), 0, 2048, (2048<<6), 64, 1}, /*Sams*/
139 {0x005c00ec, 0xFFFFFFFF, (256<<20), 0, 2048, (2048<<6), 64, 1}, /*Sams*/
140 {0x005800ec, 0xFFFFFFFF, (256<<20), 0, 2048, (2048<<6), 64, 1}, /*Sams*/
Chandan Uddaraju40605112010-08-09 14:25:08 -0700141 {0x6600bcec, 0xFF00FFFF, (512<<20), 1, 4096, (4096<<6), 128, 0}, /*Sams*/
Shashank Mittal246f8d02011-01-21 17:12:27 -0800142 {0x5580ba2c, 0xFFFFFFFF, (256<<20), 1, 2048, (2048<<6), 64, 0}, /*Hynx*/
Shashank Mittalef325412011-04-01 13:48:26 -0700143 {0x6600b3ec, 0xFFFFFFFF, (512<<20), 1, 4096, (4096<<6), 128, 0}, /*Sams*/
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800144 /* Note: Width flag is 0 for 8 bit Flash and 1 for 16 bit flash */
145 /* Note: Onenand flag is 0 for NAND Flash and 1 for OneNAND flash */
146 /* Note: The First row will be filled at runtime during ONFI probe */
Shashank Mittal83d16d02009-11-18 16:54:42 -0800147};
Shashank Mittal8e49dec2010-03-01 15:19:04 -0800148static void set_nand_configuration(char type)
149{
150 if(type == TYPE_MODEM_PARTITION)
151 {
152 CFG0 = CFG0_M;
153 CFG1 = CFG1_M;
154 }
155 else
156 {
157 CFG0 = CFG0_A;
158 CFG1 = CFG1_A;
159 }
160}
Shashank Mittal83d16d02009-11-18 16:54:42 -0800161
162static void flash_nand_read_id(dmov_s *cmdlist, unsigned *ptrlist)
Dima Zavin03cf4312009-01-23 16:38:30 -0800163{
164 dmov_s *cmd = cmdlist;
165 unsigned *ptr = ptrlist;
166 unsigned *data = ptrlist + 4;
167
168 data[0] = 0 | 4;
169 data[1] = NAND_CMD_FETCH_ID;
170 data[2] = 1;
171 data[3] = 0;
172 data[4] = 0;
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800173 data[5] = 0;
174 data[6] = 0;
175 data[7] = 0xAAD40000; /* Default value for CFG0 for reading device id */
Dima Zavin03cf4312009-01-23 16:38:30 -0800176
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800177 /* Read NAND device id */
Dima Zavin03cf4312009-01-23 16:38:30 -0800178 cmd[0].cmd = 0 | CMD_OCB;
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800179 cmd[0].src = paddr(&data[7]);
180 cmd[0].dst = NAND_DEV0_CFG0;
Dima Zavin03cf4312009-01-23 16:38:30 -0800181 cmd[0].len = 4;
182
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800183 cmd[1].cmd = 0;
184 cmd[1].src = NAND_SFLASHC_BURST_CFG;
185 cmd[1].dst = paddr(&data[5]);
Dima Zavin03cf4312009-01-23 16:38:30 -0800186 cmd[1].len = 4;
187
188 cmd[2].cmd = 0;
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800189 cmd[2].src = paddr(&data[6]);
190 cmd[2].dst = NAND_SFLASHC_BURST_CFG;
Dima Zavin03cf4312009-01-23 16:38:30 -0800191 cmd[2].len = 4;
192
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800193 cmd[3].cmd = 0;
194 cmd[3].src = paddr(&data[0]);
195 cmd[3].dst = NAND_FLASH_CHIP_SELECT;
Dima Zavin03cf4312009-01-23 16:38:30 -0800196 cmd[3].len = 4;
197
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800198 cmd[4].cmd = DST_CRCI_NAND_CMD;
199 cmd[4].src = paddr(&data[1]);
200 cmd[4].dst = NAND_FLASH_CMD;
Dima Zavin03cf4312009-01-23 16:38:30 -0800201 cmd[4].len = 4;
202
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800203 cmd[5].cmd = 0;
204 cmd[5].src = paddr(&data[2]);
205 cmd[5].dst = NAND_EXEC_CMD;
206 cmd[5].len = 4;
207
208 cmd[6].cmd = SRC_CRCI_NAND_DATA;
209 cmd[6].src = NAND_FLASH_STATUS;
210 cmd[6].dst = paddr(&data[3]);
211 cmd[6].len = 4;
212
213 cmd[7].cmd = 0;
214 cmd[7].src = NAND_READ_ID;
215 cmd[7].dst = paddr(&data[4]);
216 cmd[7].len = 4;
217
218 cmd[8].cmd = CMD_OCU | CMD_LC;
219 cmd[8].src = paddr(&data[5]);
220 cmd[8].dst = NAND_SFLASHC_BURST_CFG;
221 cmd[8].len = 4;
222
Dima Zavin03cf4312009-01-23 16:38:30 -0800223 ptr[0] = (paddr(cmd) >> 3) | CMD_PTR_LP;
224
225 dmov_exec_cmdptr(DMOV_NAND_CHAN, ptr);
226
227#if VERBOSE
228 dprintf(INFO, "status: %x\n", data[3]);
229#endif
Dima Zavin03cf4312009-01-23 16:38:30 -0800230
Shashank Mittal83d16d02009-11-18 16:54:42 -0800231 flash_info.id = data[4];
Dima Zavinca337f52009-03-02 16:41:44 -0800232 flash_info.vendor = data[4] & 0xff;
233 flash_info.device = (data[4] >> 8) & 0xff;
Shashank Mittal83d16d02009-11-18 16:54:42 -0800234 return;
235}
Dima Zavinca337f52009-03-02 16:41:44 -0800236
Shashank Mittalad3d05c2009-11-19 15:53:57 -0800237static int flash_nand_block_isbad(dmov_s *cmdlist, unsigned *ptrlist,
238 unsigned page)
239{
240 dmov_s *cmd = cmdlist;
241 unsigned *ptr = ptrlist;
242 unsigned *data = ptrlist + 4;
243 char buf[4];
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800244 unsigned cwperpage;
245
246 cwperpage = (flash_pagesize >> 9);
Shashank Mittalad3d05c2009-11-19 15:53:57 -0800247
248 /* Check first page of this block */
249 if(page & 63)
250 page = page - (page & 63);
251
252 /* Check bad block marker */
253 data[0] = NAND_CMD_PAGE_READ; /* command */
254
255 /* addr0 */
256 if (CFG1 & CFG1_WIDE_FLASH)
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800257 data[1] = (page << 16) | ((528*(cwperpage-1)) >> 1);
Shashank Mittalad3d05c2009-11-19 15:53:57 -0800258 else
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800259 data[1] = (page << 16) | (528*(cwperpage-1));
Shashank Mittalad3d05c2009-11-19 15:53:57 -0800260
261 data[2] = (page >> 16) & 0xff; /* addr1 */
262 data[3] = 0 | 4; /* chipsel */
263 data[4] = NAND_CFG0_RAW & ~(7U << 6); /* cfg0 */
264 data[5] = NAND_CFG1_RAW | (CFG1 & CFG1_WIDE_FLASH); /* cfg1 */
265 data[6] = 1;
266 data[7] = CLEAN_DATA_32; /* flash status */
267 data[8] = CLEAN_DATA_32; /* buf status */
268
269 cmd[0].cmd = DST_CRCI_NAND_CMD | CMD_OCB;
270 cmd[0].src = paddr(&data[0]);
271 cmd[0].dst = NAND_FLASH_CMD;
272 cmd[0].len = 16;
273
274 cmd[1].cmd = 0;
275 cmd[1].src = paddr(&data[4]);
276 cmd[1].dst = NAND_DEV0_CFG0;
277 cmd[1].len = 8;
278
279 cmd[2].cmd = 0;
280 cmd[2].src = paddr(&data[6]);
281 cmd[2].dst = NAND_EXEC_CMD;
282 cmd[2].len = 4;
283
284 cmd[3].cmd = SRC_CRCI_NAND_DATA;
285 cmd[3].src = NAND_FLASH_STATUS;
286 cmd[3].dst = paddr(&data[7]);
287 cmd[3].len = 8;
288
289 cmd[4].cmd = CMD_OCU | CMD_LC;
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800290 cmd[4].src = NAND_FLASH_BUFFER + (flash_pagesize - (528*(cwperpage-1)));
Shashank Mittalad3d05c2009-11-19 15:53:57 -0800291 cmd[4].dst = paddr(&buf);
292 cmd[4].len = 4;
293
294 ptr[0] = (paddr(cmd) >> 3) | CMD_PTR_LP;
295
296 dmov_exec_cmdptr(DMOV_NAND_CHAN, ptr);
297
298#if VERBOSE
299 dprintf(INFO, "status: %x\n", data[7]);
300#endif
301
302 /* we fail if there was an operation error, a mpu error, or the
303 ** erase success bit was not set.
304 */
305 if(data[7] & 0x110) return -1;
306
307 /* Check for bad block marker byte */
308 if (CFG1 & CFG1_WIDE_FLASH) {
309 if (buf[0] != 0xFF || buf[1] != 0xFF)
310 return 1;
311 } else {
312 if (buf[0] != 0xFF)
313 return 1;
314 }
315
316 return 0;
317}
318
Murali Nalajalaa8c94c62010-03-05 20:24:30 +0530319static int flash_nand_block_isbad_interleave(dmov_s *cmdlist, unsigned *ptrlist,
320 unsigned page)
321{
322 dmov_s *cmd = cmdlist;
323 unsigned *ptr = ptrlist;
324 unsigned *data = ptrlist + 4;
325 char buf01[4];
326 char buf10[4];
327 unsigned cwperpage;
328
329 cwperpage = ((flash_pagesize >> 1)>> 9);
330
331 /* Check first page of this block */
332 if(page & 63)
333 page = page - (page & 63);
334
335 /* Check bad block marker */
336 data[0] = NAND_CMD_PAGE_READ; /* command */
337
338 /* addr0 */
339 if (CFG1 & CFG1_WIDE_FLASH)
340 data[1] = (page << 16) | ((528*(cwperpage-1)) >> 1);
341 else
342 data[1] = (page << 16) | (528*(cwperpage-1));
343
344 data[2] = (page >> 16) & 0xff; /* addr1 */
345 data[3] = 0 | 4; /* chipsel CS0 */
346 data[4] = 0 | 5; /* chipsel CS1 */
347 data[5] = NAND_CFG0_RAW & ~(7U << 6); /* cfg0 */
348 data[6] = NAND_CFG1_RAW | (CFG1 & CFG1_WIDE_FLASH); /* cfg1 */
349 data[7] = 1;
350 data[8] = CLEAN_DATA_32; /* NC01 flash status */
351 data[9] = CLEAN_DATA_32; /* NC01 buf01 status */
352 data[10] = CLEAN_DATA_32; /* NC10 flash status */
353 data[11] = CLEAN_DATA_32; /* NC10 buf10 status */
354 data[12] = 0x00000A3C; /* adm_mux_data_ack_req_nc01 */
355 data[13] = 0x0000053C; /* adm_mux_cmd_ack_req_nc01 */
356 data[14] = 0x00000F28; /* adm_mux_data_ack_req_nc10 */
357 data[15] = 0x00000F14; /* adm_mux_cmd_ack_req_nc10 */
358 data[16] = 0x00000FC0; /* adm_default_mux */
359 data[17] = 0x00000805; /* enable CS1 */
360 data[18] = 0x00000801; /* disable CS1 */
361
362 /* enable CS1 */
363 cmd[0].cmd = 0;
364 cmd[0].src = paddr(data[17]);
365 cmd[0].dst = EBI2_CHIP_SELECT_CFG0;
366 cmd[0].len = 4;
367
368 /* Reading last code word from NC01 */
369 /* 0xF14 */
370 cmd[1].cmd = 0;
371 cmd[1].src = paddr(data[15]);
372 cmd[1].dst = EBI2_NAND_ADM_MUX;
373 cmd[1].len = 4;
374
375 cmd[2].cmd = DST_CRCI_NAND_CMD;
376 cmd[2].src = paddr(&data[0]);
377 cmd[2].dst = NC01(NAND_FLASH_CMD);
378 cmd[2].len = 16;
379
380 cmd[3].cmd = 0;
381 cmd[3].src = paddr(&data[5]);
382 cmd[3].dst = NC01(NAND_DEV0_CFG0);
383 cmd[3].len = 8;
384
385 cmd[4].cmd = 0;
386 cmd[4].src = paddr(&data[7]);
387 cmd[4].dst = NC01(NAND_EXEC_CMD);
388 cmd[4].len = 4;
389
390 /* 0xF28 */
391 cmd[5].cmd = 0;
392 cmd[5].src = paddr(data[14]);
393 cmd[5].dst = EBI2_NAND_ADM_MUX;
394 cmd[5].len = 4;
395
396 cmd[6].cmd = SRC_CRCI_NAND_DATA;
397 cmd[6].src = NC01(NAND_FLASH_STATUS);
398 cmd[6].dst = paddr(&data[8]);
399 cmd[6].len = 8;
400
401 cmd[7].cmd = 0;
402 cmd[7].src = NC01(NAND_FLASH_BUFFER) + (flash_pagesize - (528*(cwperpage-1)));
403 cmd[7].dst = paddr(&buf01);
404 cmd[7].len = 4;
405
406 /* Reading last code word from NC10 */
407 /* 0x53C */
408 cmd[8].cmd = 0;
409 cmd[8].src = paddr(data[13]);
410 cmd[8].dst = EBI2_NAND_ADM_MUX;
411 cmd[8].len = 4;
412
413 cmd[9].cmd = DST_CRCI_NAND_CMD;
414 cmd[9].src = paddr(&data[0]);
415 cmd[9].dst = NC10(NAND_FLASH_CMD);
416 cmd[9].len = 12;
417
418 cmd[10].cmd = 0;
419 cmd[10].src = paddr(&data[4]);
420 cmd[10].dst = NC10(NAND_FLASH_CHIP_SELECT);
421 cmd[10].len = 4;
422
423 cmd[11].cmd = 0;
424 cmd[11].src = paddr(&data[5]);
425 cmd[11].dst = NC10(NAND_DEV1_CFG0);
426 cmd[11].len = 8;
427
428 cmd[12].cmd = 0;
429 cmd[12].src = paddr(&data[7]);
430 cmd[12].dst = NC10(NAND_EXEC_CMD);
431 cmd[12].len = 4;
432
433 /* 0xA3C */
434 cmd[13].cmd = 0;
435 cmd[13].src = paddr(data[12]);
436 cmd[13].dst = EBI2_NAND_ADM_MUX;
437 cmd[13].len = 4;
438
439 cmd[14].cmd = SRC_CRCI_NAND_DATA;
440 cmd[14].src = NC10(NAND_FLASH_STATUS);
441 cmd[14].dst = paddr(&data[10]);
442 cmd[14].len = 8;
443
444 cmd[15].cmd = 0;
445 cmd[15].src = NC10(NAND_FLASH_BUFFER) + (flash_pagesize - (528*(cwperpage-1)));
446 cmd[15].dst = paddr(&buf10);
447 cmd[15].len = 4;
448
449 cmd[16].cmd = 0;
450 cmd[16].src = paddr(&data[16]);
451 cmd[16].dst = EBI2_NAND_ADM_MUX;
452 cmd[16].len = 4;
453
454 /* setting default value */
455 cmd[17].cmd = CMD_OCU | CMD_LC;
456 cmd[17].src = paddr(&data[18]);
457 cmd[17].dst = EBI2_CHIP_SELECT_CFG0;
458 cmd[17].len = 4;
459
460 ptr[0] = (paddr(cmd) >> 3) | CMD_PTR_LP;
461
462 dmov_exec_cmdptr(DMOV_NAND_CHAN, ptr);
463
464#if VERBOSE
465 dprintf(INFO, "NC01 status: %x\n", data[8]);
466 dprintf(INFO, "NC10 status: %x\n", data[10]);
467#endif
468
469 /* we fail if there was an operation error, a mpu error, or the
470 ** erase success bit was not set.
471 */
472 if((data[8] & 0x110) || (data[10] & 0x110)) return -1;
473
474 /* Check for bad block marker byte */
475 if (CFG1 & CFG1_WIDE_FLASH) {
476 if ((buf01[0] != 0xFF || buf01[1] != 0xFF) ||
477 (buf10[0] != 0xFF || buf10[1] != 0xFF))
478 return 1;
479 } else {
480 if (buf01[0] != 0xFF || buf10[0] != 0xFF)
481 return 1;
482 }
483
484 return 0;
485}
486
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800487static int flash_nand_erase_block(dmov_s *cmdlist, unsigned *ptrlist,
488 unsigned page)
Dima Zavin03cf4312009-01-23 16:38:30 -0800489{
490 dmov_s *cmd = cmdlist;
491 unsigned *ptr = ptrlist;
492 unsigned *data = ptrlist + 4;
Shashank Mittalad3d05c2009-11-19 15:53:57 -0800493 int isbad = 0;
Dima Zavin03cf4312009-01-23 16:38:30 -0800494
495 /* only allow erasing on block boundaries */
496 if(page & 63) return -1;
497
Shashank Mittalad3d05c2009-11-19 15:53:57 -0800498 /* Check for bad block and erase only if block is not marked bad */
499 isbad = flash_nand_block_isbad(cmdlist, ptrlist, page);
500
501 if (isbad) {
502 dprintf(INFO, "skipping @ %d (bad block)\n", page >> 6);
503 return -1;
504 }
505
506 /* Erase block */
Dima Zavin03cf4312009-01-23 16:38:30 -0800507 data[0] = NAND_CMD_BLOCK_ERASE;
508 data[1] = page;
509 data[2] = 0;
510 data[3] = 0 | 4;
511 data[4] = 1;
512 data[5] = 0xeeeeeeee;
513 data[6] = CFG0 & (~(7 << 6)); /* CW_PER_PAGE = 0 */
514 data[7] = CFG1;
Murali Palnatic54d13a2010-01-15 19:50:19 +0530515 data[8] = 0x00000020;
516 data[9] = 0x000000C0;
Dima Zavin03cf4312009-01-23 16:38:30 -0800517
518 cmd[0].cmd = DST_CRCI_NAND_CMD | CMD_OCB;
519 cmd[0].src = paddr(&data[0]);
520 cmd[0].dst = NAND_FLASH_CMD;
521 cmd[0].len = 16;
522
523 cmd[1].cmd = 0;
524 cmd[1].src = paddr(&data[6]);
525 cmd[1].dst = NAND_DEV0_CFG0;
526 cmd[1].len = 8;
527
528 cmd[2].cmd = 0;
529 cmd[2].src = paddr(&data[4]);
530 cmd[2].dst = NAND_EXEC_CMD;
531 cmd[2].len = 4;
532
Murali Palnatic54d13a2010-01-15 19:50:19 +0530533 cmd[3].cmd = SRC_CRCI_NAND_DATA;
Dima Zavin03cf4312009-01-23 16:38:30 -0800534 cmd[3].src = NAND_FLASH_STATUS;
535 cmd[3].dst = paddr(&data[5]);
536 cmd[3].len = 4;
537
Murali Palnatic54d13a2010-01-15 19:50:19 +0530538 cmd[4].cmd = 0;
539 cmd[4].src = paddr(&data[8]);
540 cmd[4].dst = NAND_FLASH_STATUS;
541 cmd[4].len = 4;
542
543 cmd[5].cmd = CMD_OCU | CMD_LC;
544 cmd[5].src = paddr(&data[9]);
545 cmd[5].dst = NAND_READ_STATUS;
546 cmd[5].len = 4;
547
Dima Zavin03cf4312009-01-23 16:38:30 -0800548 ptr[0] = (paddr(cmd) >> 3) | CMD_PTR_LP;
549
550 dmov_exec_cmdptr(DMOV_NAND_CHAN, ptr);
551
552#if VERBOSE
553 dprintf(INFO, "status: %x\n", data[5]);
554#endif
555
556 /* we fail if there was an operation error, a mpu error, or the
557 ** erase success bit was not set.
558 */
559 if(data[5] & 0x110) return -1;
560 if(!(data[5] & 0x80)) return -1;
561
562 return 0;
563}
564
Murali Nalajalaa8c94c62010-03-05 20:24:30 +0530565static int flash_nand_erase_block_interleave(dmov_s *cmdlist, unsigned *ptrlist,
566 unsigned page)
567{
568 dmov_s *cmd = cmdlist;
569 unsigned *ptr = ptrlist;
570 unsigned *data = ptrlist + 4;
571 int isbad = 0;
572
573 /* only allow erasing on block boundaries */
574 if(page & 63) return -1;
575
576 /* Check for bad block and erase only if block is not marked bad */
577 isbad = flash_nand_block_isbad(cmdlist, ptrlist, page);
578
579 if (isbad) {
580 dprintf(INFO, "skipping @ %d (bad block)\n", page >> 6);
581 return -1;
582 }
583
584 /* Erase block */
585 data[0] = NAND_CMD_BLOCK_ERASE;
586 data[1] = page;
587 data[2] = 0;
588 data[3] = 0 | 4; /* chipselect CS0 */
589 data[4] = 0 | 5; /* chipselect CS1 */
590 data[5] = 1;
591 data[6] = 0xeeeeeeee;
592 data[7] = 0xeeeeeeee;
593 data[8] = CFG0 & (~(7 << 6)); /* CW_PER_PAGE = 0 */
594 data[9] = CFG1;
595 data[10] = 0x00000A3C; /* adm_mux_data_ack_req_nc01 */
596 data[11] = 0x0000053C; /* adm_mux_cmd_ack_req_nc01 */
597 data[12] = 0x00000F28; /* adm_mux_data_ack_req_nc10 */
598 data[13] = 0x00000F14; /* adm_mux_cmd_ack_req_nc10 */
599 data[14] = 0x00000FC0; /* adm_default_mux */
600 data[15] = 0x00000805; /* enable CS1 */
601 data[16] = 0x00000801; /* disable CS1 */
602
603 /* enable CS1 */
604 cmd[0].cmd = 0 | CMD_OCB;
605 cmd[0].src = paddr(data[15]);
606 cmd[0].dst = EBI2_CHIP_SELECT_CFG0;
607 cmd[0].len = 4;
608
609 /* Reading last code word from NC01 */
610 /* 0xF14 */
611 cmd[1].cmd = 0;
612 cmd[1].src = paddr(data[13]);
613 cmd[1].dst = EBI2_NAND_ADM_MUX;
614 cmd[1].len = 4;
615
616 cmd[2].cmd = DST_CRCI_NAND_CMD;
617 cmd[2].src = paddr(&data[0]);
618 cmd[2].dst = NC01(NAND_FLASH_CMD);
619 cmd[2].len = 16;
620
621 cmd[3].cmd = 0;
622 cmd[3].src = paddr(&data[8]);
623 cmd[3].dst = NC01(NAND_DEV0_CFG0);
624 cmd[3].len = 8;
625
626 cmd[4].cmd = 0;
627 cmd[4].src = paddr(&data[5]);
628 cmd[4].dst = NC01(NAND_EXEC_CMD);
629 cmd[4].len = 4;
630
631 /* 0xF28 */
632 cmd[5].cmd = 0;
633 cmd[5].src = paddr(data[12]);
634 cmd[5].dst = EBI2_NAND_ADM_MUX;
635 cmd[5].len = 4;
636
637 cmd[6].cmd = SRC_CRCI_NAND_DATA;
638 cmd[6].src = NC01(NAND_FLASH_STATUS);
639 cmd[6].dst = paddr(&data[6]);
640 cmd[6].len = 4;
641
642 /* Reading last code word from NC10 */
643 /* 0x53C */
644 cmd[7].cmd = 0;
645 cmd[7].src = paddr(data[11]);
646 cmd[7].dst = EBI2_NAND_ADM_MUX;
647 cmd[7].len = 4;
648
649 cmd[8].cmd = DST_CRCI_NAND_CMD;
650 cmd[8].src = paddr(&data[0]);
651 cmd[8].dst = NC10(NAND_FLASH_CMD);
652 cmd[8].len = 12;
653
654 cmd[9].cmd = 0;
655 cmd[9].src = paddr(&data[4]);
656 cmd[9].dst = NC10(NAND_FLASH_CHIP_SELECT);
657 cmd[9].len = 4;
658
659 cmd[10].cmd = 0;
660 cmd[10].src = paddr(&data[8]);
661 cmd[10].dst = NC10(NAND_DEV1_CFG0);
662 cmd[10].len = 8;
663
664 cmd[11].cmd = 0;
665 cmd[11].src = paddr(&data[5]);
666 cmd[11].dst = NC10(NAND_EXEC_CMD);
667 cmd[11].len = 4;
668
669 /* 0xA3C */
670 cmd[12].cmd = 0;
671 cmd[12].src = paddr(data[10]);
672 cmd[12].dst = EBI2_NAND_ADM_MUX;
673 cmd[12].len = 4;
674
675 cmd[13].cmd = SRC_CRCI_NAND_DATA;
676 cmd[13].src = NC10(NAND_FLASH_STATUS);
677 cmd[13].dst = paddr(&data[7]);
678 cmd[13].len = 4;
679
680 /* adm default mux state */
681 /* 0xFCO */
682 cmd[14].cmd = 0;
683 cmd[14].src = paddr(data[14]);
684 cmd[14].dst = EBI2_NAND_ADM_MUX;
685 cmd[14].len = 4;
686
687 /* disable CS1 */
688 cmd[15].cmd = CMD_OCU | CMD_LC;
689 cmd[15].src = paddr(data[16]);
690 cmd[15].dst = EBI2_CHIP_SELECT_CFG0;
691 cmd[15].len = 4;
692
693 ptr[0] = (paddr(cmd) >> 3) | CMD_PTR_LP;
694
695 dmov_exec_cmdptr(DMOV_NAND_CHAN, ptr);
696
697#if VERBOSE
698 dprintf(INFO, "NC01 status: %x\n", data[6]);
699 dprintf(INFO, "NC10 status: %x\n", data[7]);
700#endif
701
702 /* we fail if there was an operation error, a mpu error, or the
703 ** erase success bit was not set.
704 */
705 if(data[6] & 0x110 || data[7] & 0x110) return -1;
706 if(!(data[6] & 0x80) || !(data[7] & 0x80)) return -1;
707
708 return 0;
709}
710
Dima Zavin03cf4312009-01-23 16:38:30 -0800711struct data_flash_io {
712 unsigned cmd;
713 unsigned addr0;
714 unsigned addr1;
715 unsigned chipsel;
716 unsigned cfg0;
717 unsigned cfg1;
718 unsigned exec;
719 unsigned ecc_cfg;
720 unsigned ecc_cfg_save;
Murali Palnatic54d13a2010-01-15 19:50:19 +0530721 unsigned clrfstatus;
722 unsigned clrrstatus;
Dima Zavin03cf4312009-01-23 16:38:30 -0800723 struct {
724 unsigned flash_status;
725 unsigned buffer_status;
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800726 } result[8];
Dima Zavin03cf4312009-01-23 16:38:30 -0800727};
728
Murali Nalajalaa8c94c62010-03-05 20:24:30 +0530729struct interleave_data_flash_io {
730 uint32_t cmd;
731 uint32_t addr0;
732 uint32_t addr1;
733 uint32_t chipsel_cs0;
734 uint32_t chipsel_cs1;
735 uint32_t cfg0;
736 uint32_t cfg1;
737 uint32_t exec;
738 uint32_t ecc_cfg;
739 uint32_t ecc_cfg_save;
740 uint32_t ebi2_chip_select_cfg0;
741 uint32_t adm_mux_data_ack_req_nc01;
742 uint32_t adm_mux_cmd_ack_req_nc01;
743 uint32_t adm_mux_data_ack_req_nc10;
744 uint32_t adm_mux_cmd_ack_req_nc10;
745 uint32_t adm_default_mux;
746 uint32_t default_ebi2_chip_select_cfg0;
747 struct {
748 uint32_t flash_status;
749 } result[16];
750};
751
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800752static int _flash_nand_read_page(dmov_s *cmdlist, unsigned *ptrlist,
753 unsigned page, void *_addr, void *_spareaddr)
Dima Zavin03cf4312009-01-23 16:38:30 -0800754{
755 dmov_s *cmd = cmdlist;
756 unsigned *ptr = ptrlist;
757 struct data_flash_io *data = (void*) (ptrlist + 4);
758 unsigned addr = (unsigned) _addr;
759 unsigned spareaddr = (unsigned) _spareaddr;
760 unsigned n;
Shashank Mittalad3d05c2009-11-19 15:53:57 -0800761 int isbad = 0;
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800762 unsigned cwperpage;
763 cwperpage = (flash_pagesize >> 9);
Shashank Mittalad3d05c2009-11-19 15:53:57 -0800764
765 /* Check for bad block and read only from a good block */
766 isbad = flash_nand_block_isbad(cmdlist, ptrlist, page);
767 if (isbad)
768 return -2;
Dima Zavin03cf4312009-01-23 16:38:30 -0800769
770 data->cmd = NAND_CMD_PAGE_READ_ECC;
771 data->addr0 = page << 16;
772 data->addr1 = (page >> 16) & 0xff;
773 data->chipsel = 0 | 4; /* flash0 + undoc bit */
774
775 /* GO bit for the EXEC register */
776 data->exec = 1;
777
778 data->cfg0 = CFG0;
779 data->cfg1 = CFG1;
780
781 data->ecc_cfg = 0x203;
782
783 /* save existing ecc config */
784 cmd->cmd = CMD_OCB;
785 cmd->src = NAND_EBI2_ECC_BUF_CFG;
786 cmd->dst = paddr(&data->ecc_cfg_save);
787 cmd->len = 4;
788 cmd++;
789
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800790 for(n = 0; n < cwperpage; n++) {
Dima Zavin03cf4312009-01-23 16:38:30 -0800791 /* write CMD / ADDR0 / ADDR1 / CHIPSEL regs in a burst */
792 cmd->cmd = DST_CRCI_NAND_CMD;
793 cmd->src = paddr(&data->cmd);
794 cmd->dst = NAND_FLASH_CMD;
795 cmd->len = ((n == 0) ? 16 : 4);
796 cmd++;
797
798 if (n == 0) {
799 /* block on cmd ready, set configuration */
800 cmd->cmd = 0;
801 cmd->src = paddr(&data->cfg0);
802 cmd->dst = NAND_DEV0_CFG0;
803 cmd->len = 8;
804 cmd++;
805
806 /* set our ecc config */
807 cmd->cmd = 0;
808 cmd->src = paddr(&data->ecc_cfg);
809 cmd->dst = NAND_EBI2_ECC_BUF_CFG;
810 cmd->len = 4;
811 cmd++;
812 }
813 /* kick the execute register */
814 cmd->cmd = 0;
815 cmd->src = paddr(&data->exec);
816 cmd->dst = NAND_EXEC_CMD;
817 cmd->len = 4;
818 cmd++;
819
820 /* block on data ready, then read the status register */
821 cmd->cmd = SRC_CRCI_NAND_DATA;
822 cmd->src = NAND_FLASH_STATUS;
823 cmd->dst = paddr(&data->result[n]);
824 cmd->len = 8;
825 cmd++;
826
827 /* read data block */
828 cmd->cmd = 0;
829 cmd->src = NAND_FLASH_BUFFER;
830 cmd->dst = addr + n * 516;
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800831 cmd->len = ((n < (cwperpage -1 )) ? 516 : (512 - ((cwperpage - 1) << 2)));
Dima Zavin03cf4312009-01-23 16:38:30 -0800832 cmd++;
833 }
834
835 /* read extra data */
836 cmd->cmd = 0;
837 cmd->src = NAND_FLASH_BUFFER + 500;
838 cmd->dst = spareaddr;
839 cmd->len = 16;
840 cmd++;
841
842 /* restore saved ecc config */
843 cmd->cmd = CMD_OCU | CMD_LC;
844 cmd->src = paddr(&data->ecc_cfg_save);
845 cmd->dst = NAND_EBI2_ECC_BUF_CFG;
846 cmd->len = 4;
847
848 ptr[0] = (paddr(cmdlist) >> 3) | CMD_PTR_LP;
849
850 dmov_exec_cmdptr(DMOV_NAND_CHAN, ptr);
851
852#if VERBOSE
853 dprintf(INFO, "read page %d: status: %x %x %x %x\n",
854 page, data[5], data[6], data[7], data[8]);
855 for(n = 0; n < 4; n++) {
856 ptr = (unsigned*)(addr + 512 * n);
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800857 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 -0800858 ptr = (unsigned*)(spareaddr + 16 * n);
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800859 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 -0800860 }
861#endif
862
863 /* if any of the writes failed (0x10), or there was a
864 ** protection violation (0x100), we lose
865 */
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800866 for(n = 0; n < cwperpage; n++) {
Dima Zavin03cf4312009-01-23 16:38:30 -0800867 if (data->result[n].flash_status & 0x110) {
868 return -1;
869 }
870 }
871
872 return 0;
873}
874
Murali Nalajalaa8c94c62010-03-05 20:24:30 +0530875static int flash_nand_read_page_interleave(dmov_s *cmdlist, unsigned *ptrlist,
876 unsigned page, void *_addr, void *_spareaddr)
877{
878 dmov_s *cmd = cmdlist;
879 unsigned *ptr = ptrlist;
880 struct interleave_data_flash_io *data = (void*) (ptrlist + 4);
881 unsigned addr = (unsigned) _addr;
882 unsigned spareaddr = (unsigned) _spareaddr;
883 unsigned n;
884 int isbad = 0;
885 unsigned cwperpage;
886 cwperpage = (flash_pagesize >> 9);
887
888 /* Check for bad block and read only from a good block */
889 isbad = flash_nand_block_isbad(cmdlist, ptrlist, page);
890 if (isbad)
891 return -2;
892
893 data->cmd = NAND_CMD_PAGE_READ_ECC;
894 data->addr0 = page << 16;
895 data->addr1 = (page >> 16) & 0xff;
896 data->chipsel_cs0 = 0 | 4; /* flash0 + undoc bit */
897 data->chipsel_cs1 = 0 | 5; /* flash0 + undoc bit */
898 data->ebi2_chip_select_cfg0 = 0x00000805;
899 data->adm_mux_data_ack_req_nc01 = 0x00000A3C;
900 data->adm_mux_cmd_ack_req_nc01 = 0x0000053C;
901 data->adm_mux_data_ack_req_nc10 = 0x00000F28;
902 data->adm_mux_cmd_ack_req_nc10 = 0x00000F14;
903 data->adm_default_mux = 0x00000FC0;
904 data->default_ebi2_chip_select_cfg0 = 0x00000801;
905
906 /* GO bit for the EXEC register */
907 data->exec = 1;
908
909 data->cfg0 = CFG0;
910 data->cfg1 = CFG1;
911
912 data->ecc_cfg = 0x203;
913
914 for (n = 0; n < cwperpage; n++) {
915 /* flash + buffer status return words */
916 data->result[n].flash_status = 0xeeeeeeee;
917
918 if (n == 0) {
919 /* enable CS1 */
920 cmd->cmd = CMD_OCB;
921 cmd->src = paddr(&data->ebi2_chip_select_cfg0);
922 cmd->dst = EBI2_CHIP_SELECT_CFG0;
923 cmd->len = 4;
924 cmd++;
925
926 /* save existing ecc config */
927 cmd->cmd = 0;
928 cmd->src = NAND_EBI2_ECC_BUF_CFG;
929 cmd->dst = paddr(&data->ecc_cfg_save);
930 cmd->len = 4;
931 cmd++;
932
933 /* NC01, NC10 --> ADDR0/ADDR1 */
934 cmd->cmd = 0;
935 cmd->src = paddr(&data->addr0);
936 cmd->dst = NC11(NAND_ADDR0);
937 cmd->len = 8;
938 cmd++;
939
940 /* Select the CS0,
941 * for NC01!
942 */
943 cmd->cmd = 0;
944 cmd->src = paddr(&data->chipsel_cs0);
945 cmd->dst = NC01(NAND_FLASH_CHIP_SELECT);
946 cmd->len = 4;
947 cmd++;
948
949 /* Select the CS1,
950 * for NC10!
951 */
952 cmd->cmd = 0;
953 cmd->src = paddr(&data->chipsel_cs1);
954 cmd->dst = NC10(NAND_FLASH_CHIP_SELECT);
955 cmd->len = 4;
956 cmd++;
957
958 cmd->cmd = 0;
959 cmd->src = paddr(&data->cfg0);
960 cmd->dst = NC01(NAND_DEV0_CFG0);
961 cmd->len = 8;
962 cmd++;
963
964 /* config DEV1 for CS1 */
965 cmd->cmd = 0;
966 cmd->src = paddr(&data->cfg0);
967 cmd->dst = NC10(NAND_DEV1_CFG0);
968 cmd->len = 8;
969 cmd++;
970
971 cmd->cmd = 0;
972 cmd->src = paddr(&data->ecc_cfg);
973 cmd->dst = NC11(NAND_EBI2_ECC_BUF_CFG);
974 cmd->len = 4;
975 cmd++;
976
977 /* if 'only' the last code word */
978 if (n == cwperpage - 1) {
979 /* MASK CMD ACK/REQ --> NC01 (0x53C)*/
980 cmd->cmd = 0;
981 cmd->src = paddr(&data->adm_mux_cmd_ack_req_nc01);
982 cmd->dst = EBI2_NAND_ADM_MUX;
983 cmd->len = 4;
984 cmd++;
985
986 /* CMD */
987 cmd->cmd = DST_CRCI_NAND_CMD;
988 cmd->src = paddr(&data->cmd);
989 cmd->dst = NC10(NAND_FLASH_CMD);
990 cmd->len = 4;
991 cmd++;
992
993 /* kick the execute register for NC10 */
994 cmd->cmd = 0;
995 cmd->src = paddr(&data->exec);
996 cmd->dst = NC10(NAND_EXEC_CMD);
997 cmd->len = 4;
998 cmd++;
999
1000 /* MASK DATA ACK/REQ --> NC01 (0xA3C)*/
1001 cmd->cmd = 0;
1002 cmd->src = paddr(&data->adm_mux_data_ack_req_nc01);
1003 cmd->dst = EBI2_NAND_ADM_MUX;
1004 cmd->len = 4;
1005 cmd++;
1006
1007 /* block on data ready from NC10, then
1008 * read the status register
1009 */
1010 cmd->cmd = SRC_CRCI_NAND_DATA;
1011 cmd->src = NC10(NAND_FLASH_STATUS);
1012 cmd->dst = paddr(&data->result[n]);
1013 /* NAND_FLASH_STATUS +
1014 * NAND_BUFFER_STATUS
1015 */
1016 cmd->len = 4;
1017 cmd++;
1018 } else {
1019 /* MASK CMD ACK/REQ --> NC10 (0xF14)*/
1020 cmd->cmd = 0;
1021 cmd->src = paddr(&data->adm_mux_cmd_ack_req_nc10);
1022 cmd->dst = EBI2_NAND_ADM_MUX;
1023 cmd->len = 4;
1024 cmd++;
1025
1026 /* CMD */
1027 cmd->cmd = DST_CRCI_NAND_CMD;
1028 cmd->src = paddr(&data->cmd);
1029 cmd->dst = NC01(NAND_FLASH_CMD);
1030 cmd->len = 4;
1031 cmd++;
1032
1033 /* kick the execute register for NC01*/
1034 cmd->cmd = 0;
1035 cmd->src = paddr(&data->exec);
1036 cmd->dst = NC01(NAND_EXEC_CMD);
1037 cmd->len = 4;
1038 cmd++;
1039 }
1040 }
1041
1042
1043 if (n % 2 == 0) {
1044 /* MASK CMD ACK/REQ --> NC01 (0x53C)*/
1045 cmd->cmd = 0;
1046 cmd->src = paddr(&data->adm_mux_cmd_ack_req_nc01);
1047 cmd->dst = EBI2_NAND_ADM_MUX;
1048 cmd->len = 4;
1049 cmd++;
1050
1051 /* CMD */
1052 cmd->cmd = DST_CRCI_NAND_CMD;
1053 cmd->src = paddr(&data->cmd);
1054 cmd->dst = NC10(NAND_FLASH_CMD);
1055 cmd->len = 4;
1056 cmd++;
1057
1058 /* kick the execute register for NC10 */
1059 cmd->cmd = 0;
1060 cmd->src = paddr(&data->exec);
1061 cmd->dst = NC10(NAND_EXEC_CMD);
1062 cmd->len = 4;
1063 cmd++;
1064
1065 /* MASK DATA ACK/REQ --> NC10 (0xF28)*/
1066 cmd->cmd = 0;
1067 cmd->src = paddr(&data->adm_mux_data_ack_req_nc10);
1068 cmd->dst = EBI2_NAND_ADM_MUX;
1069 cmd->len = 4;
1070 cmd++;
1071
1072 /* block on data ready from NC01, then
1073 * read the status register
1074 */
1075 cmd->cmd = SRC_CRCI_NAND_DATA;
1076 cmd->src = NC01(NAND_FLASH_STATUS);
1077 cmd->dst = paddr(&data->result[n]);
1078 /* NAND_FLASH_STATUS +
1079 * NAND_BUFFER_STATUS
1080 */
1081 cmd->len = 4;
1082 cmd++;
1083
1084 /* read data block */
1085 cmd->cmd = 0;
1086 cmd->src = NC01(NAND_FLASH_BUFFER);
1087 cmd->dst = addr + n * 516;
1088 cmd->len = ((n < (cwperpage -1 )) ? 516 : (512 - ((cwperpage - 1) << 2)));
1089 cmd++;
1090 } else {
1091 if (n != cwperpage - 1) {
1092 /* MASK CMD ACK/REQ -->
1093 * NC10 (0xF14)
1094 */
1095 cmd->cmd = 0;
1096 cmd->src = paddr(&data->adm_mux_cmd_ack_req_nc10);
1097 cmd->dst = EBI2_NAND_ADM_MUX;
1098 cmd->len = 4;
1099 cmd++;
1100
1101 /* CMD */
1102 cmd->cmd = DST_CRCI_NAND_CMD;
1103 cmd->src = paddr(&data->cmd);
1104 cmd->dst = NC01(NAND_FLASH_CMD);
1105 cmd->len = 4;
1106 cmd++;
1107
1108 /* EXEC */
1109 cmd->cmd = 0;
1110 cmd->src = paddr(&data->exec);
1111 cmd->dst = NC01(NAND_EXEC_CMD);
1112 cmd->len = 4;
1113 cmd++;
1114
1115 /* MASK DATA ACK/REQ -->
1116 * NC01 (0xA3C)
1117 */
1118 cmd->cmd = 0;
1119 cmd->src = paddr(&data->adm_mux_data_ack_req_nc01);
1120 cmd->dst = EBI2_NAND_ADM_MUX;
1121 cmd->len = 4;
1122 cmd++;
1123
1124 /* block on data ready from NC10
1125 * then read the status register
1126 */
1127 cmd->cmd = SRC_CRCI_NAND_DATA;
1128 cmd->src = NC10(NAND_FLASH_STATUS);
1129 cmd->dst = paddr(&data->result[n]);
1130 /* NAND_FLASH_STATUS +
1131 * NAND_BUFFER_STATUS
1132 */
1133 cmd->len = 4;
1134 cmd++;
1135 } else {
1136 /* MASK DATA ACK/REQ ->
1137 * NC01 (0xA3C)
1138 */
1139 cmd->cmd = 0;
1140 cmd->src = paddr(&data->adm_mux_data_ack_req_nc01);
1141 cmd->dst = EBI2_NAND_ADM_MUX;
1142 cmd->len = 4;
1143 cmd++;
1144
1145 /* block on data ready from NC10
1146 * then read the status register
1147 */
1148 cmd->cmd = SRC_CRCI_NAND_DATA;
1149 cmd->src = NC10(NAND_FLASH_STATUS);
1150 cmd->dst = paddr(&data->result[n]);
1151 /* NAND_FLASH_STATUS +
1152 * NAND_BUFFER_STATUS
1153 */
1154 cmd->len = 4;
1155 cmd++;
1156 }
1157 /* read data block */
1158 cmd->cmd = 0;
1159 cmd->src = NC10(NAND_FLASH_BUFFER);
1160 cmd->dst = addr + n * 516;
1161 cmd->len = ((n < (cwperpage -1 )) ? 516 : (512 - ((cwperpage - 1) << 2)));
1162 cmd++;
1163
1164 if (n == (cwperpage - 1)) {
1165 /* Use NC10 for reading the
1166 * last codeword!!!
1167 */
1168 cmd->cmd = 0;
1169 cmd->src = NC10(NAND_FLASH_BUFFER) +
1170 (512 - ((cwperpage -1) << 2));
1171 cmd->dst = spareaddr;
1172 cmd->len = 16;
1173 cmd++;
1174 }
1175 }
1176 }
1177 /* restore saved ecc config */
1178 cmd->cmd = CMD_OCU | CMD_LC;
1179 cmd->src = paddr(&data->ecc_cfg_save);
1180 cmd->dst = NAND_EBI2_ECC_BUF_CFG;
1181 cmd->len = 4;
1182
1183 /* ADM --> Default mux state (0xFC0) */
1184 cmd->cmd = 0;
1185 cmd->src = paddr(&data->adm_default_mux);
1186 cmd->dst = EBI2_NAND_ADM_MUX;
1187 cmd->len = 4;
1188 cmd++;
1189
1190 /* disable CS1 */
1191 cmd->cmd = 0;
1192 cmd->src = paddr(&data->default_ebi2_chip_select_cfg0);
1193 cmd->dst = EBI2_CHIP_SELECT_CFG0;
1194 cmd->len = 4;
1195 cmd++;
1196
1197 ptr[0] = (paddr(cmdlist) >> 3) | CMD_PTR_LP;
1198
1199 dmov_exec_cmdptr(DMOV_NAND_CHAN, ptr);
1200
1201#if VERBOSE
1202 dprintf(INFO, "read page %d: status: %x %x %x %x %x %x %x %x \
1203 %x %x %x %x %x %x %x %x \n", page,
1204 data->result[0].flash_status[0],
1205 data->result[1].flash_status[1],
1206 data->result[2].flash_status[2],
1207 data->result[3].flash_status[3],
1208 data->result[4].flash_status[4],
1209 data->result[5].flash_status[5],
1210 data->result[6].flash_status[6],
1211 data->result[7].flash_status[7],
1212 data->result[8].flash_status[8],
1213 data->result[9].flash_status[9],
1214 data->result[10].flash_status[10],
1215 data->result[11].flash_status[11],
1216 data->result[12].flash_status[12],
1217 data->result[13].flash_status[13],
1218 data->result[14].flash_status[14],
1219 data->result[15].flash_status[15]);
1220
1221 for(n = 0; n < 4; n++) {
1222 ptr = (unsigned*)(addr + 512 * n);
1223 dprintf(INFO, "data%d: %x %x %x %x\n", n, ptr[0], ptr[1], ptr[2], ptr[3]);
1224 ptr = (unsigned*)(spareaddr + 16 * n);
1225 dprintf(INFO, "spare data%d %x %x %x %x\n", n, ptr[0], ptr[1], ptr[2], ptr[3]);
1226 }
1227#endif
1228
1229 /* if any of the writes failed (0x10), or there was a
1230 ** protection violation (0x100), we lose
1231 */
1232 for(n = 0; n < cwperpage; n++) {
1233 if (data->result[n].flash_status & 0x110) {
1234 return -1;
1235 }
1236 }
1237
1238 return 0;
1239}
1240
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001241static int _flash_nand_write_page(dmov_s *cmdlist, unsigned *ptrlist, unsigned page,
Shashank Mittald0c836d2009-11-20 10:31:18 -08001242 const void *_addr, const void *_spareaddr, unsigned raw_mode)
Dima Zavin03cf4312009-01-23 16:38:30 -08001243{
1244 dmov_s *cmd = cmdlist;
1245 unsigned *ptr = ptrlist;
1246 struct data_flash_io *data = (void*) (ptrlist + 4);
1247 unsigned addr = (unsigned) _addr;
1248 unsigned spareaddr = (unsigned) _spareaddr;
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001249 unsigned n;
Shashank Mittaldcc2e352009-11-19 19:11:16 -08001250 unsigned cwperpage;
1251 cwperpage = (flash_pagesize >> 9);
Shashank Mittal8e49dec2010-03-01 15:19:04 -08001252 unsigned modem_partition = 0;
1253 if (CFG0 == CFG0_M)
1254 {
1255 modem_partition = 1;
1256 }
Dima Zavin03cf4312009-01-23 16:38:30 -08001257
1258 data->cmd = NAND_CMD_PRG_PAGE;
1259 data->addr0 = page << 16;
1260 data->addr1 = (page >> 16) & 0xff;
1261 data->chipsel = 0 | 4; /* flash0 + undoc bit */
Murali Palnatic54d13a2010-01-15 19:50:19 +05301262 data->clrfstatus = 0x00000020;
1263 data->clrrstatus = 0x000000C0;
Dima Zavin03cf4312009-01-23 16:38:30 -08001264
Shashank Mittald0c836d2009-11-20 10:31:18 -08001265 if (!raw_mode){
1266 data->cfg0 = CFG0;
1267 data->cfg1 = CFG1;
1268 }else{
1269 data->cfg0 = (NAND_CFG0_RAW & ~(7 << 6)) |((cwperpage-1) << 6);
1270 data->cfg1 = NAND_CFG1_RAW | (CFG1 & CFG1_WIDE_FLASH);
1271 }
Dima Zavin03cf4312009-01-23 16:38:30 -08001272
1273 /* GO bit for the EXEC register */
1274 data->exec = 1;
1275
Shashank Mittal8e49dec2010-03-01 15:19:04 -08001276 if (modem_partition)
1277 data->ecc_cfg = 0x1FF;
1278 else
1279 data->ecc_cfg = 0x203;
Dima Zavin03cf4312009-01-23 16:38:30 -08001280
1281 /* save existing ecc config */
1282 cmd->cmd = CMD_OCB;
1283 cmd->src = NAND_EBI2_ECC_BUF_CFG;
1284 cmd->dst = paddr(&data->ecc_cfg_save);
1285 cmd->len = 4;
1286 cmd++;
1287
Shashank Mittaldcc2e352009-11-19 19:11:16 -08001288 for(n = 0; n < cwperpage; n++) {
1289 /* write CMD / ADDR0 / ADDR1 / CHIPSEL regs in a burst */
Dima Zavin03cf4312009-01-23 16:38:30 -08001290 cmd->cmd = DST_CRCI_NAND_CMD;
1291 cmd->src = paddr(&data->cmd);
1292 cmd->dst = NAND_FLASH_CMD;
1293 cmd->len = ((n == 0) ? 16 : 4);
1294 cmd++;
1295
1296 if (n == 0) {
1297 /* set configuration */
1298 cmd->cmd = 0;
1299 cmd->src = paddr(&data->cfg0);
1300 cmd->dst = NAND_DEV0_CFG0;
1301 cmd->len = 8;
1302 cmd++;
1303
1304 /* set our ecc config */
1305 cmd->cmd = 0;
1306 cmd->src = paddr(&data->ecc_cfg);
1307 cmd->dst = NAND_EBI2_ECC_BUF_CFG;
1308 cmd->len = 4;
1309 cmd++;
1310 }
1311
1312 /* write data block */
1313 cmd->cmd = 0;
Dima Zavin03cf4312009-01-23 16:38:30 -08001314 cmd->dst = NAND_FLASH_BUFFER;
Shashank Mittald0c836d2009-11-20 10:31:18 -08001315 if (!raw_mode){
Shashank Mittal8e49dec2010-03-01 15:19:04 -08001316 if(modem_partition){
1317 cmd->src = addr + n * 512;
1318 cmd->len = 512;
1319 }else{
1320 cmd->src = addr + n * 516;
1321 cmd->len = ((n < (cwperpage - 1)) ? 516 : (512 - ((cwperpage - 1) << 2)));
1322 }
Shashank Mittald0c836d2009-11-20 10:31:18 -08001323 }else{
1324 cmd->src = addr;
1325 cmd->len = 528;
1326 }
Dima Zavin03cf4312009-01-23 16:38:30 -08001327 cmd++;
1328
Shashank Mittal8e49dec2010-03-01 15:19:04 -08001329 if ((n == (cwperpage - 1)) && (!raw_mode) && (!modem_partition)) {
Dima Zavin03cf4312009-01-23 16:38:30 -08001330 /* write extra data */
1331 cmd->cmd = 0;
1332 cmd->src = spareaddr;
Shashank Mittaldcc2e352009-11-19 19:11:16 -08001333 cmd->dst = NAND_FLASH_BUFFER + (512 - ((cwperpage - 1) << 2));
1334 cmd->len = (cwperpage << 2);
Dima Zavin03cf4312009-01-23 16:38:30 -08001335 cmd++;
1336 }
1337
1338 /* kick the execute register */
1339 cmd->cmd = 0;
1340 cmd->src = paddr(&data->exec);
1341 cmd->dst = NAND_EXEC_CMD;
1342 cmd->len = 4;
1343 cmd++;
1344
1345 /* block on data ready, then read the status register */
1346 cmd->cmd = SRC_CRCI_NAND_DATA;
1347 cmd->src = NAND_FLASH_STATUS;
1348 cmd->dst = paddr(&data->result[n]);
1349 cmd->len = 8;
1350 cmd++;
Murali Palnatic54d13a2010-01-15 19:50:19 +05301351
1352 cmd->cmd = 0;
1353 cmd->src = paddr(&data->clrfstatus);
1354 cmd->dst = NAND_FLASH_STATUS;
1355 cmd->len = 4;
1356 cmd++;
1357
1358 cmd->cmd = 0;
1359 cmd->src = paddr(&data->clrrstatus);
1360 cmd->dst = NAND_READ_STATUS;
1361 cmd->len = 4;
1362 cmd++;
Dima Zavin03cf4312009-01-23 16:38:30 -08001363 }
1364
1365 /* restore saved ecc config */
1366 cmd->cmd = CMD_OCU | CMD_LC;
1367 cmd->src = paddr(&data->ecc_cfg_save);
1368 cmd->dst = NAND_EBI2_ECC_BUF_CFG;
1369 cmd->len = 4;
1370
1371 ptr[0] = (paddr(cmdlist) >> 3) | CMD_PTR_LP;
1372
1373 dmov_exec_cmdptr(DMOV_NAND_CHAN, ptr);
1374
1375#if VERBOSE
1376 dprintf(INFO, "write page %d: status: %x %x %x %x\n",
1377 page, data[5], data[6], data[7], data[8]);
1378#endif
1379
1380 /* if any of the writes failed (0x10), or there was a
1381 ** protection violation (0x100), or the program success
1382 ** bit (0x80) is unset, we lose
1383 */
Shashank Mittaldcc2e352009-11-19 19:11:16 -08001384 for(n = 0; n < cwperpage; n++) {
Dima Zavin03cf4312009-01-23 16:38:30 -08001385 if(data->result[n].flash_status & 0x110) return -1;
1386 if(!(data->result[n].flash_status & 0x80)) return -1;
1387 }
1388
Dima Zavin5582c7d2009-03-03 15:17:59 -08001389#if VERIFY_WRITE
1390 n = _flash_read_page(cmdlist, ptrlist, page, flash_data,
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001391 flash_data + 2048);
Dima Zavin5582c7d2009-03-03 15:17:59 -08001392 if (n != 0)
1393 return -1;
1394 if (memcmp(flash_data, _addr, 2048) ||
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001395 memcmp(flash_data + 2048, _spareaddr, 16)) {
Dima Zavin5582c7d2009-03-03 15:17:59 -08001396 dprintf(CRITICAL, "verify error @ page %d\n", page);
1397 return -1;
1398 }
1399#endif
Dima Zavin03cf4312009-01-23 16:38:30 -08001400 return 0;
1401}
Murali Nalajalaa8c94c62010-03-05 20:24:30 +05301402
1403static int flash_nand_write_page_interleave(dmov_s *cmdlist, unsigned *ptrlist, unsigned page,
1404 const void *_addr, const void *_spareaddr, unsigned raw_mode)
1405{
1406 dmov_s *cmd = cmdlist;
1407 unsigned *ptr = ptrlist;
1408 struct interleave_data_flash_io *data = (void*) (ptrlist + 4);
1409 unsigned addr = (unsigned) _addr;
1410 unsigned spareaddr = (unsigned) _spareaddr;
1411 unsigned n;
1412 unsigned cwperpage, cwcount;
1413
1414 cwperpage = (flash_pagesize >> 9) * 2; /* double for interleave mode */
1415 cwcount = (cwperpage << 1);
1416
1417 data->cmd = NAND_CMD_PRG_PAGE;
1418 data->addr0 = page << 16;
1419 data->addr1 = (page >> 16) & 0xff;
1420 data->chipsel_cs0 = 0 | 4; /* flash0 + undoc bit */
1421 data->chipsel_cs1 = 0 | 5; /* flash0 + undoc bit */
1422 data->ebi2_chip_select_cfg0 = 0x00000805;
1423 data->adm_mux_data_ack_req_nc01 = 0x00000A3C;
1424 data->adm_mux_cmd_ack_req_nc01 = 0x0000053C;
1425 data->adm_mux_data_ack_req_nc10 = 0x00000F28;
1426 data->adm_mux_cmd_ack_req_nc10 = 0x00000F14;
1427 data->adm_default_mux = 0x00000FC0;
1428 data->default_ebi2_chip_select_cfg0 = 0x00000801;
1429
1430 if (!raw_mode){
1431 data->cfg0 = CFG0;
1432 data->cfg1 = CFG1;
1433 }else{
1434 data->cfg0 = (NAND_CFG0_RAW & ~(7 << 6)) |((cwcount-1) << 6);
1435 data->cfg1 = NAND_CFG1_RAW | (CFG1 & CFG1_WIDE_FLASH);
1436 }
1437
1438 /* GO bit for the EXEC register */
1439 data->exec = 1;
1440 data->ecc_cfg = 0x203;
1441
1442 for (n = 0; n < cwperpage; n++) {
1443 /* status return words */
1444 data->result[n].flash_status = 0xeeeeeeee;
1445
1446 if (n == 0) {
1447 /* enable CS1 */
1448 cmd->cmd = CMD_OCB;
1449 cmd->src = paddr(&data->ebi2_chip_select_cfg0);
1450 cmd->dst = EBI2_CHIP_SELECT_CFG0;
1451 cmd->len = 4;
1452 cmd++;
1453
1454 /* save existing ecc config */
1455 cmd->cmd = 0;
1456 cmd->src = NC11(NAND_EBI2_ECC_BUF_CFG);
1457 cmd->dst = paddr(&data->ecc_cfg_save);
1458 cmd->len = 4;
1459 cmd++;
1460
1461 cmd->cmd = 0;
1462 cmd->src = paddr(&data->ecc_cfg);
1463 cmd->dst = NC11(NAND_EBI2_ECC_BUF_CFG);
1464 cmd->len = 4;
1465 cmd++;
1466
1467 cmd->cmd = 0;
1468 cmd->src = paddr(&data->addr0);
1469 cmd->dst = NC11(NAND_ADDR0);
1470 cmd->len = 8;
1471 cmd++;
1472
1473 /* enable CS0 */
1474 cmd->cmd = 0;
1475 cmd->src = paddr(&data->chipsel_cs0);
1476 cmd->dst = NC01(NAND_FLASH_CHIP_SELECT);
1477 cmd->len = 4;
1478 cmd++;
1479
1480 /* enable CS1 */
1481 cmd->cmd = 0;
1482 cmd->src = paddr(&data->chipsel_cs1);
1483 cmd->dst = NC10(NAND_FLASH_CHIP_SELECT);
1484 cmd->len = 4;
1485 cmd++;
1486
1487 cmd->cmd = 0;
1488 cmd->src =paddr(&data->cfg0);
1489 cmd->dst = NC01(NAND_DEV0_CFG0);
1490 cmd->len = 8;
1491 cmd++;
1492
1493 /* config CFG1 for CS1 */
1494 cmd->cmd = 0;
1495 cmd->src =paddr(&data->cfg0);
1496 cmd->dst = NC10(NAND_DEV1_CFG0);
1497 cmd->len = 8;
1498 cmd++;
1499 }
1500
1501 if (n % 2 == 0) {
1502 /* MASK CMD ACK/REQ --> NC10 (0xF14)*/
1503 cmd->cmd = 0;
1504 cmd->src = paddr(&data->adm_mux_cmd_ack_req_nc10);
1505 cmd->dst = EBI2_NAND_ADM_MUX;
1506 cmd->len = 4;
1507 cmd++;
1508
1509 /* CMD */
1510 cmd->cmd = DST_CRCI_NAND_CMD;
1511 cmd->src = paddr(&data->cmd);
1512 cmd->dst = NC01(NAND_FLASH_CMD);
1513 cmd->len = 4;
1514 cmd++;
1515 } else {
1516 /* MASK CMD ACK/REQ --> NC01 (0x53C)*/
1517 cmd->cmd = 0;
1518 cmd->src = paddr(&data->adm_mux_cmd_ack_req_nc01);
1519 cmd->dst = EBI2_NAND_ADM_MUX;
1520 cmd->len = 4;
1521 cmd++;
1522
1523 /* CMD */
1524 cmd->cmd = DST_CRCI_NAND_CMD;
1525 cmd->src = paddr(&data->cmd);
1526 cmd->dst = NC10(NAND_FLASH_CMD);
1527 cmd->len = 4;
1528 cmd++;
1529 }
1530
1531 cmd->cmd = 0;
1532 if (!raw_mode){
1533 cmd->src = addr + n * 516;
1534 cmd->len = ((n < (cwperpage - 1)) ? 516 : (512 - ((cwperpage - 1) << 2)));
1535 }else{
1536 cmd->src = addr;
1537 cmd->len = 528;
1538 }
1539
1540 if (n % 2 == 0)
1541 cmd->dst = NC01(NAND_FLASH_BUFFER);
1542 else
1543 cmd->dst = NC10(NAND_FLASH_BUFFER);
1544 cmd++;
1545
1546 if ((n == (cwperpage - 1)) && (!raw_mode)) {
1547 /* write extra data */
1548 cmd->cmd = 0;
1549 cmd->src = spareaddr;
1550 cmd->dst = NC10(NAND_FLASH_BUFFER) + (512 - ((cwperpage - 1) << 2));
1551 cmd->len = (cwperpage << 2);
1552 cmd++;
1553 }
1554
1555 if (n % 2 == 0) {
1556 /* kick the NC01 execute register */
1557 cmd->cmd = 0;
1558 cmd->src = paddr(&data->exec);
1559 cmd->dst = NC01(NAND_EXEC_CMD);
1560 cmd->len = 4;
1561 cmd++;
1562 if (n != 0) {
1563 /* MASK DATA ACK/REQ --> NC01 (0xA3C)*/
1564 cmd->cmd = 0;
1565 cmd->src = paddr(&data->adm_mux_data_ack_req_nc01);
1566 cmd->dst = EBI2_NAND_ADM_MUX;
1567 cmd->len = 4;
1568 cmd++;
1569
1570 /* block on data ready from NC10, then
1571 * read the status register
1572 */
1573 cmd->cmd = SRC_CRCI_NAND_DATA;
1574 cmd->src = NC10(NAND_FLASH_STATUS);
1575 cmd->dst = paddr(&data->result[n-1]);
1576 cmd->len = 4;
1577 cmd++;
1578 }
1579 } else {
1580 /* kick the execute register */
1581 cmd->cmd = 0;
1582 cmd->src = paddr(&data->exec);
1583 cmd->dst = NC10(NAND_EXEC_CMD);
1584 cmd->len = 4;
1585 cmd++;
1586
1587 /* MASK DATA ACK/REQ --> NC10 (0xF28)*/
1588 cmd->cmd = 0;
1589 cmd->src = paddr(&data->adm_mux_data_ack_req_nc10);
1590 cmd->dst = EBI2_NAND_ADM_MUX;
1591 cmd->len = 4;
1592 cmd++;
1593
1594 /* block on data ready from NC01, then
1595 * read the status register
1596 */
1597 cmd->cmd = SRC_CRCI_NAND_DATA;
1598 cmd->src = NC01(NAND_FLASH_STATUS);
1599 cmd->dst = paddr(&data->result[n-1]);
1600 cmd->len = 4;
1601 cmd++;
1602 }
1603 }
1604
1605 /* MASK DATA ACK/REQ --> NC01 (0xA3C)*/
1606 cmd->cmd = 0;
1607 cmd->src = paddr(&data->adm_mux_data_ack_req_nc01);
1608 cmd->dst = EBI2_NAND_ADM_MUX;
1609 cmd->len = 4;
1610 cmd++;
1611
1612 /* we should process outstanding request */
1613 /* block on data ready, then
1614 * read the status register
1615 */
1616 cmd->cmd = SRC_CRCI_NAND_DATA;
1617 cmd->src = NC10(NAND_FLASH_STATUS);
1618 cmd->dst = paddr(&data->result[n-1]);
1619 cmd->len = 4;
1620 cmd++;
1621
1622 /* restore saved ecc config */
1623 cmd->cmd = 0;
1624 cmd->src = paddr(&data->ecc_cfg_save);
1625 cmd->dst = NAND_EBI2_ECC_BUF_CFG;
1626 cmd->len = 4;
1627
1628 /* MASK DATA ACK/REQ --> NC01 (0xFC0)*/
1629 cmd->cmd = 0;
1630 cmd->src = paddr(&data->adm_default_mux);
1631 cmd->dst = EBI2_NAND_ADM_MUX;
1632 cmd->len = 4;
1633 cmd++;
1634
1635 /* disable CS1 */
1636 cmd->cmd = CMD_OCU | CMD_LC;
1637 cmd->src = paddr(&data->default_ebi2_chip_select_cfg0);
1638 cmd->dst = EBI2_CHIP_SELECT_CFG0;
1639 cmd->len = 4;
1640 cmd++;
1641
1642 ptr[0] = (paddr(cmdlist) >> 3) | CMD_PTR_LP;
1643
1644 dmov_exec_cmdptr(DMOV_NAND_CHAN, ptr);
1645
1646#if VERBOSE
1647dprintf(INFO, "write page %d: status: %x %x %x %x %x %x %x %x \
1648 %x %x %x %x %x %x %x %x \n", page,
1649 data->result[0].flash_status[0],
1650 data->result[1].flash_status[1],
1651 data->result[2].flash_status[2],
1652 data->result[3].flash_status[3],
1653 data->result[4].flash_status[4],
1654 data->result[5].flash_status[5],
1655 data->result[6].flash_status[6],
1656 data->result[7].flash_status[7],
1657 data->result[8].flash_status[8],
1658 data->result[9].flash_status[9],
1659 data->result[10].flash_status[10],
1660 data->result[11].flash_status[11],
1661 data->result[12].flash_status[12],
1662 data->result[13].flash_status[13],
1663 data->result[14].flash_status[14],
1664 data->result[15].flash_status[15]);
1665#endif
1666
1667 /* if any of the writes failed (0x10), or there was a
1668 ** protection violation (0x100), or the program success
1669 ** bit (0x80) is unset, we lose
1670 */
1671 for(n = 0; n < cwperpage; n++) {
1672 if(data->result[n].flash_status & 0x110) return -1;
1673 if(!(data->result[n].flash_status & 0x80)) return -1;
1674 }
1675
1676#if VERIFY_WRITE
1677 n = _flash_read_page(cmdlist, ptrlist, page, flash_data,
1678 flash_data + 2048);
1679 if (n != 0)
1680 return -1;
1681 if (memcmp(flash_data, _addr, 2048) ||
1682 memcmp(flash_data + 2048, _spareaddr, 16)) {
1683 dprintf(CRITICAL, "verify error @ page %d\n", page);
1684 return -1;
1685 }
1686#endif
1687 return 0;
1688}
1689
Shashank Mittald0c836d2009-11-20 10:31:18 -08001690char empty_buf[528];
1691static int flash_nand_mark_badblock(dmov_s *cmdlist, unsigned *ptrlist, unsigned page)
1692{
1693 memset(empty_buf,0,528);
1694 /* Going to first page of the block */
1695 if(page & 63)
1696 page = page - (page & 63);
1697 return _flash_nand_write_page(cmdlist, ptrlist, page, empty_buf, 0, 1);
1698}
Dima Zavin03cf4312009-01-23 16:38:30 -08001699
Shashank Mittal83d16d02009-11-18 16:54:42 -08001700unsigned nand_cfg0;
1701unsigned nand_cfg1;
1702
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001703static int flash_nand_read_config(dmov_s *cmdlist, unsigned *ptrlist)
Dima Zavin03cf4312009-01-23 16:38:30 -08001704{
Shashank Mittal8e49dec2010-03-01 15:19:04 -08001705 static unsigned CFG0_TMP, CFG1_TMP;
Dima Zavin03cf4312009-01-23 16:38:30 -08001706 cmdlist[0].cmd = CMD_OCB;
1707 cmdlist[0].src = NAND_DEV0_CFG0;
Shashank Mittal8e49dec2010-03-01 15:19:04 -08001708 cmdlist[0].dst = paddr(&CFG0_TMP);
Dima Zavin03cf4312009-01-23 16:38:30 -08001709 cmdlist[0].len = 4;
1710
1711 cmdlist[1].cmd = CMD_OCU | CMD_LC;
1712 cmdlist[1].src = NAND_DEV0_CFG1;
Shashank Mittal8e49dec2010-03-01 15:19:04 -08001713 cmdlist[1].dst = paddr(&CFG1_TMP);
Dima Zavin03cf4312009-01-23 16:38:30 -08001714 cmdlist[1].len = 4;
1715
1716 *ptrlist = (paddr(cmdlist) >> 3) | CMD_PTR_LP;
1717
1718 dmov_exec_cmdptr(DMOV_NAND_CHAN, ptrlist);
1719
Shashank Mittal8e49dec2010-03-01 15:19:04 -08001720 if((CFG0_TMP == 0) || (CFG1_TMP == 0)) {
Dima Zavin03cf4312009-01-23 16:38:30 -08001721 return -1;
1722 }
1723
Shashank Mittal8e49dec2010-03-01 15:19:04 -08001724 CFG0_A = CFG0_TMP;
1725 CFG1_A = CFG1_TMP;
Shashank Mittal83d16d02009-11-18 16:54:42 -08001726 if (flash_info.type == FLASH_16BIT_NAND_DEVICE) {
1727 nand_cfg1 |= CFG1_WIDE_FLASH;
1728 }
Dima Zavin03cf4312009-01-23 16:38:30 -08001729 dprintf(INFO, "nandcfg: %x %x (initial)\n", CFG0, CFG1);
1730
Shashank Mittal8e49dec2010-03-01 15:19:04 -08001731 CFG0_A = (((flash_pagesize >> 9) - 1) << 6) /* 4/8 cw/pg for 2/4k */
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001732 | (516 << 9) /* 516 user data bytes */
1733 | (10 << 19) /* 10 parity bytes */
1734 | (5 << 27) /* 5 address cycles */
Murali Palnatic54d13a2010-01-15 19:50:19 +05301735 | (0 << 30) /* Do not read status before data */
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001736 | (1 << 31) /* Send read cmd */
1737 /* 0 spare bytes for 16 bit nand or 1 spare bytes for 8 bit */
1738 | ((nand_cfg1 & CFG1_WIDE_FLASH) ? (0 << 23) : (1 << 23));
Shashank Mittal8e49dec2010-03-01 15:19:04 -08001739 CFG1_A = (0 << 0) /* Enable ecc */
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001740 | (7 << 2) /* 8 recovery cycles */
1741 | (0 << 5) /* Allow CS deassertion */
Shashank Mittaldcc2e352009-11-19 19:11:16 -08001742 | ((flash_pagesize - (528 * ((flash_pagesize >> 9) - 1)) + 1) << 6) /* Bad block marker location */
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001743 | (0 << 16) /* Bad block in user data area */
1744 | (2 << 17) /* 6 cycle tWB/tRB */
1745 | (nand_cfg1 & CFG1_WIDE_FLASH); /* preserve wide flash flag */
Dima Zavin03cf4312009-01-23 16:38:30 -08001746
Shashank Mittal8e49dec2010-03-01 15:19:04 -08001747 dprintf(INFO, "nandcfg(Apps): %x %x (used)\n", CFG0_A, CFG1_A);
Dima Zavin03cf4312009-01-23 16:38:30 -08001748
Shashank Mittal8e49dec2010-03-01 15:19:04 -08001749 CFG0_M = CFG0_TMP;
1750 CFG1_M = CFG1_TMP;
1751 if (flash_info.type == FLASH_16BIT_NAND_DEVICE) {
1752 nand_cfg1 |= CFG1_WIDE_FLASH;
1753 }
1754 CFG0_M = (((flash_pagesize >> 9) - 1) << 6) /* 4/8 cw/pg for 2/4k */
1755 | (512 << 9) /* 512 user data bytes */
1756 | (10 << 19) /* 10 parity bytes */
1757 | (5 << 27) /* 5 address cycles */
1758 | (0 << 30) /* Do not read status before data */
1759 | (1 << 31) /* Send read cmd */
1760 | ((nand_cfg1 & CFG1_WIDE_FLASH) ? (4 << 23) : (5 << 23));
1761 CFG1_M = (0 << 0) /* Enable ecc */
1762 | (7 << 2) /* 8 recovery cycles */
1763 | (0 << 5) /* Allow CS deassertion */
1764 | ((flash_pagesize - (528 * ((flash_pagesize >> 9) - 1)) + 1) << 6) /* Bad block marker location */
1765 | (0 << 16) /* Bad block in user data area */
1766 | (2 << 17) /* 6 cycle tWB/tRB */
1767 | (nand_cfg1 & CFG1_WIDE_FLASH); /* preserve wide flash flag */
1768 dprintf(INFO, "nandcfg(Modem): %x %x (used)\n", CFG0_M, CFG1_M);
Dima Zavin03cf4312009-01-23 16:38:30 -08001769 return 0;
1770}
1771
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001772/* OneNAND programming functions */
1773
1774static void flash_onenand_read_id(dmov_s *cmdlist, unsigned *ptrlist)
1775{
1776 dmov_s *cmd = cmdlist;
1777 unsigned *ptr = ptrlist;
1778 unsigned *data = ptrlist + 4;
1779
1780 data[0] = SFLASH_BCFG;
1781 data[1] = SFLASH_PREPCMD(8, 0, 0, NAND_SFCMD_DATXS, NAND_SFCMD_ASYNC, NAND_SFCMD_REGRD);
1782 data[2] = (ONENAND_DEVICE_ID << 16) | (ONENAND_MANUFACTURER_ID);
1783 data[3] = (ONENAND_DATA_BUFFER_SIZE << 16) | (ONENAND_VERSION_ID);
1784 data[4] = (ONENAND_AMOUNT_OF_BUFFERS << 16) | (ONENAND_BOOT_BUFFER_SIZE);
1785 data[5] = (CLEAN_DATA_16 << 16) | (ONENAND_TECHNOLOGY);
1786 data[6] = CLEAN_DATA_32; //status
1787 data[7] = CLEAN_DATA_32; //register read
1788 data[8] = CLEAN_DATA_32; //register read
1789 data[9] = CLEAN_DATA_32; //register read
1790 data[10] = CLEAN_DATA_32; //register read
1791 data[11] = 1;
1792 data[12] = 0 | 4;
1793
1794 /* Setup controller in SFLASH mode */
1795 cmd[0].cmd = 0 | CMD_OCB;
1796 cmd[0].src = paddr(&data[0]);
1797 cmd[0].dst = NAND_SFLASHC_BURST_CFG;
1798 cmd[0].len = 4;
1799
1800 /* Enable data mover for controller */
1801 cmd[1].cmd = 0;
1802 cmd[1].src = paddr(&data[12]);
1803 cmd[1].dst = NAND_FLASH_CHIP_SELECT;
1804 cmd[1].len = 4;
1805
1806 /* Setup SFLASHC_CMD with xfers in async mode */
1807 cmd[2].cmd = DST_CRCI_NAND_CMD;
1808 cmd[2].src = paddr(&data[1]);
1809 cmd[2].dst = NAND_SFLASHC_CMD;
1810 cmd[2].len = 4;
1811
1812 /* Setup to read device information */
1813 cmd[3].cmd = 0;
1814 cmd[3].src = paddr(&data[2]);
1815 cmd[3].dst = NAND_ADDR0;
1816 cmd[3].len = 8;
1817
1818 cmd[4].cmd = 0;
1819 cmd[4].src = paddr(&data[4]);
1820 cmd[4].dst = NAND_ADDR2;
1821 cmd[4].len = 8;
1822
1823 /* Set execute bit */
1824 cmd[5].cmd = 0;
1825 cmd[5].src = paddr(&data[11]);
1826 cmd[5].dst = NAND_SFLASHC_EXEC_CMD;
1827 cmd[5].len = 4;
1828
1829 /* Check status */
1830 cmd[6].cmd = SRC_CRCI_NAND_DATA;
1831 cmd[6].src = NAND_SFLASHC_STATUS;
1832 cmd[6].dst = paddr(&data[6]);
1833 cmd[6].len = 4;
1834
1835 /* Read result device registers */
1836 cmd[7].cmd = 0 | CMD_OCU | CMD_LC;
1837 cmd[7].src = NAND_GENP_REG0;
1838 cmd[7].dst = paddr(&data[7]);
1839 cmd[7].len = 16;
1840
1841 ptr[0] = (paddr(cmd) >> 3) | CMD_PTR_LP;
1842
1843 dmov_exec_cmdptr(DMOV_NAND_CHAN, ptr);
1844
1845#if VERBOSE
1846 dprintf(INFO, "status: %x\n", data[6]);
1847#endif
1848
1849 flash_info.id = data[7];
1850 flash_info.vendor = data[7] & CLEAN_DATA_16;
1851 flash_info.device = (data[7] >> 16) & CLEAN_DATA_16;
1852 return;
1853}
1854
1855
1856struct data_onenand_erase {
1857 unsigned sfbcfg;
1858 unsigned sfcmd[4];
1859 unsigned sfexec;
1860 unsigned sfstat[4];
1861 unsigned addr0;
1862 unsigned addr1;
1863 unsigned addr2;
1864 unsigned addr3;
1865 unsigned addr4;
1866 unsigned addr5;
1867 unsigned addr6;
1868 unsigned data0;
1869 unsigned data1;
1870 unsigned data2;
1871 unsigned data3;
1872 unsigned data4;
1873 unsigned data5;
1874 unsigned data6;
1875};
1876
Shashank Mittalad3d05c2009-11-19 15:53:57 -08001877
1878static int _flash_onenand_read_page(dmov_s *cmdlist, unsigned *ptrlist,
1879 unsigned page, void *_addr,
1880 void *_spareaddr, unsigned raw_mode);
1881
1882
1883static int flash_onenand_block_isbad(dmov_s *cmdlist, unsigned *ptrlist,
1884 unsigned page)
1885{
1886 unsigned char page_data[2112];
1887 unsigned char *oobptr = &(page_data[2048]);
1888
1889 /* Going to first page of the block */
1890 if(page & 63)
1891 page = page - (page & 63);
1892
1893 /* Reading page in raw mode */
1894 if (_flash_onenand_read_page(cmdlist, ptrlist,page, page_data, 0, 1))
1895 return 1;
1896
1897 /* Checking if block is bad */
1898 if ((oobptr[0] != 0xFF) || (oobptr[1] != 0xFF) ||
1899 (oobptr[16] != 0xFF) || (oobptr[17] != 0xFF) ||
1900 (oobptr[32] != 0xFF) || (oobptr[33] != 0xFF) ||
1901 (oobptr[48] != 0xFF) || (oobptr[49] != 0xFF)
1902 )
1903 {
1904 return 1;
1905 }
1906 return 0;
1907}
1908
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001909static int flash_onenand_erase_block(dmov_s *cmdlist, unsigned *ptrlist,
1910 unsigned page)
1911{
1912 dmov_s *cmd = cmdlist;
1913 unsigned *ptr = ptrlist;
1914 struct data_onenand_erase *data = (void *)ptrlist + 4;
Shashank Mittalad3d05c2009-11-19 15:53:57 -08001915 int isbad = 0;
Shashank Mittaldcc2e352009-11-19 19:11:16 -08001916 unsigned erasesize = (flash_pagesize << 6);
1917 unsigned onenand_startaddr1 = DEVICE_FLASHCORE_0 | (page * flash_pagesize)/erasesize;
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001918 unsigned onenand_startaddr8 = 0x0000;
1919 unsigned onenand_startaddr2 = DEVICE_BUFFERRAM_0 << 15;
1920 unsigned onenand_startbuffer = DATARAM0_0 << 8;
1921
1922 unsigned controller_status;
1923 unsigned interrupt_status;
1924 unsigned ecc_status;
1925
Shashank Mittaldcc2e352009-11-19 19:11:16 -08001926 if((page * flash_pagesize) & (erasesize-1)) return -1;
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001927
Shashank Mittalad3d05c2009-11-19 15:53:57 -08001928 /* Check for bad block and erase only if block is not marked bad */
1929 isbad = flash_onenand_block_isbad(cmdlist, ptrlist, page);
1930 if (isbad)
1931 {
1932 dprintf(INFO, "skipping @ %d (bad block)\n", page >> 6);
1933 return -1;
1934 }
1935
1936 /*Erase block*/
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001937 onenand_startaddr1 = DEVICE_FLASHCORE_0 |
Shashank Mittaldcc2e352009-11-19 19:11:16 -08001938 ((page * flash_pagesize) / (erasesize));
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001939 onenand_startaddr8 = 0x0000;
1940 onenand_startaddr2 = DEVICE_BUFFERRAM_0 << 15;
1941 onenand_startbuffer = DATARAM0_0 << 8;
1942
1943
1944 data->sfbcfg = SFLASH_BCFG;
1945 data->sfcmd[0] = SFLASH_PREPCMD(7, 0, 0,
1946 NAND_SFCMD_CMDXS,
1947 NAND_SFCMD_ASYNC,
1948 NAND_SFCMD_REGWR);
1949 data->sfcmd[1] = SFLASH_PREPCMD(0, 0, 32,
1950 NAND_SFCMD_CMDXS,
1951 NAND_SFCMD_ASYNC,
1952 NAND_SFCMD_INTHI);
1953 data->sfcmd[2] = SFLASH_PREPCMD(3, 7, 0,
1954 NAND_SFCMD_DATXS,
1955 NAND_SFCMD_ASYNC,
1956 NAND_SFCMD_REGRD);
1957 data->sfcmd[3] = SFLASH_PREPCMD(4, 10, 0,
1958 NAND_SFCMD_CMDXS,
1959 NAND_SFCMD_ASYNC,
1960 NAND_SFCMD_REGWR);
1961 data->sfexec = 1;
1962 data->sfstat[0] = CLEAN_DATA_32;
1963 data->sfstat[1] = CLEAN_DATA_32;
1964 data->sfstat[2] = CLEAN_DATA_32;
1965 data->sfstat[3] = CLEAN_DATA_32;
1966 data->addr0 = (ONENAND_INTERRUPT_STATUS << 16) |
1967 (ONENAND_SYSTEM_CONFIG_1);
1968 data->addr1 = (ONENAND_START_ADDRESS_8 << 16) |
1969 (ONENAND_START_ADDRESS_1);
1970 data->addr2 = (ONENAND_START_BUFFER << 16) |
1971 (ONENAND_START_ADDRESS_2);
1972 data->addr3 = (ONENAND_ECC_STATUS << 16) |
1973 (ONENAND_COMMAND);
1974 data->addr4 = (ONENAND_CONTROLLER_STATUS << 16) |
1975 (ONENAND_INTERRUPT_STATUS);
1976 data->addr5 = (ONENAND_INTERRUPT_STATUS << 16) |
1977 (ONENAND_SYSTEM_CONFIG_1);
1978 data->addr6 = (ONENAND_START_ADDRESS_3 << 16) |
1979 (ONENAND_START_ADDRESS_1);
1980 data->data0 = (ONENAND_CLRINTR << 16) |
1981 (ONENAND_SYSCFG1_ECCENA);
1982 data->data1 = (onenand_startaddr8 << 16) |
1983 (onenand_startaddr1);
1984 data->data2 = (onenand_startbuffer << 16) |
1985 (onenand_startaddr2);
1986 data->data3 = (CLEAN_DATA_16 << 16) |
1987 (ONENAND_CMDERAS);
1988 data->data4 = (CLEAN_DATA_16 << 16) |
1989 (CLEAN_DATA_16);
1990 data->data5 = (ONENAND_CLRINTR << 16) |
1991 (ONENAND_SYSCFG1_ECCENA);
1992 data->data6 = (ONENAND_STARTADDR3_RES << 16) |
1993 (ONENAND_STARTADDR1_RES);
1994
1995 /***************************************************************/
1996 /* Write the necessary address registers in the onenand device */
1997 /***************************************************************/
1998
1999 /* Enable and configure the SFlash controller */
2000 cmd->cmd = 0 | CMD_OCB;
2001 cmd->src = paddr(&data->sfbcfg);
2002 cmd->dst = NAND_SFLASHC_BURST_CFG;
2003 cmd->len = 4;
2004 cmd++;
2005
2006 /* Block on cmd ready and write CMD register */
2007 cmd->cmd = DST_CRCI_NAND_CMD;
2008 cmd->src = paddr(&data->sfcmd[0]);
2009 cmd->dst = NAND_SFLASHC_CMD;
2010 cmd->len = 4;
2011 cmd++;
2012
2013 /* Write the ADDR0 and ADDR1 registers */
2014 cmd->cmd = 0;
2015 cmd->src = paddr(&data->addr0);
2016 cmd->dst = NAND_ADDR0;
2017 cmd->len = 8;
2018 cmd++;
2019
2020 /* Write the ADDR2 ADDR3 ADDR4 ADDR5 registers */
2021 cmd->cmd = 0;
2022 cmd->src = paddr(&data->addr2);
2023 cmd->dst = NAND_ADDR2;
2024 cmd->len = 16;
2025 cmd++;
2026
2027 /* Write the ADDR6 registers */
2028 cmd->cmd = 0;
2029 cmd->src = paddr(&data->addr6);
2030 cmd->dst = NAND_ADDR6;
2031 cmd->len = 4;
2032 cmd++;
2033
2034 /* Write the GENP0, GENP1, GENP2, GENP3, GENP4 registers */
2035 cmd->cmd = 0;
2036 cmd->src = paddr(&data->data0);
2037 cmd->dst = NAND_GENP_REG0;
2038 cmd->len = 16;
2039 cmd++;
2040
2041 /* Write the FLASH_DEV_CMD4,5,6 registers */
2042 cmd->cmd = 0;
2043 cmd->src = paddr(&data->data4);
2044 cmd->dst = NAND_DEV_CMD4;
2045 cmd->len = 12;
2046 cmd++;
2047
2048 /* Kick the execute command */
2049 cmd->cmd = 0;
2050 cmd->src = paddr(&data->sfexec);
2051 cmd->dst = NAND_SFLASHC_EXEC_CMD;
2052 cmd->len = 4;
2053 cmd++;
2054
2055 /* Block on data ready, and read the status register */
2056 cmd->cmd = SRC_CRCI_NAND_DATA;
2057 cmd->src = NAND_SFLASHC_STATUS;
2058 cmd->dst = paddr(&data->sfstat[0]);
2059 cmd->len = 4;
2060 cmd++;
2061
2062 /***************************************************************/
2063 /* Wait for the interrupt from the Onenand device controller */
2064 /***************************************************************/
2065
2066 /* Block on cmd ready and write CMD register */
2067 cmd->cmd = DST_CRCI_NAND_CMD;
2068 cmd->src = paddr(&data->sfcmd[1]);
2069 cmd->dst = NAND_SFLASHC_CMD;
2070 cmd->len = 4;
2071 cmd++;
2072
2073 /* Kick the execute command */
2074 cmd->cmd = 0;
2075 cmd->src = paddr(&data->sfexec);
2076 cmd->dst = NAND_SFLASHC_EXEC_CMD;
2077 cmd->len = 4;
2078 cmd++;
2079
2080 /* Block on data ready, and read the status register */
2081 cmd->cmd = SRC_CRCI_NAND_DATA;
2082 cmd->src = NAND_SFLASHC_STATUS;
2083 cmd->dst = paddr(&data->sfstat[1]);
2084 cmd->len = 4;
2085 cmd++;
2086
2087 /***************************************************************/
2088 /* Read the necessary status registers from the onenand device */
2089 /***************************************************************/
2090
2091 /* Block on cmd ready and write CMD register */
2092 cmd->cmd = DST_CRCI_NAND_CMD;
2093 cmd->src = paddr(&data->sfcmd[2]);
2094 cmd->dst = NAND_SFLASHC_CMD;
2095 cmd->len = 4;
2096 cmd++;
2097
2098 /* Kick the execute command */
2099 cmd->cmd = 0;
2100 cmd->src = paddr(&data->sfexec);
2101 cmd->dst = NAND_SFLASHC_EXEC_CMD;
2102 cmd->len = 4;
2103 cmd++;
2104
2105 /* Block on data ready, and read the status register */
2106 cmd->cmd = SRC_CRCI_NAND_DATA;
2107 cmd->src = NAND_SFLASHC_STATUS;
2108 cmd->dst = paddr(&data->sfstat[2]);
2109 cmd->len = 4;
2110 cmd++;
2111
2112 /* Read the GENP3 register */
2113 cmd->cmd = 0;
2114 cmd->src = NAND_GENP_REG3;
2115 cmd->dst = paddr(&data->data3);
2116 cmd->len = 4;
2117 cmd++;
2118
2119 /* Read the DEVCMD4 register */
2120 cmd->cmd = 0;
2121 cmd->src = NAND_DEV_CMD4;
2122 cmd->dst = paddr(&data->data4);
2123 cmd->len = 4;
2124 cmd++;
2125
2126 /***************************************************************/
2127 /* Restore the necessary registers to proper values */
2128 /***************************************************************/
2129
2130 /* Block on cmd ready and write CMD register */
2131 cmd->cmd = DST_CRCI_NAND_CMD;
2132 cmd->src = paddr(&data->sfcmd[3]);
2133 cmd->dst = NAND_SFLASHC_CMD;
2134 cmd->len = 4;
2135 cmd++;
2136
2137 /* Kick the execute command */
2138 cmd->cmd = 0;
2139 cmd->src = paddr(&data->sfexec);
2140 cmd->dst = NAND_SFLASHC_EXEC_CMD;
2141 cmd->len = 4;
2142 cmd++;
2143
2144 /* Block on data ready, and read the status register */
2145 cmd->cmd = SRC_CRCI_NAND_DATA | CMD_OCU | CMD_LC;
2146 cmd->src = NAND_SFLASHC_STATUS;
2147 cmd->dst = paddr(&data->sfstat[3]);
2148 cmd->len = 4;
2149 cmd++;
2150
2151 ptr[0] = (paddr(cmdlist) >> 3) | CMD_PTR_LP;
2152
2153 dmov_exec_cmdptr(DMOV_NAND_CHAN, ptr);
2154
2155 ecc_status = (data->data3 >> 16) & 0x0000FFFF;
2156 interrupt_status = (data->data4 >> 0) & 0x0000FFFF;
2157 controller_status = (data->data4 >> 16) & 0x0000FFFF;
2158
2159#if VERBOSE
2160 dprintf(INFO, "\n%s: sflash status %x %x %x %x\n", __func__,
2161 data->sfstat[0],
2162 data->sfstat[1],
2163 data->sfstat[2],
2164 data->sfstat[3]);
2165
2166 dprintf(INFO, "%s: controller_status = %x\n", __func__,
2167 controller_status);
2168 dprintf(INFO, "%s: interrupt_status = %x\n", __func__,
2169 interrupt_status);
2170 dprintf(INFO, "%s: ecc_status = %x\n", __func__,
2171 ecc_status);
2172#endif
2173 /* Check for errors, protection violations etc */
2174 if ((controller_status != 0)
2175 || (data->sfstat[0] & 0x110)
2176 || (data->sfstat[1] & 0x110)
2177 || (data->sfstat[2] & 0x110)
2178 || (data->sfstat[3] & 0x110)) {
2179 dprintf(CRITICAL, "%s: ECC/MPU/OP error\n", __func__);
2180 return -1;
2181 }
2182
2183
2184#if VERBOSE
2185 dprintf(INFO, "status: %x\n", data[5]);
2186#endif
2187
2188 return 0;
2189}
2190
2191
2192struct data_onenand_read {
2193 unsigned sfbcfg;
2194 unsigned sfcmd[9];
2195 unsigned sfexec;
2196 unsigned sfstat[9];
2197 unsigned addr0;
2198 unsigned addr1;
2199 unsigned addr2;
2200 unsigned addr3;
2201 unsigned addr4;
2202 unsigned addr5;
2203 unsigned addr6;
2204 unsigned data0;
2205 unsigned data1;
2206 unsigned data2;
2207 unsigned data3;
2208 unsigned data4;
2209 unsigned data5;
2210 unsigned data6;
2211 unsigned macro[5];
2212};
2213
2214
2215static int _flash_onenand_read_page(dmov_s *cmdlist, unsigned *ptrlist,
Shashank Mittalad3d05c2009-11-19 15:53:57 -08002216 unsigned page, void *_addr, void *_spareaddr,
2217 unsigned raw_mode)
Shashank Mittalc20b5a12009-11-18 19:35:30 -08002218{
2219 dmov_s *cmd = cmdlist;
2220 unsigned *ptr = ptrlist;
2221 struct data_onenand_read *data = (void*) (ptrlist + 4);
2222 unsigned addr = (unsigned) _addr;
2223 unsigned curr_addr = (unsigned) _addr;
2224 unsigned spareaddr = (unsigned) _spareaddr;
2225 unsigned i;
Shashank Mittaldcc2e352009-11-19 19:11:16 -08002226 unsigned erasesize = (flash_pagesize<<6);
2227 unsigned writesize = flash_pagesize;
Shashank Mittalc20b5a12009-11-18 19:35:30 -08002228
2229 unsigned onenand_startaddr1 = DEVICE_FLASHCORE_0 |
Shashank Mittaldcc2e352009-11-19 19:11:16 -08002230 ((unsigned)(page * flash_pagesize) / erasesize);
2231 unsigned onenand_startaddr8 = (((unsigned)(page * flash_pagesize) &
Shashank Mittalc20b5a12009-11-18 19:35:30 -08002232 (erasesize - 1)) / writesize) << 2;
2233 unsigned onenand_startaddr2 = DEVICE_BUFFERRAM_0 << 15;
2234 unsigned onenand_startbuffer = DATARAM0_0 << 8;
Shashank Mittalad3d05c2009-11-19 15:53:57 -08002235 unsigned onenand_sysconfig1 = (raw_mode == 1) ? ONENAND_SYSCFG1_ECCDIS :\
2236 ONENAND_SYSCFG1_ECCENA;
Shashank Mittalc20b5a12009-11-18 19:35:30 -08002237
2238 unsigned controller_status;
2239 unsigned interrupt_status;
2240 unsigned ecc_status;
Shashank Mittalad3d05c2009-11-19 15:53:57 -08002241 if (raw_mode != 1)
2242 {
2243 int isbad = 0;
2244 isbad = flash_onenand_block_isbad(cmdlist, ptrlist, page);
2245 if (isbad)
2246 return -2;
2247 }
Shashank Mittalc20b5a12009-11-18 19:35:30 -08002248
2249 //static int oobfree_offset[8] = {2, 14, 18, 30, 34, 46, 50, 62};
2250 //static int oobfree_length[8] = {3, 2, 3, 2, 3, 2, 3, 2};
2251
2252 data->sfbcfg = SFLASH_BCFG;
2253 data->sfcmd[0] = SFLASH_PREPCMD(7, 0, 0,
2254 NAND_SFCMD_CMDXS,
2255 NAND_SFCMD_ASYNC,
2256 NAND_SFCMD_REGWR);
2257 data->sfcmd[1] = SFLASH_PREPCMD(0, 0, 32,
2258 NAND_SFCMD_CMDXS,
2259 NAND_SFCMD_ASYNC,
2260 NAND_SFCMD_INTHI);
2261 data->sfcmd[2] = SFLASH_PREPCMD(3, 7, 0,
2262 NAND_SFCMD_DATXS,
2263 NAND_SFCMD_ASYNC,
2264 NAND_SFCMD_REGRD);
2265 data->sfcmd[3] = SFLASH_PREPCMD(256, 0, 0,
2266 NAND_SFCMD_DATXS,
2267 NAND_SFCMD_ASYNC,
2268 NAND_SFCMD_DATRD);
2269 data->sfcmd[4] = SFLASH_PREPCMD(256, 0, 0,
2270 NAND_SFCMD_DATXS,
2271 NAND_SFCMD_ASYNC,
2272 NAND_SFCMD_DATRD);
2273 data->sfcmd[5] = SFLASH_PREPCMD(256, 0, 0,
2274 NAND_SFCMD_DATXS,
2275 NAND_SFCMD_ASYNC,
2276 NAND_SFCMD_DATRD);
2277 data->sfcmd[6] = SFLASH_PREPCMD(256, 0, 0,
2278 NAND_SFCMD_DATXS,
2279 NAND_SFCMD_ASYNC,
2280 NAND_SFCMD_DATRD);
2281 data->sfcmd[7] = SFLASH_PREPCMD(32, 0, 0,
2282 NAND_SFCMD_DATXS,
2283 NAND_SFCMD_ASYNC,
2284 NAND_SFCMD_DATRD);
2285 data->sfcmd[8] = SFLASH_PREPCMD(4, 10, 0,
2286 NAND_SFCMD_CMDXS,
2287 NAND_SFCMD_ASYNC,
2288 NAND_SFCMD_REGWR);
2289 data->sfexec = 1;
2290 data->sfstat[0] = CLEAN_DATA_32;
2291 data->sfstat[1] = CLEAN_DATA_32;
2292 data->sfstat[2] = CLEAN_DATA_32;
2293 data->sfstat[3] = CLEAN_DATA_32;
2294 data->sfstat[4] = CLEAN_DATA_32;
2295 data->sfstat[5] = CLEAN_DATA_32;
2296 data->sfstat[6] = CLEAN_DATA_32;
2297 data->sfstat[7] = CLEAN_DATA_32;
2298 data->sfstat[8] = CLEAN_DATA_32;
2299
2300 data->addr0 = (ONENAND_INTERRUPT_STATUS << 16) |
2301 (ONENAND_SYSTEM_CONFIG_1);
2302 data->addr1 = (ONENAND_START_ADDRESS_8 << 16) |
2303 (ONENAND_START_ADDRESS_1);
2304 data->addr2 = (ONENAND_START_BUFFER << 16) |
2305 (ONENAND_START_ADDRESS_2);
2306 data->addr3 = (ONENAND_ECC_STATUS << 16) |
2307 (ONENAND_COMMAND);
2308 data->addr4 = (ONENAND_CONTROLLER_STATUS << 16) |
2309 (ONENAND_INTERRUPT_STATUS);
2310 data->addr5 = (ONENAND_INTERRUPT_STATUS << 16) |
2311 (ONENAND_SYSTEM_CONFIG_1);
2312 data->addr6 = (ONENAND_START_ADDRESS_3 << 16) |
2313 (ONENAND_START_ADDRESS_1);
2314 data->data0 = (ONENAND_CLRINTR << 16) |
2315 (onenand_sysconfig1);
2316 data->data1 = (onenand_startaddr8 << 16) |
2317 (onenand_startaddr1);
2318 data->data2 = (onenand_startbuffer << 16) |
2319 (onenand_startaddr2);
2320 data->data3 = (CLEAN_DATA_16 << 16) |
2321 (ONENAND_CMDLOADSPARE);
2322 data->data4 = (CLEAN_DATA_16 << 16) |
2323 (CLEAN_DATA_16);
2324 data->data5 = (ONENAND_CLRINTR << 16) |
2325 (ONENAND_SYSCFG1_ECCENA);
2326 data->data6 = (ONENAND_STARTADDR3_RES << 16) |
2327 (ONENAND_STARTADDR1_RES);
2328 data->macro[0] = 0x0200;
2329 data->macro[1] = 0x0300;
2330 data->macro[2] = 0x0400;
2331 data->macro[3] = 0x0500;
2332 data->macro[4] = 0x8010;
2333
2334 /*************************************************************/
2335 /* Write necessary address registers in the onenand device */
2336 /*************************************************************/
2337
2338 /* Enable and configure the SFlash controller */
2339 cmd->cmd = 0 | CMD_OCB;
2340 cmd->src = paddr(&data->sfbcfg);
2341 cmd->dst = NAND_SFLASHC_BURST_CFG;
2342 cmd->len = 4;
2343 cmd++;
2344
2345 /* Block on cmd ready and write CMD register */
2346 cmd->cmd = DST_CRCI_NAND_CMD;
2347 cmd->src = paddr(&data->sfcmd[0]);
2348 cmd->dst = NAND_SFLASHC_CMD;
2349 cmd->len = 4;
2350 cmd++;
2351
2352 /* Write the ADDR0 and ADDR1 registers */
2353 cmd->cmd = 0;
2354 cmd->src = paddr(&data->addr0);
2355 cmd->dst = NAND_ADDR0;
2356 cmd->len = 8;
2357 cmd++;
2358
2359 /* Write the ADDR2 ADDR3 ADDR4 ADDR5 registers */
2360 cmd->cmd = 0;
2361 cmd->src = paddr(&data->addr2);
2362 cmd->dst = NAND_ADDR2;
2363 cmd->len = 16;
2364 cmd++;
2365
2366 /* Write the ADDR6 registers */
2367 cmd->cmd = 0;
2368 cmd->src = paddr(&data->addr6);
2369 cmd->dst = NAND_ADDR6;
2370 cmd->len = 4;
2371 cmd++;
2372
2373 /* Write the GENP0, GENP1, GENP2, GENP3 registers */
2374 cmd->cmd = 0;
2375 cmd->src = paddr(&data->data0);
2376 cmd->dst = NAND_GENP_REG0;
2377 cmd->len = 16;
2378 cmd++;
2379
2380 /* Write the FLASH_DEV_CMD4,5,6 registers */
2381 cmd->cmd = 0;
2382 cmd->src = paddr(&data->data4);
2383 cmd->dst = NAND_DEV_CMD4;
2384 cmd->len = 12;
2385 cmd++;
2386
2387 /* Kick the execute command */
2388 cmd->cmd = 0;
2389 cmd->src = paddr(&data->sfexec);
2390 cmd->dst = NAND_SFLASHC_EXEC_CMD;
2391 cmd->len = 4;
2392 cmd++;
2393
2394 /* Block on data ready, and read the status register */
2395 cmd->cmd = SRC_CRCI_NAND_DATA;
2396 cmd->src = NAND_SFLASHC_STATUS;
2397 cmd->dst = paddr(&data->sfstat[0]);
2398 cmd->len = 4;
2399 cmd++;
2400
2401 /*************************************************************/
2402 /* Wait for the interrupt from the Onenand device controller */
2403 /*************************************************************/
2404
2405 /* Block on cmd ready and write CMD register */
2406 cmd->cmd = DST_CRCI_NAND_CMD;
2407 cmd->src = paddr(&data->sfcmd[1]);
2408 cmd->dst = NAND_SFLASHC_CMD;
2409 cmd->len = 4;
2410 cmd++;
2411
2412 /* Kick the execute command */
2413 cmd->cmd = 0;
2414 cmd->src = paddr(&data->sfexec);
2415 cmd->dst = NAND_SFLASHC_EXEC_CMD;
2416 cmd->len = 4;
2417 cmd++;
2418
2419 /* Block on data ready, and read the status register */
2420 cmd->cmd = SRC_CRCI_NAND_DATA;
2421 cmd->src = NAND_SFLASHC_STATUS;
2422 cmd->dst = paddr(&data->sfstat[1]);
2423 cmd->len = 4;
2424 cmd++;
2425
2426
2427 /*************************************************************/
2428 /* Read necessary status registers from the onenand device */
2429 /*************************************************************/
2430
2431 /* Block on cmd ready and write CMD register */
2432 cmd->cmd = DST_CRCI_NAND_CMD;
2433 cmd->src = paddr(&data->sfcmd[2]);
2434 cmd->dst = NAND_SFLASHC_CMD;
2435 cmd->len = 4;
2436 cmd++;
2437
2438 /* Kick the execute command */
2439 cmd->cmd = 0;
2440 cmd->src = paddr(&data->sfexec);
2441 cmd->dst = NAND_SFLASHC_EXEC_CMD;
2442 cmd->len = 4;
2443 cmd++;
2444
2445 /* Block on data ready, and read the status register */
2446 cmd->cmd = SRC_CRCI_NAND_DATA;
2447 cmd->src = NAND_SFLASHC_STATUS;
2448 cmd->dst = paddr(&data->sfstat[2]);
2449 cmd->len = 4;
2450 cmd++;
2451
2452 /* Read the GENP3 register */
2453 cmd->cmd = 0;
2454 cmd->src = NAND_GENP_REG3;
2455 cmd->dst = paddr(&data->data3);
2456 cmd->len = 4;
2457 cmd++;
2458
2459 /* Read the DEVCMD4 register */
2460 cmd->cmd = 0;
2461 cmd->src = NAND_DEV_CMD4;
2462 cmd->dst = paddr(&data->data4);
2463 cmd->len = 4;
2464 cmd++;
2465
2466
2467 /*************************************************************/
2468 /* Read the data ram area from the onenand buffer ram */
2469 /*************************************************************/
2470
2471 if (addr) {
2472
2473 data->data3 = (CLEAN_DATA_16 << 16) |
2474 (ONENAND_CMDLOAD);
2475
2476 for (i = 0; i < 4; i++) {
2477
2478 /* Block on cmd ready and write CMD register */
2479 cmd->cmd = DST_CRCI_NAND_CMD;
2480 cmd->src = paddr(&data->sfcmd[3+i]);
2481 cmd->dst = NAND_SFLASHC_CMD;
2482 cmd->len = 4;
2483 cmd++;
2484
2485 /* Write the MACRO1 register */
2486 cmd->cmd = 0;
2487 cmd->src = paddr(&data->macro[i]);
2488 cmd->dst = NAND_MACRO1_REG;
2489 cmd->len = 4;
2490 cmd++;
2491
2492 /* Kick the execute command */
2493 cmd->cmd = 0;
2494 cmd->src = paddr(&data->sfexec);
2495 cmd->dst = NAND_SFLASHC_EXEC_CMD;
2496 cmd->len = 4;
2497 cmd++;
2498
2499 /* Block on data rdy, & read status register */
2500 cmd->cmd = SRC_CRCI_NAND_DATA;
2501 cmd->src = NAND_SFLASHC_STATUS;
2502 cmd->dst = paddr(&data->sfstat[3+i]);
2503 cmd->len = 4;
2504 cmd++;
2505
2506 /* Transfer nand ctlr buf contents to usr buf */
2507 cmd->cmd = 0;
2508 cmd->src = NAND_FLASH_BUFFER;
2509 cmd->dst = curr_addr;
2510 cmd->len = 512;
2511 curr_addr += 512;
2512 cmd++;
2513 }
2514 }
2515
Shashank Mittalad3d05c2009-11-19 15:53:57 -08002516 /* Read oob bytes in Raw Mode */
2517 if (raw_mode == 1)
2518 {
2519 /* Block on cmd ready and write CMD register */
2520 cmd->cmd = DST_CRCI_NAND_CMD;
2521 cmd->src = paddr(&data->sfcmd[7]);
2522 cmd->dst = NAND_SFLASHC_CMD;
2523 cmd->len = 4;
2524 cmd++;
2525
2526 /* Write the MACRO1 register */
2527 cmd->cmd = 0;
2528 cmd->src = paddr(&data->macro[4]);
2529 cmd->dst = NAND_MACRO1_REG;
2530 cmd->len = 4;
2531 cmd++;
2532
2533 /* Kick the execute command */
2534 cmd->cmd = 0;
2535 cmd->src = paddr(&data->sfexec);
2536 cmd->dst = NAND_SFLASHC_EXEC_CMD;
2537 cmd->len = 4;
2538 cmd++;
2539
2540 /* Block on data rdy, & read status register */
2541 cmd->cmd = SRC_CRCI_NAND_DATA;
2542 cmd->src = NAND_SFLASHC_STATUS;
2543 cmd->dst = paddr(&data->sfstat[7]);
2544 cmd->len = 4;
2545 cmd++;
2546
2547 /* Transfer nand ctlr buf contents to usr buf */
2548 cmd->cmd = 0;
2549 cmd->src = NAND_FLASH_BUFFER;
2550 cmd->dst = curr_addr;
2551 cmd->len = 64;
2552 curr_addr += 64;
2553 cmd++;
2554 }
2555
Shashank Mittalc20b5a12009-11-18 19:35:30 -08002556 /*************************************************************/
2557 /* Restore the necessary registers to proper values */
2558 /*************************************************************/
2559
2560 /* Block on cmd ready and write CMD register */
2561 cmd->cmd = DST_CRCI_NAND_CMD;
2562 cmd->src = paddr(&data->sfcmd[8]);
2563 cmd->dst = NAND_SFLASHC_CMD;
2564 cmd->len = 4;
2565 cmd++;
2566
2567 /* Kick the execute command */
2568 cmd->cmd = 0;
2569 cmd->src = paddr(&data->sfexec);
2570 cmd->dst = NAND_SFLASHC_EXEC_CMD;
2571 cmd->len = 4;
2572 cmd++;
2573
2574 /* Block on data ready, and read the status register */
2575 cmd->cmd = SRC_CRCI_NAND_DATA | CMD_OCU | CMD_LC;
2576 cmd->src = NAND_SFLASHC_STATUS;
2577 cmd->dst = paddr(&data->sfstat[8]);
2578 cmd->len = 4;
2579 cmd++;
2580
2581
2582 ptr[0] = (paddr(cmdlist) >> 3) | CMD_PTR_LP;
2583
2584 dmov_exec_cmdptr(DMOV_NAND_CHAN, ptr);
2585
2586
2587 ecc_status = (data->data3 >> 16) &
2588 0x0000FFFF;
2589 interrupt_status = (data->data4 >> 0) &
2590 0x0000FFFF;
2591 controller_status = (data->data4 >> 16) &
2592 0x0000FFFF;
2593
2594#if VERBOSE
2595 dprintf(INFO, "\n%s: sflash status %x %x %x %x %x %x %x"
2596 "%x %x\n", __func__,
2597 data->sfstat[0],
2598 data->sfstat[1],
2599 data->sfstat[2],
2600 data->sfstat[3],
2601 data->sfstat[4],
2602 data->sfstat[5],
2603 data->sfstat[6],
2604 data->sfstat[7]);
2605
2606 dprintf(INFO, "%s: controller_status = %x\n", __func__,
2607 controller_status);
2608 dprintf(INFO, "%s: interrupt_status = %x\n", __func__,
2609 interrupt_status);
2610 dprintf(INFO, "%s: ecc_status = %x\n", __func__,
2611 ecc_status);
2612#endif
2613 /* Check for errors, protection violations etc */
2614 if ((controller_status != 0)
2615 || (data->sfstat[0] & 0x110)
2616 || (data->sfstat[1] & 0x110)
2617 || (data->sfstat[2] & 0x110)
2618 || ((data->sfstat[3] & 0x110) &&
2619 (addr))
2620 || ((data->sfstat[4] & 0x110) &&
2621 (addr))
2622 || ((data->sfstat[5] & 0x110) &&
2623 (addr))
2624 || ((data->sfstat[6] & 0x110) &&
2625 (addr))) {
2626 dprintf(INFO, "%s: ECC/MPU/OP error\n", __func__);
2627 return -1;
2628 }
2629
2630#if VERBOSE
2631 dprintf(INFO, "read page %d: status: %x %x %x %x\n",
2632 page, data[5], data[6], data[7], data[8]);
2633 for(n = 0; n < 4; n++) {
2634 ptr = (unsigned*)(addr + 512 * n);
2635 dprintf(INFO, "data%d: %x %x %x %x\n", n, ptr[0], ptr[1], ptr[2], ptr[3]);
2636 ptr = (unsigned*)(spareaddr + 16 * n);
2637 dprintf(INFO, "spare data%d %x %x %x %x\n", n, ptr[0], ptr[1], ptr[2], ptr[3]);
2638 }
2639#endif
2640
2641 return 0;
2642}
2643
2644
2645struct data_onenand_write {
2646 unsigned sfbcfg;
2647 unsigned sfcmd[9];
2648 unsigned sfexec;
2649 unsigned sfstat[9];
2650 unsigned addr0;
2651 unsigned addr1;
2652 unsigned addr2;
2653 unsigned addr3;
2654 unsigned addr4;
2655 unsigned addr5;
2656 unsigned addr6;
2657 unsigned data0;
2658 unsigned data1;
2659 unsigned data2;
2660 unsigned data3;
2661 unsigned data4;
2662 unsigned data5;
2663 unsigned data6;
2664 unsigned macro[5];
2665};
2666
2667static int _flash_onenand_write_page(dmov_s *cmdlist, unsigned *ptrlist,
2668 unsigned page, const void *_addr,
Shashank Mittald0c836d2009-11-20 10:31:18 -08002669 const void *_spareaddr, unsigned raw_mode)
Shashank Mittalc20b5a12009-11-18 19:35:30 -08002670{
2671 dmov_s *cmd = cmdlist;
2672 unsigned *ptr = ptrlist;
2673 struct data_onenand_write *data = (void*) (ptrlist + 4);
2674 unsigned addr = (unsigned) _addr;
2675 unsigned addr_curr = (unsigned) _addr;
2676 char * spareaddr = (char *) _spareaddr;
2677 unsigned i, j, k;
2678
Shashank Mittaldcc2e352009-11-19 19:11:16 -08002679 unsigned erasesize = (flash_pagesize<<6);
2680 unsigned writesize = flash_pagesize;
Shashank Mittalc20b5a12009-11-18 19:35:30 -08002681
Shashank Mittaldcc2e352009-11-19 19:11:16 -08002682 unsigned onenand_startaddr1 = (page * flash_pagesize) / erasesize;
2683 unsigned onenand_startaddr8 = (((unsigned)(page * flash_pagesize) &
Shashank Mittalc20b5a12009-11-18 19:35:30 -08002684 (erasesize-1)) / writesize) << 2;
2685 unsigned onenand_startaddr2 = DEVICE_BUFFERRAM_0 << 15;
2686 unsigned onenand_startbuffer = DATARAM0_0 << 8;
Shashank Mittald0c836d2009-11-20 10:31:18 -08002687 unsigned onenand_sysconfig1 = (raw_mode == 1) ? ONENAND_SYSCFG1_ECCDIS :\
2688 ONENAND_SYSCFG1_ECCENA;
Shashank Mittalc20b5a12009-11-18 19:35:30 -08002689
2690 unsigned controller_status;
2691 unsigned interrupt_status;
2692 unsigned ecc_status;
2693
2694 char flash_oob[64];
2695
2696 unsigned oobfree_offset[8] = {2, 14, 18, 30, 34, 46, 50, 62};
2697 unsigned oobfree_length[8] = {3, 2, 3, 2, 3, 2, 3, 2};
2698
2699 for (i = 0; i < 64; i++)
2700 flash_oob[i] = 0xFF;
2701
2702 data->sfbcfg = SFLASH_BCFG;
2703 data->sfcmd[0] = SFLASH_PREPCMD(256, 0, 0,
2704 NAND_SFCMD_CMDXS,
2705 NAND_SFCMD_ASYNC,
2706 NAND_SFCMD_DATWR);
2707 data->sfcmd[1] = SFLASH_PREPCMD(256, 0, 0,
2708 NAND_SFCMD_CMDXS,
2709 NAND_SFCMD_ASYNC,
2710 NAND_SFCMD_DATWR);
2711 data->sfcmd[2] = SFLASH_PREPCMD(256, 0, 0,
2712 NAND_SFCMD_CMDXS,
2713 NAND_SFCMD_ASYNC,
2714 NAND_SFCMD_DATWR);
2715 data->sfcmd[3] = SFLASH_PREPCMD(256, 0, 0,
2716 NAND_SFCMD_CMDXS,
2717 NAND_SFCMD_ASYNC,
2718 NAND_SFCMD_DATWR);
2719 data->sfcmd[4] = SFLASH_PREPCMD(32, 0, 0,
2720 NAND_SFCMD_CMDXS,
2721 NAND_SFCMD_ASYNC,
2722 NAND_SFCMD_DATWR);
2723 data->sfcmd[5] = SFLASH_PREPCMD(7, 0, 0,
2724 NAND_SFCMD_CMDXS,
2725 NAND_SFCMD_ASYNC,
2726 NAND_SFCMD_REGWR);
2727 data->sfcmd[6] = SFLASH_PREPCMD(0, 0, 32,
2728 NAND_SFCMD_CMDXS,
2729 NAND_SFCMD_ASYNC,
2730 NAND_SFCMD_INTHI);
2731 data->sfcmd[7] = SFLASH_PREPCMD(3, 7, 0,
2732 NAND_SFCMD_DATXS,
2733 NAND_SFCMD_ASYNC,
2734 NAND_SFCMD_REGRD);
2735 data->sfcmd[8] = SFLASH_PREPCMD(4, 10, 0,
2736 NAND_SFCMD_CMDXS,
2737 NAND_SFCMD_ASYNC,
2738 NAND_SFCMD_REGWR);
2739 data->sfexec = 1;
2740
2741 data->sfstat[0] = CLEAN_DATA_32;
2742 data->sfstat[1] = CLEAN_DATA_32;
2743 data->sfstat[2] = CLEAN_DATA_32;
2744 data->sfstat[3] = CLEAN_DATA_32;
2745 data->sfstat[4] = CLEAN_DATA_32;
2746 data->sfstat[5] = CLEAN_DATA_32;
2747 data->sfstat[6] = CLEAN_DATA_32;
2748 data->sfstat[7] = CLEAN_DATA_32;
2749 data->sfstat[8] = CLEAN_DATA_32;
2750 data->addr0 = (ONENAND_INTERRUPT_STATUS << 16) |
2751 (ONENAND_SYSTEM_CONFIG_1);
2752 data->addr1 = (ONENAND_START_ADDRESS_8 << 16) |
2753 (ONENAND_START_ADDRESS_1);
2754 data->addr2 = (ONENAND_START_BUFFER << 16) |
2755 (ONENAND_START_ADDRESS_2);
2756 data->addr3 = (ONENAND_ECC_STATUS << 16) |
2757 (ONENAND_COMMAND);
2758 data->addr4 = (ONENAND_CONTROLLER_STATUS << 16) |
2759 (ONENAND_INTERRUPT_STATUS);
2760 data->addr5 = (ONENAND_INTERRUPT_STATUS << 16) |
2761 (ONENAND_SYSTEM_CONFIG_1);
2762 data->addr6 = (ONENAND_START_ADDRESS_3 << 16) |
2763 (ONENAND_START_ADDRESS_1);
2764 data->data0 = (ONENAND_CLRINTR << 16) |
2765 (onenand_sysconfig1);
2766 data->data1 = (onenand_startaddr8 << 16) |
2767 (onenand_startaddr1);
2768 data->data2 = (onenand_startbuffer << 16) |
2769 (onenand_startaddr2);
2770 data->data3 = (CLEAN_DATA_16 << 16) |
2771 (ONENAND_CMDPROGSPARE);
2772 data->data3 = (CLEAN_DATA_16 << 16) |
2773 (ONENAND_CMDPROGSPARE);
2774 data->data4 = (CLEAN_DATA_16 << 16) |
2775 (CLEAN_DATA_16);
2776 data->data5 = (ONENAND_CLRINTR << 16) |
2777 (ONENAND_SYSCFG1_ECCENA);
2778 data->data6 = (ONENAND_STARTADDR3_RES << 16) |
2779 (ONENAND_STARTADDR1_RES);
2780 data->macro[0] = 0x0200;
2781 data->macro[1] = 0x0300;
2782 data->macro[2] = 0x0400;
2783 data->macro[3] = 0x0500;
2784 data->macro[4] = 0x8010;
2785
2786
2787 /*************************************************************/
2788 /* Write the data ram area in the onenand buffer ram */
2789 /*************************************************************/
2790
2791 /* Enable and configure the SFlash controller */
2792 cmd->cmd = 0 | CMD_OCB;
2793 cmd->src = paddr(&data->sfbcfg);
2794 cmd->dst = NAND_SFLASHC_BURST_CFG;
2795 cmd->len = 4;
2796 cmd++;
2797
2798 if (addr) {
2799 data->data3 = (CLEAN_DATA_16 << 16) |
2800 (ONENAND_CMDPROG);
2801
2802 for (i = 0; i < 4; i++) {
2803
2804 /* Block on cmd ready and write CMD register */
2805 cmd->cmd = DST_CRCI_NAND_CMD;
2806 cmd->src = paddr(&data->sfcmd[i]);
2807 cmd->dst = NAND_SFLASHC_CMD;
2808 cmd->len = 4;
2809 cmd++;
2810
2811 /* Trnsfr usr buf contents to nand ctlr buf */
2812 cmd->cmd = 0;
2813 cmd->src = paddr(addr_curr);
2814 cmd->dst = NAND_FLASH_BUFFER;
2815 cmd->len = 512;
Shashank Mittald0c836d2009-11-20 10:31:18 -08002816 if(!raw_mode)
2817 addr_curr += 512;
Shashank Mittalc20b5a12009-11-18 19:35:30 -08002818 cmd++;
2819
2820 /* Write the MACRO1 register */
2821 cmd->cmd = 0;
2822 cmd->src = paddr(&data->macro[i]);
2823 cmd->dst = NAND_MACRO1_REG;
2824 cmd->len = 4;
2825 cmd++;
2826
2827 /* Kick the execute command */
2828 cmd->cmd = 0;
2829 cmd->src = paddr(&data->sfexec);
2830 cmd->dst = NAND_SFLASHC_EXEC_CMD;
2831 cmd->len = 4;
2832 cmd++;
2833
2834 /* Block on data rdy, & read status register */
2835 cmd->cmd = SRC_CRCI_NAND_DATA;
2836 cmd->src = NAND_SFLASHC_STATUS;
2837 cmd->dst = paddr(&data->sfstat[i]);
2838 cmd->len = 4;
2839 cmd++;
2840
2841 }
2842 }
2843
2844 /* Block on cmd ready and write CMD register */
2845 cmd->cmd = DST_CRCI_NAND_CMD;
2846 cmd->src = paddr(&data->sfcmd[4]);
2847 cmd->dst = NAND_SFLASHC_CMD;
2848 cmd->len = 4;
2849 cmd++;
2850
2851 if (spareaddr)
2852 {
2853 // Auto mode
2854 for (i = 0, k = 0; i < 8; i++) {
2855 for (j = 0; j < oobfree_length[i]; j++) {
2856 flash_oob[j+oobfree_offset[i]] = spareaddr[k];
2857 k++;
2858 }
2859 }
2860
2861 cmd->cmd = 0;
2862 cmd->src = paddr(&flash_oob);
2863 cmd->dst = NAND_FLASH_BUFFER;
2864 cmd->len = 64;
2865 cmd++;
2866 }
2867
Shashank Mittald0c836d2009-11-20 10:31:18 -08002868 if (raw_mode){
2869 cmd->cmd = 0;
2870 cmd->src = paddr(addr_curr);
2871 cmd->dst = NAND_FLASH_BUFFER;
2872 cmd->len = 64;
2873 cmd++;
2874 }
2875
Shashank Mittalc20b5a12009-11-18 19:35:30 -08002876 /* Write the MACRO1 register */
2877 cmd->cmd = 0;
2878 cmd->src = paddr(&data->macro[4]);
2879 cmd->dst = NAND_MACRO1_REG;
2880 cmd->len = 4;
2881 cmd++;
2882
2883 /* Kick the execute command */
2884 cmd->cmd = 0;
2885 cmd->src = paddr(&data->sfexec);
2886 cmd->dst = NAND_SFLASHC_EXEC_CMD;
2887 cmd->len = 4;
2888 cmd++;
2889
2890 /* Block on data ready, and read the status register */
2891 cmd->cmd = SRC_CRCI_NAND_DATA;
2892 cmd->src = NAND_SFLASHC_STATUS;
2893 cmd->dst = paddr(&data->sfstat[4]);
2894 cmd->len = 4;
2895 cmd++;
2896
2897 /*************************************************************/
2898 /* Write necessary address registers in the onenand device */
2899 /*************************************************************/
2900
2901 /* Block on cmd ready and write CMD register */
2902 cmd->cmd = DST_CRCI_NAND_CMD;
2903 cmd->src = paddr(&data->sfcmd[5]);
2904 cmd->dst = NAND_SFLASHC_CMD;
2905 cmd->len = 4;
2906 cmd++;
2907
2908 /* Write the ADDR0 and ADDR1 registers */
2909 cmd->cmd = 0;
2910 cmd->src = paddr(&data->addr0);
2911 cmd->dst = NAND_ADDR0;
2912 cmd->len = 8;
2913 cmd++;
2914
2915 /* Write the ADDR2 ADDR3 ADDR4 ADDR5 registers */
2916 cmd->cmd = 0;
2917 cmd->src = paddr(&data->addr2);
2918 cmd->dst = NAND_ADDR2;
2919 cmd->len = 16;
2920 cmd++;
2921
2922 /* Write the ADDR6 registers */
2923 cmd->cmd = 0;
2924 cmd->src = paddr(&data->addr6);
2925 cmd->dst = NAND_ADDR6;
2926 cmd->len = 4;
2927 cmd++;
2928
2929 /* Write the GENP0, GENP1, GENP2, GENP3 registers */
2930 cmd->cmd = 0;
2931 cmd->src = paddr(&data->data0);
2932 cmd->dst = NAND_GENP_REG0;
2933 cmd->len = 16;
2934 cmd++;
2935
2936 /* Write the FLASH_DEV_CMD4,5,6 registers */
2937 cmd->cmd = 0;
2938 cmd->src = paddr(&data->data4);
2939 cmd->dst = NAND_DEV_CMD4;
2940 cmd->len = 12;
2941 cmd++;
2942
2943 /* Kick the execute command */
2944 cmd->cmd = 0;
2945 cmd->src = paddr(&data->sfexec);
2946 cmd->dst = NAND_SFLASHC_EXEC_CMD;
2947 cmd->len = 4;
2948 cmd++;
2949
2950 /* Block on data ready, and read the status register */
2951 cmd->cmd = SRC_CRCI_NAND_DATA;
2952 cmd->src = NAND_SFLASHC_STATUS;
2953 cmd->dst = paddr(&data->sfstat[5]);
2954 cmd->len = 4;
2955 cmd++;
2956
2957 /*************************************************************/
2958 /* Wait for the interrupt from the Onenand device controller */
2959 /*************************************************************/
2960
2961 /* Block on cmd ready and write CMD register */
2962 cmd->cmd = DST_CRCI_NAND_CMD;
2963 cmd->src = paddr(&data->sfcmd[6]);
2964 cmd->dst = NAND_SFLASHC_CMD;
2965 cmd->len = 4;
2966 cmd++;
2967
2968 /* Kick the execute command */
2969 cmd->cmd = 0;
2970 cmd->src = paddr(&data->sfexec);
2971 cmd->dst = NAND_SFLASHC_EXEC_CMD;
2972 cmd->len = 4;
2973 cmd++;
2974
2975 /* Block on data ready, and read the status register */
2976 cmd->cmd = SRC_CRCI_NAND_DATA;
2977 cmd->src = NAND_SFLASHC_STATUS;
2978 cmd->dst = paddr(&data->sfstat[6]);
2979 cmd->len = 4;
2980 cmd++;
2981
2982 /*************************************************************/
2983 /* Read necessary status registers from the onenand device */
2984 /*************************************************************/
2985
2986 /* Block on cmd ready and write CMD register */
2987 cmd->cmd = DST_CRCI_NAND_CMD;
2988 cmd->src = paddr(&data->sfcmd[7]);
2989 cmd->dst = NAND_SFLASHC_CMD;
2990 cmd->len = 4;
2991 cmd++;
2992
2993 /* Kick the execute command */
2994 cmd->cmd = 0;
2995 cmd->src = paddr(&data->sfexec);
2996 cmd->dst = NAND_SFLASHC_EXEC_CMD;
2997 cmd->len = 4;
2998 cmd++;
2999
3000 /* Block on data ready, and read the status register */
3001 cmd->cmd = SRC_CRCI_NAND_DATA;
3002 cmd->src = NAND_SFLASHC_STATUS;
3003 cmd->dst = paddr(&data->sfstat[7]);
3004 cmd->len = 4;
3005 cmd++;
3006
3007 /* Read the GENP3 register */
3008 cmd->cmd = 0;
3009 cmd->src = NAND_GENP_REG3;
3010 cmd->dst = paddr(&data->data3);
3011 cmd->len = 4;
3012 cmd++;
3013
3014 /* Read the DEVCMD4 register */
3015 cmd->cmd = 0;
3016 cmd->src = NAND_DEV_CMD4;
3017 cmd->dst = paddr(&data->data4);
3018 cmd->len = 4;
3019 cmd++;
3020
3021
3022 /*************************************************************/
3023 /* Restore the necessary registers to proper values */
3024 /*************************************************************/
3025
3026 /* Block on cmd ready and write CMD register */
3027 cmd->cmd = DST_CRCI_NAND_CMD;
3028 cmd->src = paddr(&data->sfcmd[8]);
3029 cmd->dst = NAND_SFLASHC_CMD;
3030 cmd->len = 4;
3031 cmd++;
3032
3033 /* Kick the execute command */
3034 cmd->cmd = 0;
3035 cmd->src = paddr(&data->sfexec);
3036 cmd->dst = NAND_SFLASHC_EXEC_CMD;
3037 cmd->len = 4;
3038 cmd++;
3039
3040 /* Block on data ready, and read the status register */
3041 cmd->cmd = SRC_CRCI_NAND_DATA | CMD_OCU | CMD_LC;
3042 cmd->src = NAND_SFLASHC_STATUS;
3043 cmd->dst = paddr(&data->sfstat[8]);
3044 cmd->len = 4;
3045 cmd++;
3046
3047
3048 ptr[0] = (paddr(cmdlist) >> 3) | CMD_PTR_LP;
3049
3050 dmov_exec_cmdptr(DMOV_NAND_CHAN, ptr);
3051
3052 ecc_status = (data->data3 >> 16) & 0x0000FFFF;
3053 interrupt_status = (data->data4 >> 0)&0x0000FFFF;
3054 controller_status = (data->data4 >> 16)&0x0000FFFF;
3055
3056#if VERBOSE
3057 dprintf(INFO, "\n%s: sflash status %x %x %x %x %x %x %x %x %x\n", __func__,
3058 data->sfstat[0],
3059 data->sfstat[1],
3060 data->sfstat[2],
3061 data->sfstat[3],
3062 data->sfstat[4],
3063 data->sfstat[5],
3064 data->sfstat[6],
3065 data->sfstat[7],
3066 data->sfstat[8]);
3067
3068 dprintf(INFO, "%s: controller_status = %x\n", __func__,
3069 controller_status);
3070 dprintf(INFO, "%s: interrupt_status = %x\n", __func__,
3071 interrupt_status);
3072 dprintf(INFO, "%s: ecc_status = %x\n", __func__,
3073 ecc_status);
3074#endif
3075 /* Check for errors, protection violations etc */
3076 if ((controller_status != 0)
3077 || (data->sfstat[5] & 0x110)
3078 || (data->sfstat[6] & 0x110)
3079 || (data->sfstat[7] & 0x110)
3080 || (data->sfstat[8] & 0x110)
3081 || ((data->sfstat[0] & 0x110) &&
3082 (addr))
3083 || ((data->sfstat[1] & 0x110) &&
3084 (addr))
3085 || ((data->sfstat[2] & 0x110) &&
3086 (addr))
3087 || ((data->sfstat[3] & 0x110) &&
3088 (addr))) {
3089 dprintf(CRITICAL, "%s: ECC/MPU/OP error\n", __func__);
3090 return -1;
3091 }
3092
3093
3094 return 0;
3095}
Shashank Mittald0c836d2009-11-20 10:31:18 -08003096
3097static int flash_onenand_mark_badblock(dmov_s *cmdlist, unsigned *ptrlist, unsigned page)
3098{
3099 memset(empty_buf,0,528);
3100 /* Going to first page of the block */
3101 if(page & 63)
3102 page = page - (page & 63);
3103 return _flash_onenand_write_page(cmdlist, ptrlist, page, empty_buf, 0, 1);
3104}
3105
3106static int flash_mark_badblock(dmov_s *cmdlist, unsigned *ptrlist, unsigned page)
3107{
3108 switch(flash_info.type) {
3109 case FLASH_8BIT_NAND_DEVICE:
3110 case FLASH_16BIT_NAND_DEVICE:
3111 return flash_nand_mark_badblock(cmdlist, ptrlist, page);
3112 case FLASH_ONENAND_DEVICE:
3113 return flash_onenand_mark_badblock(cmdlist, ptrlist, page);
3114 default:
3115 return -1;
3116 }
3117}
3118
3119
Shashank Mittalc20b5a12009-11-18 19:35:30 -08003120/* Wrapper functions */
3121static void flash_read_id(dmov_s *cmdlist, unsigned *ptrlist)
3122{
3123 int dev_found = 0;
3124 unsigned index;
3125
3126 // Try to read id
3127 flash_nand_read_id(cmdlist, ptrlist);
3128 // Check if we support the device
3129 for (index=1;
3130 index < (sizeof(supported_flash)/sizeof(struct flash_identification));
3131 index++)
3132 {
3133 if ((flash_info.id & supported_flash[index].mask) ==
3134 (supported_flash[index].flash_id &
3135 (supported_flash[index].mask))) {
3136 dev_found = 1;
3137 break;
3138 }
3139 }
3140
3141 if(!dev_found) {
3142 flash_onenand_read_id(cmdlist, ptrlist);
3143 for (index=1;
3144 index < (sizeof(supported_flash)/sizeof(struct flash_identification));
3145 index++)
3146 {
3147 if ((flash_info.id & supported_flash[index].mask) ==
3148 (supported_flash[index].flash_id &
3149 (supported_flash[index].mask))) {
3150 dev_found = 1;
3151 break;
3152 }
3153 }
3154 }
3155
3156
3157
3158 if(dev_found) {
3159 if (supported_flash[index].widebus)
3160 flash_info.type = FLASH_16BIT_NAND_DEVICE;
3161 else
3162 flash_info.type = FLASH_8BIT_NAND_DEVICE;
3163 if (supported_flash[index].onenand)
3164 flash_info.type = FLASH_ONENAND_DEVICE;
3165 flash_info.page_size = supported_flash[index].pagesize;
Shashank Mittaldcc2e352009-11-19 19:11:16 -08003166 flash_pagesize = flash_info.page_size;
Shashank Mittalc20b5a12009-11-18 19:35:30 -08003167 flash_info.block_size = supported_flash[index].blksize;
3168 flash_info.spare_size = supported_flash[index].oobsize;
3169 if (flash_info.block_size && flash_info.page_size)
3170 {
3171 flash_info.num_blocks = supported_flash[index].density;
Chandan Uddaraju40605112010-08-09 14:25:08 -07003172 flash_info.num_blocks /= (flash_info.block_size);
Shashank Mittalc20b5a12009-11-18 19:35:30 -08003173 }
3174 else
3175 {
3176 flash_info.num_blocks = 0;
3177 }
3178 ASSERT(flash_info.num_blocks);
3179 return;
3180 }
3181
3182 // Assume 8 bit nand device for backward compatability
3183 if (dev_found == 0) {
3184 dprintf(INFO, "Device not supported. Assuming 8 bit NAND device\n");
3185 flash_info.type = FLASH_8BIT_NAND_DEVICE;
3186 }
3187 dprintf(INFO, "nandid: 0x%x maker=0x%02x device=0x%02x page_size=%d\n",
3188 flash_info.id, flash_info.vendor, flash_info.device,
3189 flash_info.page_size);
3190 dprintf(INFO, " spare_size=%d block_size=%d num_blocks=%d\n",
3191 flash_info.spare_size, flash_info.block_size,
3192 flash_info.num_blocks);
3193}
3194
3195static int flash_erase_block(dmov_s *cmdlist, unsigned *ptrlist, unsigned page)
3196{
3197 switch(flash_info.type) {
3198 case FLASH_8BIT_NAND_DEVICE:
3199 case FLASH_16BIT_NAND_DEVICE:
3200 return flash_nand_erase_block(cmdlist, ptrlist, page);
3201 case FLASH_ONENAND_DEVICE:
3202 return flash_onenand_erase_block(cmdlist, ptrlist, page);
3203 default:
3204 return -1;
3205 }
3206}
3207
3208static int _flash_read_page(dmov_s *cmdlist, unsigned *ptrlist,
3209 unsigned page, void *_addr, void *_spareaddr)
3210{
3211 switch(flash_info.type) {
3212 case FLASH_8BIT_NAND_DEVICE:
3213 case FLASH_16BIT_NAND_DEVICE:
Chandan Uddaraju14e57eb2010-06-28 12:11:06 -07003214 if(interleaved_mode)
3215 return flash_nand_read_page_interleave(cmdlist, ptrlist, page, _addr, _spareaddr);
3216 else
Shashank Mittalc20b5a12009-11-18 19:35:30 -08003217 return _flash_nand_read_page(cmdlist, ptrlist, page, _addr, _spareaddr);
3218 case FLASH_ONENAND_DEVICE:
Shashank Mittalad3d05c2009-11-19 15:53:57 -08003219 return _flash_onenand_read_page(cmdlist, ptrlist, page, _addr, _spareaddr, 0);
Shashank Mittalc20b5a12009-11-18 19:35:30 -08003220 default:
3221 return -1;
3222 }
3223}
3224
Shashank Mittalad3d05c2009-11-19 15:53:57 -08003225static int _flash_block_isbad(dmov_s *cmdlist, unsigned *ptrlist, unsigned page)
3226{
3227 switch(flash_info.type) {
3228 case FLASH_8BIT_NAND_DEVICE:
3229 case FLASH_16BIT_NAND_DEVICE:
3230 return flash_nand_block_isbad(cmdlist, ptrlist, page);
3231 case FLASH_ONENAND_DEVICE:
3232 return flash_onenand_block_isbad(cmdlist, ptrlist, page);
3233 default:
3234 return -1;
3235 }
3236}
Shashank Mittalc20b5a12009-11-18 19:35:30 -08003237
3238static int _flash_write_page(dmov_s *cmdlist, unsigned *ptrlist,
3239 unsigned page, const void *_addr,
3240 const void *_spareaddr)
3241{
3242 switch(flash_info.type) {
3243 case FLASH_8BIT_NAND_DEVICE:
3244 case FLASH_16BIT_NAND_DEVICE:
Chandan Uddaraju14e57eb2010-06-28 12:11:06 -07003245 if(interleaved_mode)
3246 return flash_nand_write_page_interleave(cmdlist, ptrlist, page, _addr, _spareaddr, 0);
3247 else
Shashank Mittald0c836d2009-11-20 10:31:18 -08003248 return _flash_nand_write_page(cmdlist, ptrlist, page, _addr, _spareaddr, 0);
Shashank Mittalc20b5a12009-11-18 19:35:30 -08003249 case FLASH_ONENAND_DEVICE:
Shashank Mittald0c836d2009-11-20 10:31:18 -08003250 return _flash_onenand_write_page(cmdlist, ptrlist, page, _addr, _spareaddr, 0);
Shashank Mittalc20b5a12009-11-18 19:35:30 -08003251 default:
3252 return -1;
3253 }
3254}
3255
Dima Zavin03cf4312009-01-23 16:38:30 -08003256static unsigned *flash_ptrlist;
3257static dmov_s *flash_cmdlist;
Dima Zavin03cf4312009-01-23 16:38:30 -08003258
3259static struct ptable *flash_ptable = NULL;
3260
Dima Zavine5f64352009-03-02 16:04:20 -08003261void flash_init(void)
Dima Zavin03cf4312009-01-23 16:38:30 -08003262{
Dima Zavine5f64352009-03-02 16:04:20 -08003263 ASSERT(flash_ptable == NULL);
Dima Zavin03cf4312009-01-23 16:38:30 -08003264
3265 flash_ptrlist = memalign(32, 1024);
3266 flash_cmdlist = memalign(32, 1024);
Ajay Dudani232ce812009-12-02 00:14:11 -08003267 flash_data = memalign(32, 4096 + 128);
3268 flash_spare = memalign(32, 128);
Dima Zavin03cf4312009-01-23 16:38:30 -08003269
Dima Zavin03cf4312009-01-23 16:38:30 -08003270 flash_read_id(flash_cmdlist, flash_ptrlist);
Shashank Mittal83d16d02009-11-18 16:54:42 -08003271 if((FLASH_8BIT_NAND_DEVICE == flash_info.type)
3272 ||(FLASH_16BIT_NAND_DEVICE == flash_info.type)) {
Shashank Mittalc20b5a12009-11-18 19:35:30 -08003273 if(flash_nand_read_config(flash_cmdlist, flash_ptrlist)) {
Shashank Mittal83d16d02009-11-18 16:54:42 -08003274 dprintf(CRITICAL, "ERROR: could not read CFG0/CFG1 state\n");
3275 ASSERT(0);
3276 }
3277 }
Dima Zavin03cf4312009-01-23 16:38:30 -08003278}
3279
3280struct ptable *flash_get_ptable(void)
3281{
3282 return flash_ptable;
3283}
3284
Dima Zavine5f64352009-03-02 16:04:20 -08003285void flash_set_ptable(struct ptable *new_ptable)
3286{
3287 ASSERT(flash_ptable == NULL && new_ptable != NULL);
3288 flash_ptable = new_ptable;
3289}
3290
Dima Zavinca337f52009-03-02 16:41:44 -08003291struct flash_info *flash_get_info(void)
3292{
3293 return &flash_info;
3294}
3295
Dima Zavin03cf4312009-01-23 16:38:30 -08003296int flash_erase(struct ptentry *ptn)
3297{
3298 unsigned block = ptn->start;
3299 unsigned count = ptn->length;
3300
Shashank Mittal8e49dec2010-03-01 15:19:04 -08003301 set_nand_configuration(ptn->type);
Dima Zavin03cf4312009-01-23 16:38:30 -08003302 while(count-- > 0) {
3303 if(flash_erase_block(flash_cmdlist, flash_ptrlist, block * 64)) {
3304 dprintf(INFO, "cannot erase @ %d (bad block?)\n", block);
3305 }
3306 block++;
3307 }
3308 return 0;
3309}
3310
3311int flash_read_ext(struct ptentry *ptn, unsigned extra_per_page,
Shashank Mittalc20b5a12009-11-18 19:35:30 -08003312 unsigned offset, void *data, unsigned bytes)
Dima Zavin03cf4312009-01-23 16:38:30 -08003313{
Shashank Mittaldcc2e352009-11-19 19:11:16 -08003314 unsigned page = (ptn->start * 64) + (offset / flash_pagesize);
Dima Zavin03cf4312009-01-23 16:38:30 -08003315 unsigned lastpage = (ptn->start + ptn->length) * 64;
Shashank Mittaldcc2e352009-11-19 19:11:16 -08003316 unsigned count = (bytes + flash_pagesize - 1 + extra_per_page) / (flash_pagesize + extra_per_page);
Dima Zavin03cf4312009-01-23 16:38:30 -08003317 unsigned *spare = (unsigned*) flash_spare;
3318 unsigned errors = 0;
3319 unsigned char *image = data;
Shashank Mittalad3d05c2009-11-19 15:53:57 -08003320 unsigned current_block = (page - (page & 63)) >> 6;
3321 unsigned start_block = ptn->start;
3322 int result = 0;
3323 int isbad = 0;
Shashank Mittalfd1f04f2010-08-03 17:38:48 -07003324 int start_block_count = 0;
Dima Zavin03cf4312009-01-23 16:38:30 -08003325
Shashank Mittal8e49dec2010-03-01 15:19:04 -08003326 ASSERT(ptn->type == TYPE_APPS_PARTITION);
3327 set_nand_configuration(TYPE_APPS_PARTITION);
3328
Shashank Mittaldcc2e352009-11-19 19:11:16 -08003329 if(offset & (flash_pagesize - 1))
Dima Zavin03cf4312009-01-23 16:38:30 -08003330 return -1;
3331
Shashank Mittalfd1f04f2010-08-03 17:38:48 -07003332// Adjust page offset based on number of bad blocks from start to current page
3333 if (start_block < current_block)
3334 {
3335 start_block_count = (current_block - start_block);
3336 while (start_block_count && (start_block < (ptn->start + ptn->length))) {
3337 isbad = _flash_block_isbad(flash_cmdlist, flash_ptrlist, start_block*64);
3338 if (isbad)
3339 page += 64;
3340 else
3341 start_block_count--;
3342 start_block++;
3343 }
Shashank Mittalad3d05c2009-11-19 15:53:57 -08003344 }
3345
Shashank Mittalfd1f04f2010-08-03 17:38:48 -07003346 while((page < lastpage) && !start_block_count) {
Dima Zavin03cf4312009-01-23 16:38:30 -08003347 if(count == 0) {
3348 dprintf(INFO, "flash_read_image: success (%d errors)\n", errors);
3349 return 0;
3350 }
3351
Shashank Mittalad3d05c2009-11-19 15:53:57 -08003352 result = _flash_read_page(flash_cmdlist, flash_ptrlist, page, image, spare);
3353
3354 if (result == -1) {
3355 // bad page, go to next page
3356 page++;
Dima Zavin03cf4312009-01-23 16:38:30 -08003357 errors++;
3358 continue;
3359 }
Shashank Mittalad3d05c2009-11-19 15:53:57 -08003360 else if (result == -2) {
3361 // bad block, go to next block same offset
3362 page += 64;
3363 errors++;
3364 continue;
3365 }
3366
3367 page++;
Shashank Mittaldcc2e352009-11-19 19:11:16 -08003368 image += flash_pagesize;
Dima Zavin03cf4312009-01-23 16:38:30 -08003369 memcpy(image, spare, extra_per_page);
3370 image += extra_per_page;
3371 count -= 1;
3372 }
3373
3374 /* could not find enough valid pages before we hit the end */
3375 dprintf(INFO, "flash_read_image: failed (%d errors)\n", errors);
3376 return 0xffffffff;
3377}
3378
3379int flash_write(struct ptentry *ptn, unsigned extra_per_page, const void *data,
3380 unsigned bytes)
3381{
3382 unsigned page = ptn->start * 64;
3383 unsigned lastpage = (ptn->start + ptn->length) * 64;
3384 unsigned *spare = (unsigned*) flash_spare;
3385 const unsigned char *image = data;
Shashank Mittaldcc2e352009-11-19 19:11:16 -08003386 unsigned wsize = flash_pagesize + extra_per_page;
Dima Zavin03cf4312009-01-23 16:38:30 -08003387 unsigned n;
3388 int r;
3389
Shashank Mittal8e49dec2010-03-01 15:19:04 -08003390 if ((flash_info.type == FLASH_ONENAND_DEVICE) && (ptn->type == TYPE_MODEM_PARTITION))
3391 {
3392 dprintf(CRITICAL, "flash_write_image: feature not supported\n");
3393 return -1;
3394 }
3395
3396 set_nand_configuration(ptn->type);
Dima Zavin03cf4312009-01-23 16:38:30 -08003397 for(n = 0; n < 16; n++) spare[n] = 0xffffffff;
3398
3399 while(bytes > 0) {
3400 if(bytes < wsize) {
3401 dprintf(CRITICAL, "flash_write_image: image undersized (%d < %d)\n", bytes, wsize);
3402 return -1;
3403 }
3404 if(page >= lastpage) {
3405 dprintf(CRITICAL, "flash_write_image: out of space\n");
3406 return -1;
3407 }
3408
3409 if((page & 63) == 0) {
3410 if(flash_erase_block(flash_cmdlist, flash_ptrlist, page)) {
3411 dprintf(INFO, "flash_write_image: bad block @ %d\n", page >> 6);
3412 page += 64;
3413 continue;
3414 }
3415 }
3416
3417 if(extra_per_page) {
Shashank Mittald0c836d2009-11-20 10:31:18 -08003418 r = _flash_write_page(flash_cmdlist, flash_ptrlist, page, image, image + flash_pagesize);
Dima Zavin03cf4312009-01-23 16:38:30 -08003419 } else {
Shashank Mittald0c836d2009-11-20 10:31:18 -08003420 r = _flash_write_page(flash_cmdlist, flash_ptrlist, page, image, spare);
Dima Zavin03cf4312009-01-23 16:38:30 -08003421 }
3422 if(r) {
3423 dprintf(INFO, "flash_write_image: write failure @ page %d (src %d)\n", page, image - (const unsigned char *)data);
3424 image -= (page & 63) * wsize;
3425 bytes += (page & 63) * wsize;
3426 page &= ~63;
3427 if(flash_erase_block(flash_cmdlist, flash_ptrlist, page)) {
3428 dprintf(INFO, "flash_write_image: erase failure @ page %d\n", page);
3429 }
Shashank Mittal8e49dec2010-03-01 15:19:04 -08003430 if (ptn->type != TYPE_MODEM_PARTITION) {
3431 flash_mark_badblock(flash_cmdlist, flash_ptrlist, page);
3432 }
Dima Zavin03cf4312009-01-23 16:38:30 -08003433 dprintf(INFO, "flash_write_image: restart write @ page %d (src %d)\n", page, image - (const unsigned char *)data);
3434 page += 64;
3435 continue;
3436 }
Shashank Mittald0c836d2009-11-20 10:31:18 -08003437 page++;
Dima Zavin03cf4312009-01-23 16:38:30 -08003438 image += wsize;
3439 bytes -= wsize;
3440 }
3441
3442 /* erase any remaining pages in the partition */
3443 page = (page + 63) & (~63);
3444 while(page < lastpage){
3445 if(flash_erase_block(flash_cmdlist, flash_ptrlist, page)) {
3446 dprintf(INFO, "flash_write_image: bad block @ %d\n", page >> 6);
3447 }
3448 page += 64;
3449 }
3450
3451 dprintf(INFO, "flash_write_image: success\n");
3452 return 0;
3453}
3454
3455#if 0
3456static int flash_read_page(unsigned page, void *data, void *extra)
3457{
3458 return _flash_read_page(flash_cmdlist, flash_ptrlist,
3459 page, data, extra);
3460}
3461#endif
Shashank Mittaldcc2e352009-11-19 19:11:16 -08003462
3463unsigned flash_page_size(void)
3464{
3465 return flash_pagesize;
3466}
Chandan Uddaraju14e57eb2010-06-28 12:11:06 -07003467
3468void enable_interleave_mode(int status)
3469{
3470 interleaved_mode = status;
3471 if(status)
3472 {
3473 flash_pagesize *= 2;
3474 platform_config_interleaved_mode_gpios();
3475 }
3476 return;
3477}