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