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