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