blob: 6264220d32199740c8b62eabc86da14c7da3c88c [file] [log] [blame]
Dima Zavin03cf4312009-01-23 16:38:30 -08001/*
2 * Copyright (c) 2008, Google Inc.
3 * All rights reserved.
Shashank Mittal246f8d02011-01-21 17:12:27 -08004 * Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
Dima Zavin03cf4312009-01-23 16:38:30 -08005 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in
Shashank Mittalc20b5a12009-11-18 19:35:30 -080013 * the documentation and/or other materials provided with the
Dima Zavin03cf4312009-01-23 16:38:30 -080014 * distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
19 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
20 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
22 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
Shashank Mittalc20b5a12009-11-18 19:35:30 -080023 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
Dima Zavin03cf4312009-01-23 16:38:30 -080024 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
26 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#include <debug.h>
31#include <reg.h>
32#include <stdlib.h>
33#include <string.h>
34#include <dev/flash.h>
35#include <lib/ptable.h>
Ajay Dudani168f6cb2009-12-07 19:04:02 -080036#include <nand.h>
Dima Zavin03cf4312009-01-23 16:38:30 -080037
38#include "dmov.h"
Dima Zavin03cf4312009-01-23 16:38:30 -080039
40#define VERBOSE 0
Dima Zavin5582c7d2009-03-03 15:17:59 -080041#define VERIFY_WRITE 0
42
43static void *flash_spare;
44static void *flash_data;
Chandan Uddaraju14e57eb2010-06-28 12:11:06 -070045void platform_config_interleaved_mode_gpios(void);
Dima Zavin03cf4312009-01-23 16:38:30 -080046
47typedef struct dmov_ch dmov_ch;
Shashank Mittalc20b5a12009-11-18 19:35:30 -080048struct dmov_ch
Dima Zavin03cf4312009-01-23 16:38:30 -080049{
50 volatile unsigned cmd;
51 volatile unsigned result;
52 volatile unsigned status;
53 volatile unsigned config;
54};
55
56static void dmov_prep_ch(dmov_ch *ch, unsigned id)
57{
58 ch->cmd = DMOV_CMD_PTR(id);
59 ch->result = DMOV_RSLT(id);
60 ch->status = DMOV_STATUS(id);
61 ch->config = DMOV_CONFIG(id);
62}
63
64#define SRC_CRCI_NAND_CMD CMD_SRC_CRCI(DMOV_NAND_CRCI_CMD)
65#define DST_CRCI_NAND_CMD CMD_DST_CRCI(DMOV_NAND_CRCI_CMD)
66#define SRC_CRCI_NAND_DATA CMD_SRC_CRCI(DMOV_NAND_CRCI_DATA)
67#define DST_CRCI_NAND_DATA CMD_DST_CRCI(DMOV_NAND_CRCI_DATA)
68
Channagoud Kadabi404a7062011-03-21 19:27:50 +053069#define CFG0_RAW 0xA80420C0
70#define CFG1_RAW 0x5045D
71
72#define CFG0_RAW_BCHECC 0xA80428C0
Shashank Mittalad3d05c2009-11-19 15:53:57 -080073
Dima Zavin03cf4312009-01-23 16:38:30 -080074static unsigned CFG0, CFG1;
Shashank Mittal8e49dec2010-03-01 15:19:04 -080075static unsigned CFG0_M, CFG1_M;
76static unsigned CFG0_A, CFG1_A;
Channagoud Kadabi404a7062011-03-21 19:27:50 +053077static unsigned NAND_CFG0_RAW, NAND_CFG1_RAW;
78static unsigned ECC_BCH_CFG;
79
80static uint32_t enable_bch_ecc;
Dima Zavin03cf4312009-01-23 16:38:30 -080081
82#define CFG1_WIDE_FLASH (1U << 1)
83
84#define paddr(n) ((unsigned) (n))
85
86static int dmov_exec_cmdptr(unsigned id, unsigned *ptr)
87{
88 dmov_ch ch;
89 unsigned n;
90
91 dmov_prep_ch(&ch, id);
92
93 writel(DMOV_CMD_PTR_LIST | DMOV_CMD_ADDR(paddr(ptr)), ch.cmd);
94
95 while(!(readl(ch.status) & DMOV_STATUS_RSLT_VALID)) ;
96
97 n = readl(ch.status);
98 while(DMOV_STATUS_RSLT_COUNT(n)) {
99 n = readl(ch.result);
100 if(n != 0x80000002) {
101 dprintf(CRITICAL, "ERROR: result: %x\n", n);
102 dprintf(CRITICAL, "ERROR: flush: %x %x %x %x\n",
103 readl(DMOV_FLUSH0(DMOV_NAND_CHAN)),
104 readl(DMOV_FLUSH1(DMOV_NAND_CHAN)),
105 readl(DMOV_FLUSH2(DMOV_NAND_CHAN)),
106 readl(DMOV_FLUSH3(DMOV_NAND_CHAN)));
107 }
108 n = readl(ch.status);
109 }
110
111 return 0;
112}
113
Dima Zavinca337f52009-03-02 16:41:44 -0800114static struct flash_info flash_info;
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800115static unsigned flash_pagesize = 0;
Chandan Uddaraju14e57eb2010-06-28 12:11:06 -0700116static int interleaved_mode = 0;
Channagoud Kadabibeb17d52011-03-25 17:14:00 +0530117static unsigned num_pages_per_blk = 0;
118static unsigned num_pages_per_blk_mask = 0;
Dima Zavin03cf4312009-01-23 16:38:30 -0800119
Shashank Mittal83d16d02009-11-18 16:54:42 -0800120struct flash_identification {
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800121 unsigned flash_id;
122 unsigned mask;
123 unsigned density;
124 unsigned widebus;
125 unsigned pagesize;
126 unsigned blksize;
127 unsigned oobsize;
128 unsigned onenand;
Shashank Mittal83d16d02009-11-18 16:54:42 -0800129};
130
131static struct flash_identification supported_flash[] =
132{
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800133 /* Flash ID ID Mask Density(MB) Wid Pgsz Blksz oobsz onenand Manuf */
134 {0x00000000, 0xFFFFFFFF, 0, 0, 0, 0, 0, 0}, /*ONFI*/
135 {0x1500aaec, 0xFF00FFFF, (256<<20), 0, 2048, (2048<<6), 64, 0}, /*Sams*/
136 {0x5500baec, 0xFF00FFFF, (256<<20), 1, 2048, (2048<<6), 64, 0}, /*Sams*/
137 {0x1500aa98, 0xFFFFFFFF, (256<<20), 0, 2048, (2048<<6), 64, 0}, /*Tosh*/
138 {0x5500ba98, 0xFFFFFFFF, (256<<20), 1, 2048, (2048<<6), 64, 0}, /*Tosh*/
Ajay Dudani86e1b422009-12-04 20:49:50 -0800139 {0xd580b12c, 0xFFFFFFFF, (256<<20), 1, 2048, (2048<<6), 64, 0}, /*Micr*/
Chandan Uddaraju40605112010-08-09 14:25:08 -0700140 {0x5590bc2c, 0xFFFFFFFF, (512<<20), 1, 2048, (2048<<6), 64, 0}, /*Micr*/
Chandan Uddaraju0ec234c2009-11-24 22:34:50 -0800141 {0x1580aa2c, 0xFFFFFFFF, (256<<20), 0, 2048, (2048<<6), 64, 0}, /*Micr*/
Shashank Mittalab958e52010-12-03 17:57:22 -0800142 {0x1590aa2c, 0xFFFFFFFF, (256<<20), 0, 2048, (2048<<6), 64, 0}, /*Micr*/
Ajay Dudani513fb742010-05-24 20:39:26 -0700143 {0x1590ac2c, 0xFFFFFFFF, (512<<20), 0, 2048, (2048<<6), 64, 0}, /*Micr*/
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800144 {0x5580baad, 0xFFFFFFFF, (256<<20), 1, 2048, (2048<<6), 64, 0}, /*Hynx*/
145 {0x5510baad, 0xFFFFFFFF, (256<<20), 1, 2048, (2048<<6), 64, 0}, /*Hynx*/
146 {0x004000ec, 0xFFFFFFFF, (256<<20), 0, 2048, (2048<<6), 64, 1}, /*Sams*/
147 {0x005c00ec, 0xFFFFFFFF, (256<<20), 0, 2048, (2048<<6), 64, 1}, /*Sams*/
148 {0x005800ec, 0xFFFFFFFF, (256<<20), 0, 2048, (2048<<6), 64, 1}, /*Sams*/
Chandan Uddaraju40605112010-08-09 14:25:08 -0700149 {0x6600bcec, 0xFF00FFFF, (512<<20), 1, 4096, (4096<<6), 128, 0}, /*Sams*/
Shashank Mittal246f8d02011-01-21 17:12:27 -0800150 {0x5580ba2c, 0xFFFFFFFF, (256<<20), 1, 2048, (2048<<6), 64, 0}, /*Hynx*/
Shashank Mittalef325412011-04-01 13:48:26 -0700151 {0x6600b3ec, 0xFFFFFFFF, (512<<20), 1, 4096, (4096<<6), 128, 0}, /*Sams*/
Channagoud Kadabi404a7062011-03-21 19:27:50 +0530152 {0x2600482c, 0xFF00FFFF, (2048<<20), 0, 4096, (4096<<7), 224 , 0}, /*8bit bch ecc*/
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800153 /* Note: Width flag is 0 for 8 bit Flash and 1 for 16 bit flash */
154 /* Note: Onenand flag is 0 for NAND Flash and 1 for OneNAND flash */
155 /* Note: The First row will be filled at runtime during ONFI probe */
Shashank Mittal83d16d02009-11-18 16:54:42 -0800156};
Shashank Mittal8e49dec2010-03-01 15:19:04 -0800157static void set_nand_configuration(char type)
158{
159 if(type == TYPE_MODEM_PARTITION)
160 {
161 CFG0 = CFG0_M;
162 CFG1 = CFG1_M;
163 }
164 else
165 {
166 CFG0 = CFG0_A;
167 CFG1 = CFG1_A;
168 }
169}
Shashank Mittal83d16d02009-11-18 16:54:42 -0800170
171static void flash_nand_read_id(dmov_s *cmdlist, unsigned *ptrlist)
Dima Zavin03cf4312009-01-23 16:38:30 -0800172{
173 dmov_s *cmd = cmdlist;
174 unsigned *ptr = ptrlist;
175 unsigned *data = ptrlist + 4;
176
177 data[0] = 0 | 4;
178 data[1] = NAND_CMD_FETCH_ID;
179 data[2] = 1;
180 data[3] = 0;
181 data[4] = 0;
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800182 data[5] = 0;
183 data[6] = 0;
184 data[7] = 0xAAD40000; /* Default value for CFG0 for reading device id */
Dima Zavin03cf4312009-01-23 16:38:30 -0800185
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800186 /* Read NAND device id */
Dima Zavin03cf4312009-01-23 16:38:30 -0800187 cmd[0].cmd = 0 | CMD_OCB;
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800188 cmd[0].src = paddr(&data[7]);
189 cmd[0].dst = NAND_DEV0_CFG0;
Dima Zavin03cf4312009-01-23 16:38:30 -0800190 cmd[0].len = 4;
191
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800192 cmd[1].cmd = 0;
193 cmd[1].src = NAND_SFLASHC_BURST_CFG;
194 cmd[1].dst = paddr(&data[5]);
Dima Zavin03cf4312009-01-23 16:38:30 -0800195 cmd[1].len = 4;
196
197 cmd[2].cmd = 0;
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800198 cmd[2].src = paddr(&data[6]);
199 cmd[2].dst = NAND_SFLASHC_BURST_CFG;
Dima Zavin03cf4312009-01-23 16:38:30 -0800200 cmd[2].len = 4;
201
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800202 cmd[3].cmd = 0;
203 cmd[3].src = paddr(&data[0]);
204 cmd[3].dst = NAND_FLASH_CHIP_SELECT;
Dima Zavin03cf4312009-01-23 16:38:30 -0800205 cmd[3].len = 4;
206
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800207 cmd[4].cmd = DST_CRCI_NAND_CMD;
208 cmd[4].src = paddr(&data[1]);
209 cmd[4].dst = NAND_FLASH_CMD;
Dima Zavin03cf4312009-01-23 16:38:30 -0800210 cmd[4].len = 4;
211
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800212 cmd[5].cmd = 0;
213 cmd[5].src = paddr(&data[2]);
214 cmd[5].dst = NAND_EXEC_CMD;
215 cmd[5].len = 4;
216
217 cmd[6].cmd = SRC_CRCI_NAND_DATA;
218 cmd[6].src = NAND_FLASH_STATUS;
219 cmd[6].dst = paddr(&data[3]);
220 cmd[6].len = 4;
221
222 cmd[7].cmd = 0;
223 cmd[7].src = NAND_READ_ID;
224 cmd[7].dst = paddr(&data[4]);
225 cmd[7].len = 4;
226
227 cmd[8].cmd = CMD_OCU | CMD_LC;
228 cmd[8].src = paddr(&data[5]);
229 cmd[8].dst = NAND_SFLASHC_BURST_CFG;
230 cmd[8].len = 4;
231
Dima Zavin03cf4312009-01-23 16:38:30 -0800232 ptr[0] = (paddr(cmd) >> 3) | CMD_PTR_LP;
233
234 dmov_exec_cmdptr(DMOV_NAND_CHAN, ptr);
235
236#if VERBOSE
237 dprintf(INFO, "status: %x\n", data[3]);
238#endif
Dima Zavin03cf4312009-01-23 16:38:30 -0800239
Shashank Mittal83d16d02009-11-18 16:54:42 -0800240 flash_info.id = data[4];
Dima Zavinca337f52009-03-02 16:41:44 -0800241 flash_info.vendor = data[4] & 0xff;
242 flash_info.device = (data[4] >> 8) & 0xff;
Shashank Mittal83d16d02009-11-18 16:54:42 -0800243 return;
244}
Dima Zavinca337f52009-03-02 16:41:44 -0800245
Shashank Mittalad3d05c2009-11-19 15:53:57 -0800246static int flash_nand_block_isbad(dmov_s *cmdlist, unsigned *ptrlist,
247 unsigned page)
248{
249 dmov_s *cmd = cmdlist;
250 unsigned *ptr = ptrlist;
251 unsigned *data = ptrlist + 4;
252 char buf[4];
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800253 unsigned cwperpage;
254
255 cwperpage = (flash_pagesize >> 9);
Shashank Mittalad3d05c2009-11-19 15:53:57 -0800256
257 /* Check first page of this block */
Channagoud Kadabibeb17d52011-03-25 17:14:00 +0530258 if(page & num_pages_per_blk_mask)
259 page = page - (page & num_pages_per_blk_mask);
Shashank Mittalad3d05c2009-11-19 15:53:57 -0800260
261 /* Check bad block marker */
262 data[0] = NAND_CMD_PAGE_READ; /* command */
263
264 /* addr0 */
265 if (CFG1 & CFG1_WIDE_FLASH)
Channagoud Kadabi404a7062011-03-21 19:27:50 +0530266 data[1] = enable_bch_ecc ?
267 ((page << 16) | ((532*(cwperpage-1)) >> 1)):
268 ((page << 16) | ((528*(cwperpage-1)) >> 1));
269
Shashank Mittalad3d05c2009-11-19 15:53:57 -0800270 else
Channagoud Kadabi404a7062011-03-21 19:27:50 +0530271 data[1] = enable_bch_ecc ?
272 ((page << 16) | (532*(cwperpage-1))):
273 ((page << 16) | (528*(cwperpage-1)));
Shashank Mittalad3d05c2009-11-19 15:53:57 -0800274
275 data[2] = (page >> 16) & 0xff; /* addr1 */
276 data[3] = 0 | 4; /* chipsel */
277 data[4] = NAND_CFG0_RAW & ~(7U << 6); /* cfg0 */
278 data[5] = NAND_CFG1_RAW | (CFG1 & CFG1_WIDE_FLASH); /* cfg1 */
Channagoud Kadabi404a7062011-03-21 19:27:50 +0530279 if (enable_bch_ecc) {
280 data[6] = ECC_BCH_CFG; /* ECC CFG */
281 }
282 data[7] = 1;
283 data[8] = CLEAN_DATA_32; /* flash status */
284 data[9] = CLEAN_DATA_32; /* buf status */
Shashank Mittalad3d05c2009-11-19 15:53:57 -0800285
286 cmd[0].cmd = DST_CRCI_NAND_CMD | CMD_OCB;
287 cmd[0].src = paddr(&data[0]);
288 cmd[0].dst = NAND_FLASH_CMD;
289 cmd[0].len = 16;
290
291 cmd[1].cmd = 0;
292 cmd[1].src = paddr(&data[4]);
293 cmd[1].dst = NAND_DEV0_CFG0;
Channagoud Kadabi404a7062011-03-21 19:27:50 +0530294 if (enable_bch_ecc) {
295 cmd[1].len = 12;
296 } else {
297 cmd[1].len = 8;
298 }
Shashank Mittalad3d05c2009-11-19 15:53:57 -0800299
300 cmd[2].cmd = 0;
Channagoud Kadabi404a7062011-03-21 19:27:50 +0530301 cmd[2].src = paddr(&data[7]);
Shashank Mittalad3d05c2009-11-19 15:53:57 -0800302 cmd[2].dst = NAND_EXEC_CMD;
303 cmd[2].len = 4;
304
305 cmd[3].cmd = SRC_CRCI_NAND_DATA;
306 cmd[3].src = NAND_FLASH_STATUS;
Channagoud Kadabi404a7062011-03-21 19:27:50 +0530307 cmd[3].dst = paddr(&data[8]);
Shashank Mittalad3d05c2009-11-19 15:53:57 -0800308 cmd[3].len = 8;
309
310 cmd[4].cmd = CMD_OCU | CMD_LC;
Channagoud Kadabi404a7062011-03-21 19:27:50 +0530311 cmd[4].src = NAND_FLASH_BUFFER + (flash_pagesize - (enable_bch_ecc ?
312 (532*(cwperpage-1)):
313 (528*(cwperpage-1))));
Shashank Mittalad3d05c2009-11-19 15:53:57 -0800314 cmd[4].dst = paddr(&buf);
315 cmd[4].len = 4;
316
317 ptr[0] = (paddr(cmd) >> 3) | CMD_PTR_LP;
318
319 dmov_exec_cmdptr(DMOV_NAND_CHAN, ptr);
320
321#if VERBOSE
Channagoud Kadabi404a7062011-03-21 19:27:50 +0530322 dprintf(INFO, "status: %x\n", data[8]);
Shashank Mittalad3d05c2009-11-19 15:53:57 -0800323#endif
324
325 /* we fail if there was an operation error, a mpu error, or the
326 ** erase success bit was not set.
327 */
Channagoud Kadabi404a7062011-03-21 19:27:50 +0530328 if(data[8] & 0x110) return -1;
Shashank Mittalad3d05c2009-11-19 15:53:57 -0800329
330 /* Check for bad block marker byte */
331 if (CFG1 & CFG1_WIDE_FLASH) {
332 if (buf[0] != 0xFF || buf[1] != 0xFF)
333 return 1;
334 } else {
335 if (buf[0] != 0xFF)
336 return 1;
337 }
338
339 return 0;
340}
341
Murali Nalajalaa8c94c62010-03-05 20:24:30 +0530342static int flash_nand_block_isbad_interleave(dmov_s *cmdlist, unsigned *ptrlist,
343 unsigned page)
344{
345 dmov_s *cmd = cmdlist;
346 unsigned *ptr = ptrlist;
347 unsigned *data = ptrlist + 4;
348 char buf01[4];
349 char buf10[4];
350 unsigned cwperpage;
351
352 cwperpage = ((flash_pagesize >> 1)>> 9);
353
354 /* Check first page of this block */
355 if(page & 63)
356 page = page - (page & 63);
357
358 /* Check bad block marker */
359 data[0] = NAND_CMD_PAGE_READ; /* command */
360
361 /* addr0 */
362 if (CFG1 & CFG1_WIDE_FLASH)
363 data[1] = (page << 16) | ((528*(cwperpage-1)) >> 1);
364 else
365 data[1] = (page << 16) | (528*(cwperpage-1));
366
367 data[2] = (page >> 16) & 0xff; /* addr1 */
368 data[3] = 0 | 4; /* chipsel CS0 */
369 data[4] = 0 | 5; /* chipsel CS1 */
370 data[5] = NAND_CFG0_RAW & ~(7U << 6); /* cfg0 */
371 data[6] = NAND_CFG1_RAW | (CFG1 & CFG1_WIDE_FLASH); /* cfg1 */
372 data[7] = 1;
373 data[8] = CLEAN_DATA_32; /* NC01 flash status */
374 data[9] = CLEAN_DATA_32; /* NC01 buf01 status */
375 data[10] = CLEAN_DATA_32; /* NC10 flash status */
376 data[11] = CLEAN_DATA_32; /* NC10 buf10 status */
377 data[12] = 0x00000A3C; /* adm_mux_data_ack_req_nc01 */
378 data[13] = 0x0000053C; /* adm_mux_cmd_ack_req_nc01 */
379 data[14] = 0x00000F28; /* adm_mux_data_ack_req_nc10 */
380 data[15] = 0x00000F14; /* adm_mux_cmd_ack_req_nc10 */
381 data[16] = 0x00000FC0; /* adm_default_mux */
382 data[17] = 0x00000805; /* enable CS1 */
383 data[18] = 0x00000801; /* disable CS1 */
384
385 /* enable CS1 */
386 cmd[0].cmd = 0;
387 cmd[0].src = paddr(data[17]);
388 cmd[0].dst = EBI2_CHIP_SELECT_CFG0;
389 cmd[0].len = 4;
390
391 /* Reading last code word from NC01 */
392 /* 0xF14 */
393 cmd[1].cmd = 0;
394 cmd[1].src = paddr(data[15]);
395 cmd[1].dst = EBI2_NAND_ADM_MUX;
396 cmd[1].len = 4;
397
398 cmd[2].cmd = DST_CRCI_NAND_CMD;
399 cmd[2].src = paddr(&data[0]);
400 cmd[2].dst = NC01(NAND_FLASH_CMD);
401 cmd[2].len = 16;
402
403 cmd[3].cmd = 0;
404 cmd[3].src = paddr(&data[5]);
405 cmd[3].dst = NC01(NAND_DEV0_CFG0);
406 cmd[3].len = 8;
407
408 cmd[4].cmd = 0;
409 cmd[4].src = paddr(&data[7]);
410 cmd[4].dst = NC01(NAND_EXEC_CMD);
411 cmd[4].len = 4;
412
413 /* 0xF28 */
414 cmd[5].cmd = 0;
415 cmd[5].src = paddr(data[14]);
416 cmd[5].dst = EBI2_NAND_ADM_MUX;
417 cmd[5].len = 4;
418
419 cmd[6].cmd = SRC_CRCI_NAND_DATA;
420 cmd[6].src = NC01(NAND_FLASH_STATUS);
421 cmd[6].dst = paddr(&data[8]);
422 cmd[6].len = 8;
423
424 cmd[7].cmd = 0;
425 cmd[7].src = NC01(NAND_FLASH_BUFFER) + (flash_pagesize - (528*(cwperpage-1)));
426 cmd[7].dst = paddr(&buf01);
427 cmd[7].len = 4;
428
429 /* Reading last code word from NC10 */
430 /* 0x53C */
431 cmd[8].cmd = 0;
432 cmd[8].src = paddr(data[13]);
433 cmd[8].dst = EBI2_NAND_ADM_MUX;
434 cmd[8].len = 4;
435
436 cmd[9].cmd = DST_CRCI_NAND_CMD;
437 cmd[9].src = paddr(&data[0]);
438 cmd[9].dst = NC10(NAND_FLASH_CMD);
439 cmd[9].len = 12;
440
441 cmd[10].cmd = 0;
442 cmd[10].src = paddr(&data[4]);
443 cmd[10].dst = NC10(NAND_FLASH_CHIP_SELECT);
444 cmd[10].len = 4;
445
446 cmd[11].cmd = 0;
447 cmd[11].src = paddr(&data[5]);
448 cmd[11].dst = NC10(NAND_DEV1_CFG0);
449 cmd[11].len = 8;
450
451 cmd[12].cmd = 0;
452 cmd[12].src = paddr(&data[7]);
453 cmd[12].dst = NC10(NAND_EXEC_CMD);
454 cmd[12].len = 4;
455
456 /* 0xA3C */
457 cmd[13].cmd = 0;
458 cmd[13].src = paddr(data[12]);
459 cmd[13].dst = EBI2_NAND_ADM_MUX;
460 cmd[13].len = 4;
461
462 cmd[14].cmd = SRC_CRCI_NAND_DATA;
463 cmd[14].src = NC10(NAND_FLASH_STATUS);
464 cmd[14].dst = paddr(&data[10]);
465 cmd[14].len = 8;
466
467 cmd[15].cmd = 0;
468 cmd[15].src = NC10(NAND_FLASH_BUFFER) + (flash_pagesize - (528*(cwperpage-1)));
469 cmd[15].dst = paddr(&buf10);
470 cmd[15].len = 4;
471
472 cmd[16].cmd = 0;
473 cmd[16].src = paddr(&data[16]);
474 cmd[16].dst = EBI2_NAND_ADM_MUX;
475 cmd[16].len = 4;
476
477 /* setting default value */
478 cmd[17].cmd = CMD_OCU | CMD_LC;
479 cmd[17].src = paddr(&data[18]);
480 cmd[17].dst = EBI2_CHIP_SELECT_CFG0;
481 cmd[17].len = 4;
482
483 ptr[0] = (paddr(cmd) >> 3) | CMD_PTR_LP;
484
485 dmov_exec_cmdptr(DMOV_NAND_CHAN, ptr);
486
487#if VERBOSE
488 dprintf(INFO, "NC01 status: %x\n", data[8]);
489 dprintf(INFO, "NC10 status: %x\n", data[10]);
490#endif
491
492 /* we fail if there was an operation error, a mpu error, or the
493 ** erase success bit was not set.
494 */
495 if((data[8] & 0x110) || (data[10] & 0x110)) return -1;
496
497 /* Check for bad block marker byte */
498 if (CFG1 & CFG1_WIDE_FLASH) {
499 if ((buf01[0] != 0xFF || buf01[1] != 0xFF) ||
500 (buf10[0] != 0xFF || buf10[1] != 0xFF))
501 return 1;
502 } else {
503 if (buf01[0] != 0xFF || buf10[0] != 0xFF)
504 return 1;
505 }
506
507 return 0;
508}
509
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800510static int flash_nand_erase_block(dmov_s *cmdlist, unsigned *ptrlist,
511 unsigned page)
Dima Zavin03cf4312009-01-23 16:38:30 -0800512{
513 dmov_s *cmd = cmdlist;
514 unsigned *ptr = ptrlist;
515 unsigned *data = ptrlist + 4;
Shashank Mittalad3d05c2009-11-19 15:53:57 -0800516 int isbad = 0;
Dima Zavin03cf4312009-01-23 16:38:30 -0800517
518 /* only allow erasing on block boundaries */
Channagoud Kadabibeb17d52011-03-25 17:14:00 +0530519 if(page & num_pages_per_blk_mask) return -1;
Dima Zavin03cf4312009-01-23 16:38:30 -0800520
Shashank Mittalad3d05c2009-11-19 15:53:57 -0800521 /* Check for bad block and erase only if block is not marked bad */
522 isbad = flash_nand_block_isbad(cmdlist, ptrlist, page);
523
524 if (isbad) {
Channagoud Kadabibeb17d52011-03-25 17:14:00 +0530525 dprintf(INFO, "skipping @ %d (bad block)\n", page / num_pages_per_blk);
Shashank Mittalad3d05c2009-11-19 15:53:57 -0800526 return -1;
527 }
528
529 /* Erase block */
Dima Zavin03cf4312009-01-23 16:38:30 -0800530 data[0] = NAND_CMD_BLOCK_ERASE;
531 data[1] = page;
532 data[2] = 0;
533 data[3] = 0 | 4;
534 data[4] = 1;
535 data[5] = 0xeeeeeeee;
536 data[6] = CFG0 & (~(7 << 6)); /* CW_PER_PAGE = 0 */
537 data[7] = CFG1;
Channagoud Kadabi404a7062011-03-21 19:27:50 +0530538 data[8] = ECC_BCH_CFG;
539 data[9] = 0x00000020;
540 data[10] = 0x000000C0;
Dima Zavin03cf4312009-01-23 16:38:30 -0800541
542 cmd[0].cmd = DST_CRCI_NAND_CMD | CMD_OCB;
543 cmd[0].src = paddr(&data[0]);
544 cmd[0].dst = NAND_FLASH_CMD;
545 cmd[0].len = 16;
546
547 cmd[1].cmd = 0;
548 cmd[1].src = paddr(&data[6]);
549 cmd[1].dst = NAND_DEV0_CFG0;
Channagoud Kadabi404a7062011-03-21 19:27:50 +0530550 if (enable_bch_ecc) {
551 cmd[1].len = 12;
552 } else {
553 cmd[1].len = 8;
554 }
Dima Zavin03cf4312009-01-23 16:38:30 -0800555
556 cmd[2].cmd = 0;
557 cmd[2].src = paddr(&data[4]);
558 cmd[2].dst = NAND_EXEC_CMD;
559 cmd[2].len = 4;
560
Murali Palnatic54d13a2010-01-15 19:50:19 +0530561 cmd[3].cmd = SRC_CRCI_NAND_DATA;
Dima Zavin03cf4312009-01-23 16:38:30 -0800562 cmd[3].src = NAND_FLASH_STATUS;
563 cmd[3].dst = paddr(&data[5]);
564 cmd[3].len = 4;
565
Murali Palnatic54d13a2010-01-15 19:50:19 +0530566 cmd[4].cmd = 0;
Channagoud Kadabi404a7062011-03-21 19:27:50 +0530567 cmd[4].src = paddr(&data[9]);
Murali Palnatic54d13a2010-01-15 19:50:19 +0530568 cmd[4].dst = NAND_FLASH_STATUS;
569 cmd[4].len = 4;
570
571 cmd[5].cmd = CMD_OCU | CMD_LC;
Channagoud Kadabi404a7062011-03-21 19:27:50 +0530572 cmd[5].src = paddr(&data[10]);
Murali Palnatic54d13a2010-01-15 19:50:19 +0530573 cmd[5].dst = NAND_READ_STATUS;
574 cmd[5].len = 4;
575
Dima Zavin03cf4312009-01-23 16:38:30 -0800576 ptr[0] = (paddr(cmd) >> 3) | CMD_PTR_LP;
577
578 dmov_exec_cmdptr(DMOV_NAND_CHAN, ptr);
579
580#if VERBOSE
581 dprintf(INFO, "status: %x\n", data[5]);
582#endif
583
584 /* we fail if there was an operation error, a mpu error, or the
585 ** erase success bit was not set.
586 */
587 if(data[5] & 0x110) return -1;
588 if(!(data[5] & 0x80)) return -1;
589
590 return 0;
591}
592
Murali Nalajalaa8c94c62010-03-05 20:24:30 +0530593static int flash_nand_erase_block_interleave(dmov_s *cmdlist, unsigned *ptrlist,
594 unsigned page)
595{
596 dmov_s *cmd = cmdlist;
597 unsigned *ptr = ptrlist;
598 unsigned *data = ptrlist + 4;
599 int isbad = 0;
600
601 /* only allow erasing on block boundaries */
602 if(page & 63) return -1;
603
604 /* Check for bad block and erase only if block is not marked bad */
605 isbad = flash_nand_block_isbad(cmdlist, ptrlist, page);
606
607 if (isbad) {
608 dprintf(INFO, "skipping @ %d (bad block)\n", page >> 6);
609 return -1;
610 }
611
612 /* Erase block */
613 data[0] = NAND_CMD_BLOCK_ERASE;
614 data[1] = page;
615 data[2] = 0;
616 data[3] = 0 | 4; /* chipselect CS0 */
617 data[4] = 0 | 5; /* chipselect CS1 */
618 data[5] = 1;
619 data[6] = 0xeeeeeeee;
620 data[7] = 0xeeeeeeee;
621 data[8] = CFG0 & (~(7 << 6)); /* CW_PER_PAGE = 0 */
622 data[9] = CFG1;
623 data[10] = 0x00000A3C; /* adm_mux_data_ack_req_nc01 */
624 data[11] = 0x0000053C; /* adm_mux_cmd_ack_req_nc01 */
625 data[12] = 0x00000F28; /* adm_mux_data_ack_req_nc10 */
626 data[13] = 0x00000F14; /* adm_mux_cmd_ack_req_nc10 */
627 data[14] = 0x00000FC0; /* adm_default_mux */
628 data[15] = 0x00000805; /* enable CS1 */
629 data[16] = 0x00000801; /* disable CS1 */
630
631 /* enable CS1 */
632 cmd[0].cmd = 0 | CMD_OCB;
633 cmd[0].src = paddr(data[15]);
634 cmd[0].dst = EBI2_CHIP_SELECT_CFG0;
635 cmd[0].len = 4;
636
637 /* Reading last code word from NC01 */
638 /* 0xF14 */
639 cmd[1].cmd = 0;
640 cmd[1].src = paddr(data[13]);
641 cmd[1].dst = EBI2_NAND_ADM_MUX;
642 cmd[1].len = 4;
643
644 cmd[2].cmd = DST_CRCI_NAND_CMD;
645 cmd[2].src = paddr(&data[0]);
646 cmd[2].dst = NC01(NAND_FLASH_CMD);
647 cmd[2].len = 16;
648
649 cmd[3].cmd = 0;
650 cmd[3].src = paddr(&data[8]);
651 cmd[3].dst = NC01(NAND_DEV0_CFG0);
652 cmd[3].len = 8;
653
654 cmd[4].cmd = 0;
655 cmd[4].src = paddr(&data[5]);
656 cmd[4].dst = NC01(NAND_EXEC_CMD);
657 cmd[4].len = 4;
658
659 /* 0xF28 */
660 cmd[5].cmd = 0;
661 cmd[5].src = paddr(data[12]);
662 cmd[5].dst = EBI2_NAND_ADM_MUX;
663 cmd[5].len = 4;
664
665 cmd[6].cmd = SRC_CRCI_NAND_DATA;
666 cmd[6].src = NC01(NAND_FLASH_STATUS);
667 cmd[6].dst = paddr(&data[6]);
668 cmd[6].len = 4;
669
670 /* Reading last code word from NC10 */
671 /* 0x53C */
672 cmd[7].cmd = 0;
673 cmd[7].src = paddr(data[11]);
674 cmd[7].dst = EBI2_NAND_ADM_MUX;
675 cmd[7].len = 4;
676
677 cmd[8].cmd = DST_CRCI_NAND_CMD;
678 cmd[8].src = paddr(&data[0]);
679 cmd[8].dst = NC10(NAND_FLASH_CMD);
680 cmd[8].len = 12;
681
682 cmd[9].cmd = 0;
683 cmd[9].src = paddr(&data[4]);
684 cmd[9].dst = NC10(NAND_FLASH_CHIP_SELECT);
685 cmd[9].len = 4;
686
687 cmd[10].cmd = 0;
688 cmd[10].src = paddr(&data[8]);
689 cmd[10].dst = NC10(NAND_DEV1_CFG0);
690 cmd[10].len = 8;
691
692 cmd[11].cmd = 0;
693 cmd[11].src = paddr(&data[5]);
694 cmd[11].dst = NC10(NAND_EXEC_CMD);
695 cmd[11].len = 4;
696
697 /* 0xA3C */
698 cmd[12].cmd = 0;
699 cmd[12].src = paddr(data[10]);
700 cmd[12].dst = EBI2_NAND_ADM_MUX;
701 cmd[12].len = 4;
702
703 cmd[13].cmd = SRC_CRCI_NAND_DATA;
704 cmd[13].src = NC10(NAND_FLASH_STATUS);
705 cmd[13].dst = paddr(&data[7]);
706 cmd[13].len = 4;
707
708 /* adm default mux state */
709 /* 0xFCO */
710 cmd[14].cmd = 0;
711 cmd[14].src = paddr(data[14]);
712 cmd[14].dst = EBI2_NAND_ADM_MUX;
713 cmd[14].len = 4;
714
715 /* disable CS1 */
716 cmd[15].cmd = CMD_OCU | CMD_LC;
717 cmd[15].src = paddr(data[16]);
718 cmd[15].dst = EBI2_CHIP_SELECT_CFG0;
719 cmd[15].len = 4;
720
721 ptr[0] = (paddr(cmd) >> 3) | CMD_PTR_LP;
722
723 dmov_exec_cmdptr(DMOV_NAND_CHAN, ptr);
724
725#if VERBOSE
726 dprintf(INFO, "NC01 status: %x\n", data[6]);
727 dprintf(INFO, "NC10 status: %x\n", data[7]);
728#endif
729
730 /* we fail if there was an operation error, a mpu error, or the
731 ** erase success bit was not set.
732 */
733 if(data[6] & 0x110 || data[7] & 0x110) return -1;
734 if(!(data[6] & 0x80) || !(data[7] & 0x80)) return -1;
735
736 return 0;
737}
738
Dima Zavin03cf4312009-01-23 16:38:30 -0800739struct data_flash_io {
740 unsigned cmd;
741 unsigned addr0;
742 unsigned addr1;
743 unsigned chipsel;
744 unsigned cfg0;
745 unsigned cfg1;
Channagoud Kadabi404a7062011-03-21 19:27:50 +0530746 unsigned ecc_bch_cfg;
Dima Zavin03cf4312009-01-23 16:38:30 -0800747 unsigned exec;
748 unsigned ecc_cfg;
749 unsigned ecc_cfg_save;
Murali Palnatic54d13a2010-01-15 19:50:19 +0530750 unsigned clrfstatus;
751 unsigned clrrstatus;
Dima Zavin03cf4312009-01-23 16:38:30 -0800752 struct {
753 unsigned flash_status;
754 unsigned buffer_status;
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800755 } result[8];
Dima Zavin03cf4312009-01-23 16:38:30 -0800756};
757
Murali Nalajalaa8c94c62010-03-05 20:24:30 +0530758struct interleave_data_flash_io {
759 uint32_t cmd;
760 uint32_t addr0;
761 uint32_t addr1;
762 uint32_t chipsel_cs0;
763 uint32_t chipsel_cs1;
764 uint32_t cfg0;
765 uint32_t cfg1;
766 uint32_t exec;
767 uint32_t ecc_cfg;
768 uint32_t ecc_cfg_save;
769 uint32_t ebi2_chip_select_cfg0;
770 uint32_t adm_mux_data_ack_req_nc01;
771 uint32_t adm_mux_cmd_ack_req_nc01;
772 uint32_t adm_mux_data_ack_req_nc10;
773 uint32_t adm_mux_cmd_ack_req_nc10;
774 uint32_t adm_default_mux;
775 uint32_t default_ebi2_chip_select_cfg0;
776 struct {
777 uint32_t flash_status;
778 } result[16];
779};
780
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800781static int _flash_nand_read_page(dmov_s *cmdlist, unsigned *ptrlist,
782 unsigned page, void *_addr, void *_spareaddr)
Dima Zavin03cf4312009-01-23 16:38:30 -0800783{
784 dmov_s *cmd = cmdlist;
785 unsigned *ptr = ptrlist;
786 struct data_flash_io *data = (void*) (ptrlist + 4);
787 unsigned addr = (unsigned) _addr;
788 unsigned spareaddr = (unsigned) _spareaddr;
789 unsigned n;
Shashank Mittalad3d05c2009-11-19 15:53:57 -0800790 int isbad = 0;
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800791 unsigned cwperpage;
792 cwperpage = (flash_pagesize >> 9);
Shashank Mittalad3d05c2009-11-19 15:53:57 -0800793
794 /* Check for bad block and read only from a good block */
795 isbad = flash_nand_block_isbad(cmdlist, ptrlist, page);
796 if (isbad)
797 return -2;
Dima Zavin03cf4312009-01-23 16:38:30 -0800798
799 data->cmd = NAND_CMD_PAGE_READ_ECC;
800 data->addr0 = page << 16;
801 data->addr1 = (page >> 16) & 0xff;
802 data->chipsel = 0 | 4; /* flash0 + undoc bit */
803
804 /* GO bit for the EXEC register */
805 data->exec = 1;
806
807 data->cfg0 = CFG0;
808 data->cfg1 = CFG1;
809
Channagoud Kadabi404a7062011-03-21 19:27:50 +0530810 if (enable_bch_ecc) {
811 data->ecc_bch_cfg = ECC_BCH_CFG;
812 }
Dima Zavin03cf4312009-01-23 16:38:30 -0800813 data->ecc_cfg = 0x203;
814
815 /* save existing ecc config */
816 cmd->cmd = CMD_OCB;
817 cmd->src = NAND_EBI2_ECC_BUF_CFG;
818 cmd->dst = paddr(&data->ecc_cfg_save);
819 cmd->len = 4;
820 cmd++;
821
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800822 for(n = 0; n < cwperpage; n++) {
Dima Zavin03cf4312009-01-23 16:38:30 -0800823 /* write CMD / ADDR0 / ADDR1 / CHIPSEL regs in a burst */
824 cmd->cmd = DST_CRCI_NAND_CMD;
825 cmd->src = paddr(&data->cmd);
826 cmd->dst = NAND_FLASH_CMD;
827 cmd->len = ((n == 0) ? 16 : 4);
828 cmd++;
829
830 if (n == 0) {
831 /* block on cmd ready, set configuration */
832 cmd->cmd = 0;
833 cmd->src = paddr(&data->cfg0);
834 cmd->dst = NAND_DEV0_CFG0;
Channagoud Kadabi404a7062011-03-21 19:27:50 +0530835 if (enable_bch_ecc) {
836 cmd->len = 12;
837 } else {
838 cmd->len = 8;
839 }
Dima Zavin03cf4312009-01-23 16:38:30 -0800840 cmd++;
841
842 /* set our ecc config */
843 cmd->cmd = 0;
844 cmd->src = paddr(&data->ecc_cfg);
845 cmd->dst = NAND_EBI2_ECC_BUF_CFG;
846 cmd->len = 4;
847 cmd++;
848 }
849 /* kick the execute register */
850 cmd->cmd = 0;
851 cmd->src = paddr(&data->exec);
852 cmd->dst = NAND_EXEC_CMD;
853 cmd->len = 4;
854 cmd++;
855
856 /* block on data ready, then read the status register */
857 cmd->cmd = SRC_CRCI_NAND_DATA;
858 cmd->src = NAND_FLASH_STATUS;
859 cmd->dst = paddr(&data->result[n]);
860 cmd->len = 8;
861 cmd++;
862
863 /* read data block */
864 cmd->cmd = 0;
865 cmd->src = NAND_FLASH_BUFFER;
866 cmd->dst = addr + n * 516;
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800867 cmd->len = ((n < (cwperpage -1 )) ? 516 : (512 - ((cwperpage - 1) << 2)));
Dima Zavin03cf4312009-01-23 16:38:30 -0800868 cmd++;
869 }
870
871 /* read extra data */
872 cmd->cmd = 0;
Channagoud Kadabi404a7062011-03-21 19:27:50 +0530873 cmd->src = NAND_FLASH_BUFFER + (512 - ((cwperpage - 1) << 2));
Dima Zavin03cf4312009-01-23 16:38:30 -0800874 cmd->dst = spareaddr;
875 cmd->len = 16;
876 cmd++;
877
878 /* restore saved ecc config */
879 cmd->cmd = CMD_OCU | CMD_LC;
880 cmd->src = paddr(&data->ecc_cfg_save);
881 cmd->dst = NAND_EBI2_ECC_BUF_CFG;
882 cmd->len = 4;
883
884 ptr[0] = (paddr(cmdlist) >> 3) | CMD_PTR_LP;
885
886 dmov_exec_cmdptr(DMOV_NAND_CHAN, ptr);
887
888#if VERBOSE
889 dprintf(INFO, "read page %d: status: %x %x %x %x\n",
890 page, data[5], data[6], data[7], data[8]);
891 for(n = 0; n < 4; n++) {
892 ptr = (unsigned*)(addr + 512 * n);
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800893 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 -0800894 ptr = (unsigned*)(spareaddr + 16 * n);
Shashank Mittalc20b5a12009-11-18 19:35:30 -0800895 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 -0800896 }
897#endif
898
899 /* if any of the writes failed (0x10), or there was a
900 ** protection violation (0x100), we lose
901 */
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800902 for(n = 0; n < cwperpage; n++) {
Dima Zavin03cf4312009-01-23 16:38:30 -0800903 if (data->result[n].flash_status & 0x110) {
904 return -1;
905 }
906 }
907
908 return 0;
909}
910
Murali Nalajalaa8c94c62010-03-05 20:24:30 +0530911static int flash_nand_read_page_interleave(dmov_s *cmdlist, unsigned *ptrlist,
912 unsigned page, void *_addr, void *_spareaddr)
913{
914 dmov_s *cmd = cmdlist;
915 unsigned *ptr = ptrlist;
916 struct interleave_data_flash_io *data = (void*) (ptrlist + 4);
917 unsigned addr = (unsigned) _addr;
918 unsigned spareaddr = (unsigned) _spareaddr;
919 unsigned n;
920 int isbad = 0;
921 unsigned cwperpage;
922 cwperpage = (flash_pagesize >> 9);
923
924 /* Check for bad block and read only from a good block */
925 isbad = flash_nand_block_isbad(cmdlist, ptrlist, page);
926 if (isbad)
927 return -2;
928
929 data->cmd = NAND_CMD_PAGE_READ_ECC;
930 data->addr0 = page << 16;
931 data->addr1 = (page >> 16) & 0xff;
932 data->chipsel_cs0 = 0 | 4; /* flash0 + undoc bit */
933 data->chipsel_cs1 = 0 | 5; /* flash0 + undoc bit */
934 data->ebi2_chip_select_cfg0 = 0x00000805;
935 data->adm_mux_data_ack_req_nc01 = 0x00000A3C;
936 data->adm_mux_cmd_ack_req_nc01 = 0x0000053C;
937 data->adm_mux_data_ack_req_nc10 = 0x00000F28;
938 data->adm_mux_cmd_ack_req_nc10 = 0x00000F14;
939 data->adm_default_mux = 0x00000FC0;
940 data->default_ebi2_chip_select_cfg0 = 0x00000801;
941
942 /* GO bit for the EXEC register */
943 data->exec = 1;
944
945 data->cfg0 = CFG0;
946 data->cfg1 = CFG1;
947
948 data->ecc_cfg = 0x203;
949
950 for (n = 0; n < cwperpage; n++) {
951 /* flash + buffer status return words */
952 data->result[n].flash_status = 0xeeeeeeee;
953
954 if (n == 0) {
955 /* enable CS1 */
956 cmd->cmd = CMD_OCB;
957 cmd->src = paddr(&data->ebi2_chip_select_cfg0);
958 cmd->dst = EBI2_CHIP_SELECT_CFG0;
959 cmd->len = 4;
960 cmd++;
961
962 /* save existing ecc config */
963 cmd->cmd = 0;
964 cmd->src = NAND_EBI2_ECC_BUF_CFG;
965 cmd->dst = paddr(&data->ecc_cfg_save);
966 cmd->len = 4;
967 cmd++;
968
969 /* NC01, NC10 --> ADDR0/ADDR1 */
970 cmd->cmd = 0;
971 cmd->src = paddr(&data->addr0);
972 cmd->dst = NC11(NAND_ADDR0);
973 cmd->len = 8;
974 cmd++;
975
976 /* Select the CS0,
977 * for NC01!
978 */
979 cmd->cmd = 0;
980 cmd->src = paddr(&data->chipsel_cs0);
981 cmd->dst = NC01(NAND_FLASH_CHIP_SELECT);
982 cmd->len = 4;
983 cmd++;
984
985 /* Select the CS1,
986 * for NC10!
987 */
988 cmd->cmd = 0;
989 cmd->src = paddr(&data->chipsel_cs1);
990 cmd->dst = NC10(NAND_FLASH_CHIP_SELECT);
991 cmd->len = 4;
992 cmd++;
993
994 cmd->cmd = 0;
995 cmd->src = paddr(&data->cfg0);
996 cmd->dst = NC01(NAND_DEV0_CFG0);
997 cmd->len = 8;
998 cmd++;
999
1000 /* config DEV1 for CS1 */
1001 cmd->cmd = 0;
1002 cmd->src = paddr(&data->cfg0);
1003 cmd->dst = NC10(NAND_DEV1_CFG0);
1004 cmd->len = 8;
1005 cmd++;
1006
1007 cmd->cmd = 0;
1008 cmd->src = paddr(&data->ecc_cfg);
1009 cmd->dst = NC11(NAND_EBI2_ECC_BUF_CFG);
1010 cmd->len = 4;
1011 cmd++;
1012
1013 /* if 'only' the last code word */
1014 if (n == cwperpage - 1) {
1015 /* MASK CMD ACK/REQ --> NC01 (0x53C)*/
1016 cmd->cmd = 0;
1017 cmd->src = paddr(&data->adm_mux_cmd_ack_req_nc01);
1018 cmd->dst = EBI2_NAND_ADM_MUX;
1019 cmd->len = 4;
1020 cmd++;
1021
1022 /* CMD */
1023 cmd->cmd = DST_CRCI_NAND_CMD;
1024 cmd->src = paddr(&data->cmd);
1025 cmd->dst = NC10(NAND_FLASH_CMD);
1026 cmd->len = 4;
1027 cmd++;
1028
1029 /* kick the execute register for NC10 */
1030 cmd->cmd = 0;
1031 cmd->src = paddr(&data->exec);
1032 cmd->dst = NC10(NAND_EXEC_CMD);
1033 cmd->len = 4;
1034 cmd++;
1035
1036 /* MASK DATA ACK/REQ --> NC01 (0xA3C)*/
1037 cmd->cmd = 0;
1038 cmd->src = paddr(&data->adm_mux_data_ack_req_nc01);
1039 cmd->dst = EBI2_NAND_ADM_MUX;
1040 cmd->len = 4;
1041 cmd++;
1042
1043 /* block on data ready from NC10, then
1044 * read the status register
1045 */
1046 cmd->cmd = SRC_CRCI_NAND_DATA;
1047 cmd->src = NC10(NAND_FLASH_STATUS);
1048 cmd->dst = paddr(&data->result[n]);
1049 /* NAND_FLASH_STATUS +
1050 * NAND_BUFFER_STATUS
1051 */
1052 cmd->len = 4;
1053 cmd++;
1054 } else {
1055 /* MASK CMD ACK/REQ --> NC10 (0xF14)*/
1056 cmd->cmd = 0;
1057 cmd->src = paddr(&data->adm_mux_cmd_ack_req_nc10);
1058 cmd->dst = EBI2_NAND_ADM_MUX;
1059 cmd->len = 4;
1060 cmd++;
1061
1062 /* CMD */
1063 cmd->cmd = DST_CRCI_NAND_CMD;
1064 cmd->src = paddr(&data->cmd);
1065 cmd->dst = NC01(NAND_FLASH_CMD);
1066 cmd->len = 4;
1067 cmd++;
1068
1069 /* kick the execute register for NC01*/
1070 cmd->cmd = 0;
1071 cmd->src = paddr(&data->exec);
1072 cmd->dst = NC01(NAND_EXEC_CMD);
1073 cmd->len = 4;
1074 cmd++;
1075 }
1076 }
1077
1078
1079 if (n % 2 == 0) {
1080 /* MASK CMD ACK/REQ --> NC01 (0x53C)*/
1081 cmd->cmd = 0;
1082 cmd->src = paddr(&data->adm_mux_cmd_ack_req_nc01);
1083 cmd->dst = EBI2_NAND_ADM_MUX;
1084 cmd->len = 4;
1085 cmd++;
1086
1087 /* CMD */
1088 cmd->cmd = DST_CRCI_NAND_CMD;
1089 cmd->src = paddr(&data->cmd);
1090 cmd->dst = NC10(NAND_FLASH_CMD);
1091 cmd->len = 4;
1092 cmd++;
1093
1094 /* kick the execute register for NC10 */
1095 cmd->cmd = 0;
1096 cmd->src = paddr(&data->exec);
1097 cmd->dst = NC10(NAND_EXEC_CMD);
1098 cmd->len = 4;
1099 cmd++;
1100
1101 /* MASK DATA ACK/REQ --> NC10 (0xF28)*/
1102 cmd->cmd = 0;
1103 cmd->src = paddr(&data->adm_mux_data_ack_req_nc10);
1104 cmd->dst = EBI2_NAND_ADM_MUX;
1105 cmd->len = 4;
1106 cmd++;
1107
1108 /* block on data ready from NC01, then
1109 * read the status register
1110 */
1111 cmd->cmd = SRC_CRCI_NAND_DATA;
1112 cmd->src = NC01(NAND_FLASH_STATUS);
1113 cmd->dst = paddr(&data->result[n]);
1114 /* NAND_FLASH_STATUS +
1115 * NAND_BUFFER_STATUS
1116 */
1117 cmd->len = 4;
1118 cmd++;
1119
1120 /* read data block */
1121 cmd->cmd = 0;
1122 cmd->src = NC01(NAND_FLASH_BUFFER);
1123 cmd->dst = addr + n * 516;
1124 cmd->len = ((n < (cwperpage -1 )) ? 516 : (512 - ((cwperpage - 1) << 2)));
1125 cmd++;
1126 } else {
1127 if (n != cwperpage - 1) {
1128 /* MASK CMD ACK/REQ -->
1129 * NC10 (0xF14)
1130 */
1131 cmd->cmd = 0;
1132 cmd->src = paddr(&data->adm_mux_cmd_ack_req_nc10);
1133 cmd->dst = EBI2_NAND_ADM_MUX;
1134 cmd->len = 4;
1135 cmd++;
1136
1137 /* CMD */
1138 cmd->cmd = DST_CRCI_NAND_CMD;
1139 cmd->src = paddr(&data->cmd);
1140 cmd->dst = NC01(NAND_FLASH_CMD);
1141 cmd->len = 4;
1142 cmd++;
1143
1144 /* EXEC */
1145 cmd->cmd = 0;
1146 cmd->src = paddr(&data->exec);
1147 cmd->dst = NC01(NAND_EXEC_CMD);
1148 cmd->len = 4;
1149 cmd++;
1150
1151 /* MASK DATA ACK/REQ -->
1152 * NC01 (0xA3C)
1153 */
1154 cmd->cmd = 0;
1155 cmd->src = paddr(&data->adm_mux_data_ack_req_nc01);
1156 cmd->dst = EBI2_NAND_ADM_MUX;
1157 cmd->len = 4;
1158 cmd++;
1159
1160 /* block on data ready from NC10
1161 * then read the status register
1162 */
1163 cmd->cmd = SRC_CRCI_NAND_DATA;
1164 cmd->src = NC10(NAND_FLASH_STATUS);
1165 cmd->dst = paddr(&data->result[n]);
1166 /* NAND_FLASH_STATUS +
1167 * NAND_BUFFER_STATUS
1168 */
1169 cmd->len = 4;
1170 cmd++;
1171 } else {
1172 /* MASK DATA ACK/REQ ->
1173 * NC01 (0xA3C)
1174 */
1175 cmd->cmd = 0;
1176 cmd->src = paddr(&data->adm_mux_data_ack_req_nc01);
1177 cmd->dst = EBI2_NAND_ADM_MUX;
1178 cmd->len = 4;
1179 cmd++;
1180
1181 /* block on data ready from NC10
1182 * then read the status register
1183 */
1184 cmd->cmd = SRC_CRCI_NAND_DATA;
1185 cmd->src = NC10(NAND_FLASH_STATUS);
1186 cmd->dst = paddr(&data->result[n]);
1187 /* NAND_FLASH_STATUS +
1188 * NAND_BUFFER_STATUS
1189 */
1190 cmd->len = 4;
1191 cmd++;
1192 }
1193 /* read data block */
1194 cmd->cmd = 0;
1195 cmd->src = NC10(NAND_FLASH_BUFFER);
1196 cmd->dst = addr + n * 516;
1197 cmd->len = ((n < (cwperpage -1 )) ? 516 : (512 - ((cwperpage - 1) << 2)));
1198 cmd++;
1199
1200 if (n == (cwperpage - 1)) {
1201 /* Use NC10 for reading the
1202 * last codeword!!!
1203 */
1204 cmd->cmd = 0;
1205 cmd->src = NC10(NAND_FLASH_BUFFER) +
1206 (512 - ((cwperpage -1) << 2));
1207 cmd->dst = spareaddr;
1208 cmd->len = 16;
1209 cmd++;
1210 }
1211 }
1212 }
1213 /* restore saved ecc config */
1214 cmd->cmd = CMD_OCU | CMD_LC;
1215 cmd->src = paddr(&data->ecc_cfg_save);
1216 cmd->dst = NAND_EBI2_ECC_BUF_CFG;
1217 cmd->len = 4;
1218
1219 /* ADM --> Default mux state (0xFC0) */
1220 cmd->cmd = 0;
1221 cmd->src = paddr(&data->adm_default_mux);
1222 cmd->dst = EBI2_NAND_ADM_MUX;
1223 cmd->len = 4;
1224 cmd++;
1225
1226 /* disable CS1 */
1227 cmd->cmd = 0;
1228 cmd->src = paddr(&data->default_ebi2_chip_select_cfg0);
1229 cmd->dst = EBI2_CHIP_SELECT_CFG0;
1230 cmd->len = 4;
1231 cmd++;
1232
1233 ptr[0] = (paddr(cmdlist) >> 3) | CMD_PTR_LP;
1234
1235 dmov_exec_cmdptr(DMOV_NAND_CHAN, ptr);
1236
1237#if VERBOSE
1238 dprintf(INFO, "read page %d: status: %x %x %x %x %x %x %x %x \
1239 %x %x %x %x %x %x %x %x \n", page,
1240 data->result[0].flash_status[0],
1241 data->result[1].flash_status[1],
1242 data->result[2].flash_status[2],
1243 data->result[3].flash_status[3],
1244 data->result[4].flash_status[4],
1245 data->result[5].flash_status[5],
1246 data->result[6].flash_status[6],
1247 data->result[7].flash_status[7],
1248 data->result[8].flash_status[8],
1249 data->result[9].flash_status[9],
1250 data->result[10].flash_status[10],
1251 data->result[11].flash_status[11],
1252 data->result[12].flash_status[12],
1253 data->result[13].flash_status[13],
1254 data->result[14].flash_status[14],
1255 data->result[15].flash_status[15]);
1256
1257 for(n = 0; n < 4; n++) {
1258 ptr = (unsigned*)(addr + 512 * n);
1259 dprintf(INFO, "data%d: %x %x %x %x\n", n, ptr[0], ptr[1], ptr[2], ptr[3]);
1260 ptr = (unsigned*)(spareaddr + 16 * n);
1261 dprintf(INFO, "spare data%d %x %x %x %x\n", n, ptr[0], ptr[1], ptr[2], ptr[3]);
1262 }
1263#endif
1264
1265 /* if any of the writes failed (0x10), or there was a
1266 ** protection violation (0x100), we lose
1267 */
1268 for(n = 0; n < cwperpage; n++) {
1269 if (data->result[n].flash_status & 0x110) {
1270 return -1;
1271 }
1272 }
1273
1274 return 0;
1275}
1276
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001277static int _flash_nand_write_page(dmov_s *cmdlist, unsigned *ptrlist, unsigned page,
Shashank Mittald0c836d2009-11-20 10:31:18 -08001278 const void *_addr, const void *_spareaddr, unsigned raw_mode)
Dima Zavin03cf4312009-01-23 16:38:30 -08001279{
1280 dmov_s *cmd = cmdlist;
1281 unsigned *ptr = ptrlist;
1282 struct data_flash_io *data = (void*) (ptrlist + 4);
1283 unsigned addr = (unsigned) _addr;
1284 unsigned spareaddr = (unsigned) _spareaddr;
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001285 unsigned n;
Shashank Mittaldcc2e352009-11-19 19:11:16 -08001286 unsigned cwperpage;
1287 cwperpage = (flash_pagesize >> 9);
Shashank Mittal8e49dec2010-03-01 15:19:04 -08001288 unsigned modem_partition = 0;
1289 if (CFG0 == CFG0_M)
1290 {
1291 modem_partition = 1;
1292 }
Dima Zavin03cf4312009-01-23 16:38:30 -08001293
1294 data->cmd = NAND_CMD_PRG_PAGE;
1295 data->addr0 = page << 16;
1296 data->addr1 = (page >> 16) & 0xff;
1297 data->chipsel = 0 | 4; /* flash0 + undoc bit */
Murali Palnatic54d13a2010-01-15 19:50:19 +05301298 data->clrfstatus = 0x00000020;
1299 data->clrrstatus = 0x000000C0;
Dima Zavin03cf4312009-01-23 16:38:30 -08001300
Shashank Mittald0c836d2009-11-20 10:31:18 -08001301 if (!raw_mode){
1302 data->cfg0 = CFG0;
1303 data->cfg1 = CFG1;
Channagoud Kadabi404a7062011-03-21 19:27:50 +05301304 if (enable_bch_ecc) {
1305 data->ecc_bch_cfg = ECC_BCH_CFG;
1306 }
Shashank Mittald0c836d2009-11-20 10:31:18 -08001307 }else{
1308 data->cfg0 = (NAND_CFG0_RAW & ~(7 << 6)) |((cwperpage-1) << 6);
1309 data->cfg1 = NAND_CFG1_RAW | (CFG1 & CFG1_WIDE_FLASH);
1310 }
Dima Zavin03cf4312009-01-23 16:38:30 -08001311
1312 /* GO bit for the EXEC register */
1313 data->exec = 1;
1314
Shashank Mittal8e49dec2010-03-01 15:19:04 -08001315 if (modem_partition)
1316 data->ecc_cfg = 0x1FF;
1317 else
1318 data->ecc_cfg = 0x203;
Dima Zavin03cf4312009-01-23 16:38:30 -08001319
1320 /* save existing ecc config */
1321 cmd->cmd = CMD_OCB;
1322 cmd->src = NAND_EBI2_ECC_BUF_CFG;
1323 cmd->dst = paddr(&data->ecc_cfg_save);
1324 cmd->len = 4;
1325 cmd++;
1326
Shashank Mittaldcc2e352009-11-19 19:11:16 -08001327 for(n = 0; n < cwperpage; n++) {
1328 /* write CMD / ADDR0 / ADDR1 / CHIPSEL regs in a burst */
Dima Zavin03cf4312009-01-23 16:38:30 -08001329 cmd->cmd = DST_CRCI_NAND_CMD;
1330 cmd->src = paddr(&data->cmd);
1331 cmd->dst = NAND_FLASH_CMD;
1332 cmd->len = ((n == 0) ? 16 : 4);
1333 cmd++;
1334
1335 if (n == 0) {
1336 /* set configuration */
1337 cmd->cmd = 0;
1338 cmd->src = paddr(&data->cfg0);
1339 cmd->dst = NAND_DEV0_CFG0;
Channagoud Kadabi404a7062011-03-21 19:27:50 +05301340 if (enable_bch_ecc) {
1341 cmd->len = 12;
1342 } else {
1343 cmd->len = 8;
1344 }
1345
Dima Zavin03cf4312009-01-23 16:38:30 -08001346 cmd++;
1347
1348 /* set our ecc config */
1349 cmd->cmd = 0;
1350 cmd->src = paddr(&data->ecc_cfg);
1351 cmd->dst = NAND_EBI2_ECC_BUF_CFG;
1352 cmd->len = 4;
1353 cmd++;
1354 }
1355
1356 /* write data block */
1357 cmd->cmd = 0;
Dima Zavin03cf4312009-01-23 16:38:30 -08001358 cmd->dst = NAND_FLASH_BUFFER;
Shashank Mittald0c836d2009-11-20 10:31:18 -08001359 if (!raw_mode){
Shashank Mittal8e49dec2010-03-01 15:19:04 -08001360 if(modem_partition){
1361 cmd->src = addr + n * 512;
1362 cmd->len = 512;
1363 }else{
1364 cmd->src = addr + n * 516;
1365 cmd->len = ((n < (cwperpage - 1)) ? 516 : (512 - ((cwperpage - 1) << 2)));
1366 }
Shashank Mittald0c836d2009-11-20 10:31:18 -08001367 }else{
1368 cmd->src = addr;
1369 cmd->len = 528;
1370 }
Dima Zavin03cf4312009-01-23 16:38:30 -08001371 cmd++;
1372
Shashank Mittal8e49dec2010-03-01 15:19:04 -08001373 if ((n == (cwperpage - 1)) && (!raw_mode) && (!modem_partition)) {
Dima Zavin03cf4312009-01-23 16:38:30 -08001374 /* write extra data */
1375 cmd->cmd = 0;
1376 cmd->src = spareaddr;
Shashank Mittaldcc2e352009-11-19 19:11:16 -08001377 cmd->dst = NAND_FLASH_BUFFER + (512 - ((cwperpage - 1) << 2));
1378 cmd->len = (cwperpage << 2);
Dima Zavin03cf4312009-01-23 16:38:30 -08001379 cmd++;
1380 }
1381
1382 /* kick the execute register */
1383 cmd->cmd = 0;
1384 cmd->src = paddr(&data->exec);
1385 cmd->dst = NAND_EXEC_CMD;
1386 cmd->len = 4;
1387 cmd++;
1388
1389 /* block on data ready, then read the status register */
1390 cmd->cmd = SRC_CRCI_NAND_DATA;
1391 cmd->src = NAND_FLASH_STATUS;
1392 cmd->dst = paddr(&data->result[n]);
1393 cmd->len = 8;
1394 cmd++;
Murali Palnatic54d13a2010-01-15 19:50:19 +05301395
1396 cmd->cmd = 0;
1397 cmd->src = paddr(&data->clrfstatus);
1398 cmd->dst = NAND_FLASH_STATUS;
1399 cmd->len = 4;
1400 cmd++;
1401
1402 cmd->cmd = 0;
1403 cmd->src = paddr(&data->clrrstatus);
1404 cmd->dst = NAND_READ_STATUS;
1405 cmd->len = 4;
1406 cmd++;
Dima Zavin03cf4312009-01-23 16:38:30 -08001407 }
1408
1409 /* restore saved ecc config */
1410 cmd->cmd = CMD_OCU | CMD_LC;
1411 cmd->src = paddr(&data->ecc_cfg_save);
1412 cmd->dst = NAND_EBI2_ECC_BUF_CFG;
1413 cmd->len = 4;
1414
1415 ptr[0] = (paddr(cmdlist) >> 3) | CMD_PTR_LP;
1416
1417 dmov_exec_cmdptr(DMOV_NAND_CHAN, ptr);
1418
1419#if VERBOSE
1420 dprintf(INFO, "write page %d: status: %x %x %x %x\n",
1421 page, data[5], data[6], data[7], data[8]);
1422#endif
1423
1424 /* if any of the writes failed (0x10), or there was a
1425 ** protection violation (0x100), or the program success
1426 ** bit (0x80) is unset, we lose
1427 */
Shashank Mittaldcc2e352009-11-19 19:11:16 -08001428 for(n = 0; n < cwperpage; n++) {
Dima Zavin03cf4312009-01-23 16:38:30 -08001429 if(data->result[n].flash_status & 0x110) return -1;
1430 if(!(data->result[n].flash_status & 0x80)) return -1;
1431 }
1432
Dima Zavin5582c7d2009-03-03 15:17:59 -08001433#if VERIFY_WRITE
1434 n = _flash_read_page(cmdlist, ptrlist, page, flash_data,
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001435 flash_data + 2048);
Dima Zavin5582c7d2009-03-03 15:17:59 -08001436 if (n != 0)
1437 return -1;
1438 if (memcmp(flash_data, _addr, 2048) ||
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001439 memcmp(flash_data + 2048, _spareaddr, 16)) {
Dima Zavin5582c7d2009-03-03 15:17:59 -08001440 dprintf(CRITICAL, "verify error @ page %d\n", page);
1441 return -1;
1442 }
1443#endif
Dima Zavin03cf4312009-01-23 16:38:30 -08001444 return 0;
1445}
Murali Nalajalaa8c94c62010-03-05 20:24:30 +05301446
1447static int flash_nand_write_page_interleave(dmov_s *cmdlist, unsigned *ptrlist, unsigned page,
1448 const void *_addr, const void *_spareaddr, unsigned raw_mode)
1449{
1450 dmov_s *cmd = cmdlist;
1451 unsigned *ptr = ptrlist;
1452 struct interleave_data_flash_io *data = (void*) (ptrlist + 4);
1453 unsigned addr = (unsigned) _addr;
1454 unsigned spareaddr = (unsigned) _spareaddr;
1455 unsigned n;
1456 unsigned cwperpage, cwcount;
1457
1458 cwperpage = (flash_pagesize >> 9) * 2; /* double for interleave mode */
1459 cwcount = (cwperpage << 1);
1460
1461 data->cmd = NAND_CMD_PRG_PAGE;
1462 data->addr0 = page << 16;
1463 data->addr1 = (page >> 16) & 0xff;
1464 data->chipsel_cs0 = 0 | 4; /* flash0 + undoc bit */
1465 data->chipsel_cs1 = 0 | 5; /* flash0 + undoc bit */
1466 data->ebi2_chip_select_cfg0 = 0x00000805;
1467 data->adm_mux_data_ack_req_nc01 = 0x00000A3C;
1468 data->adm_mux_cmd_ack_req_nc01 = 0x0000053C;
1469 data->adm_mux_data_ack_req_nc10 = 0x00000F28;
1470 data->adm_mux_cmd_ack_req_nc10 = 0x00000F14;
1471 data->adm_default_mux = 0x00000FC0;
1472 data->default_ebi2_chip_select_cfg0 = 0x00000801;
1473
1474 if (!raw_mode){
1475 data->cfg0 = CFG0;
1476 data->cfg1 = CFG1;
1477 }else{
1478 data->cfg0 = (NAND_CFG0_RAW & ~(7 << 6)) |((cwcount-1) << 6);
1479 data->cfg1 = NAND_CFG1_RAW | (CFG1 & CFG1_WIDE_FLASH);
1480 }
1481
1482 /* GO bit for the EXEC register */
1483 data->exec = 1;
1484 data->ecc_cfg = 0x203;
1485
1486 for (n = 0; n < cwperpage; n++) {
1487 /* status return words */
1488 data->result[n].flash_status = 0xeeeeeeee;
1489
1490 if (n == 0) {
1491 /* enable CS1 */
1492 cmd->cmd = CMD_OCB;
1493 cmd->src = paddr(&data->ebi2_chip_select_cfg0);
1494 cmd->dst = EBI2_CHIP_SELECT_CFG0;
1495 cmd->len = 4;
1496 cmd++;
1497
1498 /* save existing ecc config */
1499 cmd->cmd = 0;
1500 cmd->src = NC11(NAND_EBI2_ECC_BUF_CFG);
1501 cmd->dst = paddr(&data->ecc_cfg_save);
1502 cmd->len = 4;
1503 cmd++;
1504
1505 cmd->cmd = 0;
1506 cmd->src = paddr(&data->ecc_cfg);
1507 cmd->dst = NC11(NAND_EBI2_ECC_BUF_CFG);
1508 cmd->len = 4;
1509 cmd++;
1510
1511 cmd->cmd = 0;
1512 cmd->src = paddr(&data->addr0);
1513 cmd->dst = NC11(NAND_ADDR0);
1514 cmd->len = 8;
1515 cmd++;
1516
1517 /* enable CS0 */
1518 cmd->cmd = 0;
1519 cmd->src = paddr(&data->chipsel_cs0);
1520 cmd->dst = NC01(NAND_FLASH_CHIP_SELECT);
1521 cmd->len = 4;
1522 cmd++;
1523
1524 /* enable CS1 */
1525 cmd->cmd = 0;
1526 cmd->src = paddr(&data->chipsel_cs1);
1527 cmd->dst = NC10(NAND_FLASH_CHIP_SELECT);
1528 cmd->len = 4;
1529 cmd++;
1530
1531 cmd->cmd = 0;
1532 cmd->src =paddr(&data->cfg0);
1533 cmd->dst = NC01(NAND_DEV0_CFG0);
1534 cmd->len = 8;
1535 cmd++;
1536
1537 /* config CFG1 for CS1 */
1538 cmd->cmd = 0;
1539 cmd->src =paddr(&data->cfg0);
1540 cmd->dst = NC10(NAND_DEV1_CFG0);
1541 cmd->len = 8;
1542 cmd++;
1543 }
1544
1545 if (n % 2 == 0) {
1546 /* MASK CMD ACK/REQ --> NC10 (0xF14)*/
1547 cmd->cmd = 0;
1548 cmd->src = paddr(&data->adm_mux_cmd_ack_req_nc10);
1549 cmd->dst = EBI2_NAND_ADM_MUX;
1550 cmd->len = 4;
1551 cmd++;
1552
1553 /* CMD */
1554 cmd->cmd = DST_CRCI_NAND_CMD;
1555 cmd->src = paddr(&data->cmd);
1556 cmd->dst = NC01(NAND_FLASH_CMD);
1557 cmd->len = 4;
1558 cmd++;
1559 } else {
1560 /* MASK CMD ACK/REQ --> NC01 (0x53C)*/
1561 cmd->cmd = 0;
1562 cmd->src = paddr(&data->adm_mux_cmd_ack_req_nc01);
1563 cmd->dst = EBI2_NAND_ADM_MUX;
1564 cmd->len = 4;
1565 cmd++;
1566
1567 /* CMD */
1568 cmd->cmd = DST_CRCI_NAND_CMD;
1569 cmd->src = paddr(&data->cmd);
1570 cmd->dst = NC10(NAND_FLASH_CMD);
1571 cmd->len = 4;
1572 cmd++;
1573 }
1574
1575 cmd->cmd = 0;
1576 if (!raw_mode){
1577 cmd->src = addr + n * 516;
1578 cmd->len = ((n < (cwperpage - 1)) ? 516 : (512 - ((cwperpage - 1) << 2)));
1579 }else{
1580 cmd->src = addr;
1581 cmd->len = 528;
1582 }
1583
1584 if (n % 2 == 0)
1585 cmd->dst = NC01(NAND_FLASH_BUFFER);
1586 else
1587 cmd->dst = NC10(NAND_FLASH_BUFFER);
1588 cmd++;
1589
1590 if ((n == (cwperpage - 1)) && (!raw_mode)) {
1591 /* write extra data */
1592 cmd->cmd = 0;
1593 cmd->src = spareaddr;
1594 cmd->dst = NC10(NAND_FLASH_BUFFER) + (512 - ((cwperpage - 1) << 2));
1595 cmd->len = (cwperpage << 2);
1596 cmd++;
1597 }
1598
1599 if (n % 2 == 0) {
1600 /* kick the NC01 execute register */
1601 cmd->cmd = 0;
1602 cmd->src = paddr(&data->exec);
1603 cmd->dst = NC01(NAND_EXEC_CMD);
1604 cmd->len = 4;
1605 cmd++;
1606 if (n != 0) {
1607 /* MASK DATA ACK/REQ --> NC01 (0xA3C)*/
1608 cmd->cmd = 0;
1609 cmd->src = paddr(&data->adm_mux_data_ack_req_nc01);
1610 cmd->dst = EBI2_NAND_ADM_MUX;
1611 cmd->len = 4;
1612 cmd++;
1613
1614 /* block on data ready from NC10, then
1615 * read the status register
1616 */
1617 cmd->cmd = SRC_CRCI_NAND_DATA;
1618 cmd->src = NC10(NAND_FLASH_STATUS);
1619 cmd->dst = paddr(&data->result[n-1]);
1620 cmd->len = 4;
1621 cmd++;
1622 }
1623 } else {
1624 /* kick the execute register */
1625 cmd->cmd = 0;
1626 cmd->src = paddr(&data->exec);
1627 cmd->dst = NC10(NAND_EXEC_CMD);
1628 cmd->len = 4;
1629 cmd++;
1630
1631 /* MASK DATA ACK/REQ --> NC10 (0xF28)*/
1632 cmd->cmd = 0;
1633 cmd->src = paddr(&data->adm_mux_data_ack_req_nc10);
1634 cmd->dst = EBI2_NAND_ADM_MUX;
1635 cmd->len = 4;
1636 cmd++;
1637
1638 /* block on data ready from NC01, then
1639 * read the status register
1640 */
1641 cmd->cmd = SRC_CRCI_NAND_DATA;
1642 cmd->src = NC01(NAND_FLASH_STATUS);
1643 cmd->dst = paddr(&data->result[n-1]);
1644 cmd->len = 4;
1645 cmd++;
1646 }
1647 }
1648
1649 /* MASK DATA ACK/REQ --> NC01 (0xA3C)*/
1650 cmd->cmd = 0;
1651 cmd->src = paddr(&data->adm_mux_data_ack_req_nc01);
1652 cmd->dst = EBI2_NAND_ADM_MUX;
1653 cmd->len = 4;
1654 cmd++;
1655
1656 /* we should process outstanding request */
1657 /* block on data ready, then
1658 * read the status register
1659 */
1660 cmd->cmd = SRC_CRCI_NAND_DATA;
1661 cmd->src = NC10(NAND_FLASH_STATUS);
1662 cmd->dst = paddr(&data->result[n-1]);
1663 cmd->len = 4;
1664 cmd++;
1665
1666 /* restore saved ecc config */
1667 cmd->cmd = 0;
1668 cmd->src = paddr(&data->ecc_cfg_save);
1669 cmd->dst = NAND_EBI2_ECC_BUF_CFG;
1670 cmd->len = 4;
1671
1672 /* MASK DATA ACK/REQ --> NC01 (0xFC0)*/
1673 cmd->cmd = 0;
1674 cmd->src = paddr(&data->adm_default_mux);
1675 cmd->dst = EBI2_NAND_ADM_MUX;
1676 cmd->len = 4;
1677 cmd++;
1678
1679 /* disable CS1 */
1680 cmd->cmd = CMD_OCU | CMD_LC;
1681 cmd->src = paddr(&data->default_ebi2_chip_select_cfg0);
1682 cmd->dst = EBI2_CHIP_SELECT_CFG0;
1683 cmd->len = 4;
1684 cmd++;
1685
1686 ptr[0] = (paddr(cmdlist) >> 3) | CMD_PTR_LP;
1687
1688 dmov_exec_cmdptr(DMOV_NAND_CHAN, ptr);
1689
1690#if VERBOSE
1691dprintf(INFO, "write page %d: status: %x %x %x %x %x %x %x %x \
1692 %x %x %x %x %x %x %x %x \n", page,
1693 data->result[0].flash_status[0],
1694 data->result[1].flash_status[1],
1695 data->result[2].flash_status[2],
1696 data->result[3].flash_status[3],
1697 data->result[4].flash_status[4],
1698 data->result[5].flash_status[5],
1699 data->result[6].flash_status[6],
1700 data->result[7].flash_status[7],
1701 data->result[8].flash_status[8],
1702 data->result[9].flash_status[9],
1703 data->result[10].flash_status[10],
1704 data->result[11].flash_status[11],
1705 data->result[12].flash_status[12],
1706 data->result[13].flash_status[13],
1707 data->result[14].flash_status[14],
1708 data->result[15].flash_status[15]);
1709#endif
1710
1711 /* if any of the writes failed (0x10), or there was a
1712 ** protection violation (0x100), or the program success
1713 ** bit (0x80) is unset, we lose
1714 */
1715 for(n = 0; n < cwperpage; n++) {
1716 if(data->result[n].flash_status & 0x110) return -1;
1717 if(!(data->result[n].flash_status & 0x80)) return -1;
1718 }
1719
1720#if VERIFY_WRITE
1721 n = _flash_read_page(cmdlist, ptrlist, page, flash_data,
1722 flash_data + 2048);
1723 if (n != 0)
1724 return -1;
1725 if (memcmp(flash_data, _addr, 2048) ||
1726 memcmp(flash_data + 2048, _spareaddr, 16)) {
1727 dprintf(CRITICAL, "verify error @ page %d\n", page);
1728 return -1;
1729 }
1730#endif
1731 return 0;
1732}
1733
Shashank Mittald0c836d2009-11-20 10:31:18 -08001734char empty_buf[528];
1735static int flash_nand_mark_badblock(dmov_s *cmdlist, unsigned *ptrlist, unsigned page)
1736{
1737 memset(empty_buf,0,528);
1738 /* Going to first page of the block */
Channagoud Kadabibeb17d52011-03-25 17:14:00 +05301739 if(page & num_pages_per_blk_mask)
1740 page = page - (page & num_pages_per_blk_mask);
Shashank Mittald0c836d2009-11-20 10:31:18 -08001741 return _flash_nand_write_page(cmdlist, ptrlist, page, empty_buf, 0, 1);
1742}
Dima Zavin03cf4312009-01-23 16:38:30 -08001743
Shashank Mittal83d16d02009-11-18 16:54:42 -08001744unsigned nand_cfg0;
1745unsigned nand_cfg1;
1746
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001747static int flash_nand_read_config(dmov_s *cmdlist, unsigned *ptrlist)
Dima Zavin03cf4312009-01-23 16:38:30 -08001748{
Shashank Mittal8e49dec2010-03-01 15:19:04 -08001749 static unsigned CFG0_TMP, CFG1_TMP;
Dima Zavin03cf4312009-01-23 16:38:30 -08001750 cmdlist[0].cmd = CMD_OCB;
1751 cmdlist[0].src = NAND_DEV0_CFG0;
Shashank Mittal8e49dec2010-03-01 15:19:04 -08001752 cmdlist[0].dst = paddr(&CFG0_TMP);
Dima Zavin03cf4312009-01-23 16:38:30 -08001753 cmdlist[0].len = 4;
1754
1755 cmdlist[1].cmd = CMD_OCU | CMD_LC;
1756 cmdlist[1].src = NAND_DEV0_CFG1;
Shashank Mittal8e49dec2010-03-01 15:19:04 -08001757 cmdlist[1].dst = paddr(&CFG1_TMP);
Dima Zavin03cf4312009-01-23 16:38:30 -08001758 cmdlist[1].len = 4;
1759
1760 *ptrlist = (paddr(cmdlist) >> 3) | CMD_PTR_LP;
1761
1762 dmov_exec_cmdptr(DMOV_NAND_CHAN, ptrlist);
1763
Shashank Mittal8e49dec2010-03-01 15:19:04 -08001764 if((CFG0_TMP == 0) || (CFG1_TMP == 0)) {
Dima Zavin03cf4312009-01-23 16:38:30 -08001765 return -1;
1766 }
1767
Shashank Mittal8e49dec2010-03-01 15:19:04 -08001768 CFG0_A = CFG0_TMP;
1769 CFG1_A = CFG1_TMP;
Shashank Mittal83d16d02009-11-18 16:54:42 -08001770 if (flash_info.type == FLASH_16BIT_NAND_DEVICE) {
1771 nand_cfg1 |= CFG1_WIDE_FLASH;
1772 }
Dima Zavin03cf4312009-01-23 16:38:30 -08001773 dprintf(INFO, "nandcfg: %x %x (initial)\n", CFG0, CFG1);
1774
Shashank Mittal8e49dec2010-03-01 15:19:04 -08001775 CFG0_A = (((flash_pagesize >> 9) - 1) << 6) /* 4/8 cw/pg for 2/4k */
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001776 | (516 << 9) /* 516 user data bytes */
1777 | (10 << 19) /* 10 parity bytes */
1778 | (5 << 27) /* 5 address cycles */
Murali Palnatic54d13a2010-01-15 19:50:19 +05301779 | (0 << 30) /* Do not read status before data */
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001780 | (1 << 31) /* Send read cmd */
1781 /* 0 spare bytes for 16 bit nand or 1 spare bytes for 8 bit */
Channagoud Kadabi404a7062011-03-21 19:27:50 +05301782 | ((nand_cfg1 & CFG1_WIDE_FLASH) ? (0 << 23) :
1783 (enable_bch_ecc ? (2 << 23) : (1 << 23))); /* 2 spare bytes for 8 bit bch ecc */
Shashank Mittal8e49dec2010-03-01 15:19:04 -08001784 CFG1_A = (0 << 0) /* Enable ecc */
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001785 | (7 << 2) /* 8 recovery cycles */
1786 | (0 << 5) /* Allow CS deassertion */
Channagoud Kadabi404a7062011-03-21 19:27:50 +05301787 | ((flash_pagesize - ((enable_bch_ecc ? 532 : 528) *
1788 ((flash_pagesize >> 9) - 1)) + 1) << 6) /* Bad block marker location */
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001789 | (0 << 16) /* Bad block in user data area */
1790 | (2 << 17) /* 6 cycle tWB/tRB */
1791 | (nand_cfg1 & CFG1_WIDE_FLASH); /* preserve wide flash flag */
Dima Zavin03cf4312009-01-23 16:38:30 -08001792
Channagoud Kadabi404a7062011-03-21 19:27:50 +05301793 NAND_CFG0_RAW = CFG0_RAW;
1794 NAND_CFG1_RAW = CFG1_RAW;
1795
1796 if (enable_bch_ecc) {
1797 CFG1_A |= (1 << 27); /* Enable BCH engine */
1798 ECC_BCH_CFG = (0 << 0) /* Enable ECC*/
1799 | (0 << 1) /* Enable/Disable SW reset of ECC engine */
1800 | (1 << 4) /* 8bit ecc*/
1801 | ((nand_cfg1 & CFG1_WIDE_FLASH) ? (14 << 8) : (13 << 8))/*parity bytes*/
1802 | (516 << 16) /* 516 user data bytes */
1803 | (1 << 30); /* Turn on ECC engine clocks always */
1804 NAND_CFG0_RAW = CFG0_RAW_BCHECC; /* CW size is increased to 532B */
1805 }
1806
Shashank Mittal8e49dec2010-03-01 15:19:04 -08001807 dprintf(INFO, "nandcfg(Apps): %x %x (used)\n", CFG0_A, CFG1_A);
Dima Zavin03cf4312009-01-23 16:38:30 -08001808
Shashank Mittal8e49dec2010-03-01 15:19:04 -08001809 CFG0_M = CFG0_TMP;
1810 CFG1_M = CFG1_TMP;
1811 if (flash_info.type == FLASH_16BIT_NAND_DEVICE) {
1812 nand_cfg1 |= CFG1_WIDE_FLASH;
1813 }
1814 CFG0_M = (((flash_pagesize >> 9) - 1) << 6) /* 4/8 cw/pg for 2/4k */
1815 | (512 << 9) /* 512 user data bytes */
1816 | (10 << 19) /* 10 parity bytes */
1817 | (5 << 27) /* 5 address cycles */
1818 | (0 << 30) /* Do not read status before data */
1819 | (1 << 31) /* Send read cmd */
1820 | ((nand_cfg1 & CFG1_WIDE_FLASH) ? (4 << 23) : (5 << 23));
1821 CFG1_M = (0 << 0) /* Enable ecc */
1822 | (7 << 2) /* 8 recovery cycles */
1823 | (0 << 5) /* Allow CS deassertion */
1824 | ((flash_pagesize - (528 * ((flash_pagesize >> 9) - 1)) + 1) << 6) /* Bad block marker location */
1825 | (0 << 16) /* Bad block in user data area */
1826 | (2 << 17) /* 6 cycle tWB/tRB */
1827 | (nand_cfg1 & CFG1_WIDE_FLASH); /* preserve wide flash flag */
1828 dprintf(INFO, "nandcfg(Modem): %x %x (used)\n", CFG0_M, CFG1_M);
Dima Zavin03cf4312009-01-23 16:38:30 -08001829 return 0;
1830}
1831
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001832/* OneNAND programming functions */
1833
1834static void flash_onenand_read_id(dmov_s *cmdlist, unsigned *ptrlist)
1835{
1836 dmov_s *cmd = cmdlist;
1837 unsigned *ptr = ptrlist;
1838 unsigned *data = ptrlist + 4;
1839
1840 data[0] = SFLASH_BCFG;
1841 data[1] = SFLASH_PREPCMD(8, 0, 0, NAND_SFCMD_DATXS, NAND_SFCMD_ASYNC, NAND_SFCMD_REGRD);
1842 data[2] = (ONENAND_DEVICE_ID << 16) | (ONENAND_MANUFACTURER_ID);
1843 data[3] = (ONENAND_DATA_BUFFER_SIZE << 16) | (ONENAND_VERSION_ID);
1844 data[4] = (ONENAND_AMOUNT_OF_BUFFERS << 16) | (ONENAND_BOOT_BUFFER_SIZE);
1845 data[5] = (CLEAN_DATA_16 << 16) | (ONENAND_TECHNOLOGY);
1846 data[6] = CLEAN_DATA_32; //status
1847 data[7] = CLEAN_DATA_32; //register read
1848 data[8] = CLEAN_DATA_32; //register read
1849 data[9] = CLEAN_DATA_32; //register read
1850 data[10] = CLEAN_DATA_32; //register read
1851 data[11] = 1;
1852 data[12] = 0 | 4;
1853
1854 /* Setup controller in SFLASH mode */
1855 cmd[0].cmd = 0 | CMD_OCB;
1856 cmd[0].src = paddr(&data[0]);
1857 cmd[0].dst = NAND_SFLASHC_BURST_CFG;
1858 cmd[0].len = 4;
1859
1860 /* Enable data mover for controller */
1861 cmd[1].cmd = 0;
1862 cmd[1].src = paddr(&data[12]);
1863 cmd[1].dst = NAND_FLASH_CHIP_SELECT;
1864 cmd[1].len = 4;
1865
1866 /* Setup SFLASHC_CMD with xfers in async mode */
1867 cmd[2].cmd = DST_CRCI_NAND_CMD;
1868 cmd[2].src = paddr(&data[1]);
1869 cmd[2].dst = NAND_SFLASHC_CMD;
1870 cmd[2].len = 4;
1871
1872 /* Setup to read device information */
1873 cmd[3].cmd = 0;
1874 cmd[3].src = paddr(&data[2]);
1875 cmd[3].dst = NAND_ADDR0;
1876 cmd[3].len = 8;
1877
1878 cmd[4].cmd = 0;
1879 cmd[4].src = paddr(&data[4]);
1880 cmd[4].dst = NAND_ADDR2;
1881 cmd[4].len = 8;
1882
1883 /* Set execute bit */
1884 cmd[5].cmd = 0;
1885 cmd[5].src = paddr(&data[11]);
1886 cmd[5].dst = NAND_SFLASHC_EXEC_CMD;
1887 cmd[5].len = 4;
1888
1889 /* Check status */
1890 cmd[6].cmd = SRC_CRCI_NAND_DATA;
1891 cmd[6].src = NAND_SFLASHC_STATUS;
1892 cmd[6].dst = paddr(&data[6]);
1893 cmd[6].len = 4;
1894
1895 /* Read result device registers */
1896 cmd[7].cmd = 0 | CMD_OCU | CMD_LC;
1897 cmd[7].src = NAND_GENP_REG0;
1898 cmd[7].dst = paddr(&data[7]);
1899 cmd[7].len = 16;
1900
1901 ptr[0] = (paddr(cmd) >> 3) | CMD_PTR_LP;
1902
1903 dmov_exec_cmdptr(DMOV_NAND_CHAN, ptr);
1904
1905#if VERBOSE
1906 dprintf(INFO, "status: %x\n", data[6]);
1907#endif
1908
1909 flash_info.id = data[7];
1910 flash_info.vendor = data[7] & CLEAN_DATA_16;
1911 flash_info.device = (data[7] >> 16) & CLEAN_DATA_16;
1912 return;
1913}
1914
1915
1916struct data_onenand_erase {
1917 unsigned sfbcfg;
1918 unsigned sfcmd[4];
1919 unsigned sfexec;
1920 unsigned sfstat[4];
1921 unsigned addr0;
1922 unsigned addr1;
1923 unsigned addr2;
1924 unsigned addr3;
1925 unsigned addr4;
1926 unsigned addr5;
1927 unsigned addr6;
1928 unsigned data0;
1929 unsigned data1;
1930 unsigned data2;
1931 unsigned data3;
1932 unsigned data4;
1933 unsigned data5;
1934 unsigned data6;
1935};
1936
Shashank Mittalad3d05c2009-11-19 15:53:57 -08001937
1938static int _flash_onenand_read_page(dmov_s *cmdlist, unsigned *ptrlist,
1939 unsigned page, void *_addr,
1940 void *_spareaddr, unsigned raw_mode);
1941
1942
1943static int flash_onenand_block_isbad(dmov_s *cmdlist, unsigned *ptrlist,
1944 unsigned page)
1945{
1946 unsigned char page_data[2112];
1947 unsigned char *oobptr = &(page_data[2048]);
1948
1949 /* Going to first page of the block */
Channagoud Kadabibeb17d52011-03-25 17:14:00 +05301950 if(page & num_pages_per_blk_mask)
1951 page = page - (page & num_pages_per_blk_mask);
Shashank Mittalad3d05c2009-11-19 15:53:57 -08001952
1953 /* Reading page in raw mode */
1954 if (_flash_onenand_read_page(cmdlist, ptrlist,page, page_data, 0, 1))
1955 return 1;
1956
1957 /* Checking if block is bad */
1958 if ((oobptr[0] != 0xFF) || (oobptr[1] != 0xFF) ||
1959 (oobptr[16] != 0xFF) || (oobptr[17] != 0xFF) ||
1960 (oobptr[32] != 0xFF) || (oobptr[33] != 0xFF) ||
1961 (oobptr[48] != 0xFF) || (oobptr[49] != 0xFF)
1962 )
1963 {
1964 return 1;
1965 }
1966 return 0;
1967}
1968
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001969static int flash_onenand_erase_block(dmov_s *cmdlist, unsigned *ptrlist,
1970 unsigned page)
1971{
1972 dmov_s *cmd = cmdlist;
1973 unsigned *ptr = ptrlist;
1974 struct data_onenand_erase *data = (void *)ptrlist + 4;
Shashank Mittalad3d05c2009-11-19 15:53:57 -08001975 int isbad = 0;
Channagoud Kadabibeb17d52011-03-25 17:14:00 +05301976 unsigned erasesize = (flash_pagesize * num_pages_per_blk);
Shashank Mittaldcc2e352009-11-19 19:11:16 -08001977 unsigned onenand_startaddr1 = DEVICE_FLASHCORE_0 | (page * flash_pagesize)/erasesize;
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001978 unsigned onenand_startaddr8 = 0x0000;
1979 unsigned onenand_startaddr2 = DEVICE_BUFFERRAM_0 << 15;
1980 unsigned onenand_startbuffer = DATARAM0_0 << 8;
1981
1982 unsigned controller_status;
1983 unsigned interrupt_status;
1984 unsigned ecc_status;
1985
Shashank Mittaldcc2e352009-11-19 19:11:16 -08001986 if((page * flash_pagesize) & (erasesize-1)) return -1;
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001987
Shashank Mittalad3d05c2009-11-19 15:53:57 -08001988 /* Check for bad block and erase only if block is not marked bad */
1989 isbad = flash_onenand_block_isbad(cmdlist, ptrlist, page);
1990 if (isbad)
1991 {
Channagoud Kadabibeb17d52011-03-25 17:14:00 +05301992 dprintf(INFO, "skipping @ %d (bad block)\n", page / num_pages_per_blk);
Shashank Mittalad3d05c2009-11-19 15:53:57 -08001993 return -1;
1994 }
1995
1996 /*Erase block*/
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001997 onenand_startaddr1 = DEVICE_FLASHCORE_0 |
Shashank Mittaldcc2e352009-11-19 19:11:16 -08001998 ((page * flash_pagesize) / (erasesize));
Shashank Mittalc20b5a12009-11-18 19:35:30 -08001999 onenand_startaddr8 = 0x0000;
2000 onenand_startaddr2 = DEVICE_BUFFERRAM_0 << 15;
2001 onenand_startbuffer = DATARAM0_0 << 8;
2002
2003
2004 data->sfbcfg = SFLASH_BCFG;
2005 data->sfcmd[0] = SFLASH_PREPCMD(7, 0, 0,
2006 NAND_SFCMD_CMDXS,
2007 NAND_SFCMD_ASYNC,
2008 NAND_SFCMD_REGWR);
2009 data->sfcmd[1] = SFLASH_PREPCMD(0, 0, 32,
2010 NAND_SFCMD_CMDXS,
2011 NAND_SFCMD_ASYNC,
2012 NAND_SFCMD_INTHI);
2013 data->sfcmd[2] = SFLASH_PREPCMD(3, 7, 0,
2014 NAND_SFCMD_DATXS,
2015 NAND_SFCMD_ASYNC,
2016 NAND_SFCMD_REGRD);
2017 data->sfcmd[3] = SFLASH_PREPCMD(4, 10, 0,
2018 NAND_SFCMD_CMDXS,
2019 NAND_SFCMD_ASYNC,
2020 NAND_SFCMD_REGWR);
2021 data->sfexec = 1;
2022 data->sfstat[0] = CLEAN_DATA_32;
2023 data->sfstat[1] = CLEAN_DATA_32;
2024 data->sfstat[2] = CLEAN_DATA_32;
2025 data->sfstat[3] = CLEAN_DATA_32;
2026 data->addr0 = (ONENAND_INTERRUPT_STATUS << 16) |
2027 (ONENAND_SYSTEM_CONFIG_1);
2028 data->addr1 = (ONENAND_START_ADDRESS_8 << 16) |
2029 (ONENAND_START_ADDRESS_1);
2030 data->addr2 = (ONENAND_START_BUFFER << 16) |
2031 (ONENAND_START_ADDRESS_2);
2032 data->addr3 = (ONENAND_ECC_STATUS << 16) |
2033 (ONENAND_COMMAND);
2034 data->addr4 = (ONENAND_CONTROLLER_STATUS << 16) |
2035 (ONENAND_INTERRUPT_STATUS);
2036 data->addr5 = (ONENAND_INTERRUPT_STATUS << 16) |
2037 (ONENAND_SYSTEM_CONFIG_1);
2038 data->addr6 = (ONENAND_START_ADDRESS_3 << 16) |
2039 (ONENAND_START_ADDRESS_1);
2040 data->data0 = (ONENAND_CLRINTR << 16) |
2041 (ONENAND_SYSCFG1_ECCENA);
2042 data->data1 = (onenand_startaddr8 << 16) |
2043 (onenand_startaddr1);
2044 data->data2 = (onenand_startbuffer << 16) |
2045 (onenand_startaddr2);
2046 data->data3 = (CLEAN_DATA_16 << 16) |
2047 (ONENAND_CMDERAS);
2048 data->data4 = (CLEAN_DATA_16 << 16) |
2049 (CLEAN_DATA_16);
2050 data->data5 = (ONENAND_CLRINTR << 16) |
2051 (ONENAND_SYSCFG1_ECCENA);
2052 data->data6 = (ONENAND_STARTADDR3_RES << 16) |
2053 (ONENAND_STARTADDR1_RES);
2054
2055 /***************************************************************/
2056 /* Write the necessary address registers in the onenand device */
2057 /***************************************************************/
2058
2059 /* Enable and configure the SFlash controller */
2060 cmd->cmd = 0 | CMD_OCB;
2061 cmd->src = paddr(&data->sfbcfg);
2062 cmd->dst = NAND_SFLASHC_BURST_CFG;
2063 cmd->len = 4;
2064 cmd++;
2065
2066 /* Block on cmd ready and write CMD register */
2067 cmd->cmd = DST_CRCI_NAND_CMD;
2068 cmd->src = paddr(&data->sfcmd[0]);
2069 cmd->dst = NAND_SFLASHC_CMD;
2070 cmd->len = 4;
2071 cmd++;
2072
2073 /* Write the ADDR0 and ADDR1 registers */
2074 cmd->cmd = 0;
2075 cmd->src = paddr(&data->addr0);
2076 cmd->dst = NAND_ADDR0;
2077 cmd->len = 8;
2078 cmd++;
2079
2080 /* Write the ADDR2 ADDR3 ADDR4 ADDR5 registers */
2081 cmd->cmd = 0;
2082 cmd->src = paddr(&data->addr2);
2083 cmd->dst = NAND_ADDR2;
2084 cmd->len = 16;
2085 cmd++;
2086
2087 /* Write the ADDR6 registers */
2088 cmd->cmd = 0;
2089 cmd->src = paddr(&data->addr6);
2090 cmd->dst = NAND_ADDR6;
2091 cmd->len = 4;
2092 cmd++;
2093
2094 /* Write the GENP0, GENP1, GENP2, GENP3, GENP4 registers */
2095 cmd->cmd = 0;
2096 cmd->src = paddr(&data->data0);
2097 cmd->dst = NAND_GENP_REG0;
2098 cmd->len = 16;
2099 cmd++;
2100
2101 /* Write the FLASH_DEV_CMD4,5,6 registers */
2102 cmd->cmd = 0;
2103 cmd->src = paddr(&data->data4);
2104 cmd->dst = NAND_DEV_CMD4;
2105 cmd->len = 12;
2106 cmd++;
2107
2108 /* Kick the execute command */
2109 cmd->cmd = 0;
2110 cmd->src = paddr(&data->sfexec);
2111 cmd->dst = NAND_SFLASHC_EXEC_CMD;
2112 cmd->len = 4;
2113 cmd++;
2114
2115 /* Block on data ready, and read the status register */
2116 cmd->cmd = SRC_CRCI_NAND_DATA;
2117 cmd->src = NAND_SFLASHC_STATUS;
2118 cmd->dst = paddr(&data->sfstat[0]);
2119 cmd->len = 4;
2120 cmd++;
2121
2122 /***************************************************************/
2123 /* Wait for the interrupt from the Onenand device controller */
2124 /***************************************************************/
2125
2126 /* Block on cmd ready and write CMD register */
2127 cmd->cmd = DST_CRCI_NAND_CMD;
2128 cmd->src = paddr(&data->sfcmd[1]);
2129 cmd->dst = NAND_SFLASHC_CMD;
2130 cmd->len = 4;
2131 cmd++;
2132
2133 /* Kick the execute command */
2134 cmd->cmd = 0;
2135 cmd->src = paddr(&data->sfexec);
2136 cmd->dst = NAND_SFLASHC_EXEC_CMD;
2137 cmd->len = 4;
2138 cmd++;
2139
2140 /* Block on data ready, and read the status register */
2141 cmd->cmd = SRC_CRCI_NAND_DATA;
2142 cmd->src = NAND_SFLASHC_STATUS;
2143 cmd->dst = paddr(&data->sfstat[1]);
2144 cmd->len = 4;
2145 cmd++;
2146
2147 /***************************************************************/
2148 /* Read the necessary status registers from the onenand device */
2149 /***************************************************************/
2150
2151 /* Block on cmd ready and write CMD register */
2152 cmd->cmd = DST_CRCI_NAND_CMD;
2153 cmd->src = paddr(&data->sfcmd[2]);
2154 cmd->dst = NAND_SFLASHC_CMD;
2155 cmd->len = 4;
2156 cmd++;
2157
2158 /* Kick the execute command */
2159 cmd->cmd = 0;
2160 cmd->src = paddr(&data->sfexec);
2161 cmd->dst = NAND_SFLASHC_EXEC_CMD;
2162 cmd->len = 4;
2163 cmd++;
2164
2165 /* Block on data ready, and read the status register */
2166 cmd->cmd = SRC_CRCI_NAND_DATA;
2167 cmd->src = NAND_SFLASHC_STATUS;
2168 cmd->dst = paddr(&data->sfstat[2]);
2169 cmd->len = 4;
2170 cmd++;
2171
2172 /* Read the GENP3 register */
2173 cmd->cmd = 0;
2174 cmd->src = NAND_GENP_REG3;
2175 cmd->dst = paddr(&data->data3);
2176 cmd->len = 4;
2177 cmd++;
2178
2179 /* Read the DEVCMD4 register */
2180 cmd->cmd = 0;
2181 cmd->src = NAND_DEV_CMD4;
2182 cmd->dst = paddr(&data->data4);
2183 cmd->len = 4;
2184 cmd++;
2185
2186 /***************************************************************/
2187 /* Restore the necessary registers to proper values */
2188 /***************************************************************/
2189
2190 /* Block on cmd ready and write CMD register */
2191 cmd->cmd = DST_CRCI_NAND_CMD;
2192 cmd->src = paddr(&data->sfcmd[3]);
2193 cmd->dst = NAND_SFLASHC_CMD;
2194 cmd->len = 4;
2195 cmd++;
2196
2197 /* Kick the execute command */
2198 cmd->cmd = 0;
2199 cmd->src = paddr(&data->sfexec);
2200 cmd->dst = NAND_SFLASHC_EXEC_CMD;
2201 cmd->len = 4;
2202 cmd++;
2203
2204 /* Block on data ready, and read the status register */
2205 cmd->cmd = SRC_CRCI_NAND_DATA | CMD_OCU | CMD_LC;
2206 cmd->src = NAND_SFLASHC_STATUS;
2207 cmd->dst = paddr(&data->sfstat[3]);
2208 cmd->len = 4;
2209 cmd++;
2210
2211 ptr[0] = (paddr(cmdlist) >> 3) | CMD_PTR_LP;
2212
2213 dmov_exec_cmdptr(DMOV_NAND_CHAN, ptr);
2214
2215 ecc_status = (data->data3 >> 16) & 0x0000FFFF;
2216 interrupt_status = (data->data4 >> 0) & 0x0000FFFF;
2217 controller_status = (data->data4 >> 16) & 0x0000FFFF;
2218
2219#if VERBOSE
2220 dprintf(INFO, "\n%s: sflash status %x %x %x %x\n", __func__,
2221 data->sfstat[0],
2222 data->sfstat[1],
2223 data->sfstat[2],
2224 data->sfstat[3]);
2225
2226 dprintf(INFO, "%s: controller_status = %x\n", __func__,
2227 controller_status);
2228 dprintf(INFO, "%s: interrupt_status = %x\n", __func__,
2229 interrupt_status);
2230 dprintf(INFO, "%s: ecc_status = %x\n", __func__,
2231 ecc_status);
2232#endif
2233 /* Check for errors, protection violations etc */
2234 if ((controller_status != 0)
2235 || (data->sfstat[0] & 0x110)
2236 || (data->sfstat[1] & 0x110)
2237 || (data->sfstat[2] & 0x110)
2238 || (data->sfstat[3] & 0x110)) {
2239 dprintf(CRITICAL, "%s: ECC/MPU/OP error\n", __func__);
2240 return -1;
2241 }
2242
2243
2244#if VERBOSE
2245 dprintf(INFO, "status: %x\n", data[5]);
2246#endif
2247
2248 return 0;
2249}
2250
2251
2252struct data_onenand_read {
2253 unsigned sfbcfg;
2254 unsigned sfcmd[9];
2255 unsigned sfexec;
2256 unsigned sfstat[9];
2257 unsigned addr0;
2258 unsigned addr1;
2259 unsigned addr2;
2260 unsigned addr3;
2261 unsigned addr4;
2262 unsigned addr5;
2263 unsigned addr6;
2264 unsigned data0;
2265 unsigned data1;
2266 unsigned data2;
2267 unsigned data3;
2268 unsigned data4;
2269 unsigned data5;
2270 unsigned data6;
2271 unsigned macro[5];
2272};
2273
2274
2275static int _flash_onenand_read_page(dmov_s *cmdlist, unsigned *ptrlist,
Shashank Mittalad3d05c2009-11-19 15:53:57 -08002276 unsigned page, void *_addr, void *_spareaddr,
2277 unsigned raw_mode)
Shashank Mittalc20b5a12009-11-18 19:35:30 -08002278{
2279 dmov_s *cmd = cmdlist;
2280 unsigned *ptr = ptrlist;
2281 struct data_onenand_read *data = (void*) (ptrlist + 4);
2282 unsigned addr = (unsigned) _addr;
2283 unsigned curr_addr = (unsigned) _addr;
Greg Griscod2471ef2011-07-14 13:00:42 -07002284#if VERBOSE
Shashank Mittalc20b5a12009-11-18 19:35:30 -08002285 unsigned spareaddr = (unsigned) _spareaddr;
Greg Griscod2471ef2011-07-14 13:00:42 -07002286#endif
Shashank Mittalc20b5a12009-11-18 19:35:30 -08002287 unsigned i;
Channagoud Kadabibeb17d52011-03-25 17:14:00 +05302288 unsigned erasesize = (flash_pagesize * num_pages_per_blk);
Shashank Mittaldcc2e352009-11-19 19:11:16 -08002289 unsigned writesize = flash_pagesize;
Shashank Mittalc20b5a12009-11-18 19:35:30 -08002290
2291 unsigned onenand_startaddr1 = DEVICE_FLASHCORE_0 |
Shashank Mittaldcc2e352009-11-19 19:11:16 -08002292 ((unsigned)(page * flash_pagesize) / erasesize);
2293 unsigned onenand_startaddr8 = (((unsigned)(page * flash_pagesize) &
Shashank Mittalc20b5a12009-11-18 19:35:30 -08002294 (erasesize - 1)) / writesize) << 2;
2295 unsigned onenand_startaddr2 = DEVICE_BUFFERRAM_0 << 15;
2296 unsigned onenand_startbuffer = DATARAM0_0 << 8;
Shashank Mittalad3d05c2009-11-19 15:53:57 -08002297 unsigned onenand_sysconfig1 = (raw_mode == 1) ? ONENAND_SYSCFG1_ECCDIS :\
2298 ONENAND_SYSCFG1_ECCENA;
Shashank Mittalc20b5a12009-11-18 19:35:30 -08002299
2300 unsigned controller_status;
2301 unsigned interrupt_status;
2302 unsigned ecc_status;
Shashank Mittalad3d05c2009-11-19 15:53:57 -08002303 if (raw_mode != 1)
2304 {
2305 int isbad = 0;
2306 isbad = flash_onenand_block_isbad(cmdlist, ptrlist, page);
2307 if (isbad)
2308 return -2;
2309 }
Shashank Mittalc20b5a12009-11-18 19:35:30 -08002310
2311 //static int oobfree_offset[8] = {2, 14, 18, 30, 34, 46, 50, 62};
2312 //static int oobfree_length[8] = {3, 2, 3, 2, 3, 2, 3, 2};
2313
2314 data->sfbcfg = SFLASH_BCFG;
2315 data->sfcmd[0] = SFLASH_PREPCMD(7, 0, 0,
2316 NAND_SFCMD_CMDXS,
2317 NAND_SFCMD_ASYNC,
2318 NAND_SFCMD_REGWR);
2319 data->sfcmd[1] = SFLASH_PREPCMD(0, 0, 32,
2320 NAND_SFCMD_CMDXS,
2321 NAND_SFCMD_ASYNC,
2322 NAND_SFCMD_INTHI);
2323 data->sfcmd[2] = SFLASH_PREPCMD(3, 7, 0,
2324 NAND_SFCMD_DATXS,
2325 NAND_SFCMD_ASYNC,
2326 NAND_SFCMD_REGRD);
2327 data->sfcmd[3] = SFLASH_PREPCMD(256, 0, 0,
2328 NAND_SFCMD_DATXS,
2329 NAND_SFCMD_ASYNC,
2330 NAND_SFCMD_DATRD);
2331 data->sfcmd[4] = SFLASH_PREPCMD(256, 0, 0,
2332 NAND_SFCMD_DATXS,
2333 NAND_SFCMD_ASYNC,
2334 NAND_SFCMD_DATRD);
2335 data->sfcmd[5] = SFLASH_PREPCMD(256, 0, 0,
2336 NAND_SFCMD_DATXS,
2337 NAND_SFCMD_ASYNC,
2338 NAND_SFCMD_DATRD);
2339 data->sfcmd[6] = SFLASH_PREPCMD(256, 0, 0,
2340 NAND_SFCMD_DATXS,
2341 NAND_SFCMD_ASYNC,
2342 NAND_SFCMD_DATRD);
2343 data->sfcmd[7] = SFLASH_PREPCMD(32, 0, 0,
2344 NAND_SFCMD_DATXS,
2345 NAND_SFCMD_ASYNC,
2346 NAND_SFCMD_DATRD);
2347 data->sfcmd[8] = SFLASH_PREPCMD(4, 10, 0,
2348 NAND_SFCMD_CMDXS,
2349 NAND_SFCMD_ASYNC,
2350 NAND_SFCMD_REGWR);
2351 data->sfexec = 1;
2352 data->sfstat[0] = CLEAN_DATA_32;
2353 data->sfstat[1] = CLEAN_DATA_32;
2354 data->sfstat[2] = CLEAN_DATA_32;
2355 data->sfstat[3] = CLEAN_DATA_32;
2356 data->sfstat[4] = CLEAN_DATA_32;
2357 data->sfstat[5] = CLEAN_DATA_32;
2358 data->sfstat[6] = CLEAN_DATA_32;
2359 data->sfstat[7] = CLEAN_DATA_32;
2360 data->sfstat[8] = CLEAN_DATA_32;
2361
2362 data->addr0 = (ONENAND_INTERRUPT_STATUS << 16) |
2363 (ONENAND_SYSTEM_CONFIG_1);
2364 data->addr1 = (ONENAND_START_ADDRESS_8 << 16) |
2365 (ONENAND_START_ADDRESS_1);
2366 data->addr2 = (ONENAND_START_BUFFER << 16) |
2367 (ONENAND_START_ADDRESS_2);
2368 data->addr3 = (ONENAND_ECC_STATUS << 16) |
2369 (ONENAND_COMMAND);
2370 data->addr4 = (ONENAND_CONTROLLER_STATUS << 16) |
2371 (ONENAND_INTERRUPT_STATUS);
2372 data->addr5 = (ONENAND_INTERRUPT_STATUS << 16) |
2373 (ONENAND_SYSTEM_CONFIG_1);
2374 data->addr6 = (ONENAND_START_ADDRESS_3 << 16) |
2375 (ONENAND_START_ADDRESS_1);
2376 data->data0 = (ONENAND_CLRINTR << 16) |
2377 (onenand_sysconfig1);
2378 data->data1 = (onenand_startaddr8 << 16) |
2379 (onenand_startaddr1);
2380 data->data2 = (onenand_startbuffer << 16) |
2381 (onenand_startaddr2);
2382 data->data3 = (CLEAN_DATA_16 << 16) |
2383 (ONENAND_CMDLOADSPARE);
2384 data->data4 = (CLEAN_DATA_16 << 16) |
2385 (CLEAN_DATA_16);
2386 data->data5 = (ONENAND_CLRINTR << 16) |
2387 (ONENAND_SYSCFG1_ECCENA);
2388 data->data6 = (ONENAND_STARTADDR3_RES << 16) |
2389 (ONENAND_STARTADDR1_RES);
2390 data->macro[0] = 0x0200;
2391 data->macro[1] = 0x0300;
2392 data->macro[2] = 0x0400;
2393 data->macro[3] = 0x0500;
2394 data->macro[4] = 0x8010;
2395
2396 /*************************************************************/
2397 /* Write necessary address registers in the onenand device */
2398 /*************************************************************/
2399
2400 /* Enable and configure the SFlash controller */
2401 cmd->cmd = 0 | CMD_OCB;
2402 cmd->src = paddr(&data->sfbcfg);
2403 cmd->dst = NAND_SFLASHC_BURST_CFG;
2404 cmd->len = 4;
2405 cmd++;
2406
2407 /* Block on cmd ready and write CMD register */
2408 cmd->cmd = DST_CRCI_NAND_CMD;
2409 cmd->src = paddr(&data->sfcmd[0]);
2410 cmd->dst = NAND_SFLASHC_CMD;
2411 cmd->len = 4;
2412 cmd++;
2413
2414 /* Write the ADDR0 and ADDR1 registers */
2415 cmd->cmd = 0;
2416 cmd->src = paddr(&data->addr0);
2417 cmd->dst = NAND_ADDR0;
2418 cmd->len = 8;
2419 cmd++;
2420
2421 /* Write the ADDR2 ADDR3 ADDR4 ADDR5 registers */
2422 cmd->cmd = 0;
2423 cmd->src = paddr(&data->addr2);
2424 cmd->dst = NAND_ADDR2;
2425 cmd->len = 16;
2426 cmd++;
2427
2428 /* Write the ADDR6 registers */
2429 cmd->cmd = 0;
2430 cmd->src = paddr(&data->addr6);
2431 cmd->dst = NAND_ADDR6;
2432 cmd->len = 4;
2433 cmd++;
2434
2435 /* Write the GENP0, GENP1, GENP2, GENP3 registers */
2436 cmd->cmd = 0;
2437 cmd->src = paddr(&data->data0);
2438 cmd->dst = NAND_GENP_REG0;
2439 cmd->len = 16;
2440 cmd++;
2441
2442 /* Write the FLASH_DEV_CMD4,5,6 registers */
2443 cmd->cmd = 0;
2444 cmd->src = paddr(&data->data4);
2445 cmd->dst = NAND_DEV_CMD4;
2446 cmd->len = 12;
2447 cmd++;
2448
2449 /* Kick the execute command */
2450 cmd->cmd = 0;
2451 cmd->src = paddr(&data->sfexec);
2452 cmd->dst = NAND_SFLASHC_EXEC_CMD;
2453 cmd->len = 4;
2454 cmd++;
2455
2456 /* Block on data ready, and read the status register */
2457 cmd->cmd = SRC_CRCI_NAND_DATA;
2458 cmd->src = NAND_SFLASHC_STATUS;
2459 cmd->dst = paddr(&data->sfstat[0]);
2460 cmd->len = 4;
2461 cmd++;
2462
2463 /*************************************************************/
2464 /* Wait for the interrupt from the Onenand device controller */
2465 /*************************************************************/
2466
2467 /* Block on cmd ready and write CMD register */
2468 cmd->cmd = DST_CRCI_NAND_CMD;
2469 cmd->src = paddr(&data->sfcmd[1]);
2470 cmd->dst = NAND_SFLASHC_CMD;
2471 cmd->len = 4;
2472 cmd++;
2473
2474 /* Kick the execute command */
2475 cmd->cmd = 0;
2476 cmd->src = paddr(&data->sfexec);
2477 cmd->dst = NAND_SFLASHC_EXEC_CMD;
2478 cmd->len = 4;
2479 cmd++;
2480
2481 /* Block on data ready, and read the status register */
2482 cmd->cmd = SRC_CRCI_NAND_DATA;
2483 cmd->src = NAND_SFLASHC_STATUS;
2484 cmd->dst = paddr(&data->sfstat[1]);
2485 cmd->len = 4;
2486 cmd++;
2487
2488
2489 /*************************************************************/
2490 /* Read necessary status registers from the onenand device */
2491 /*************************************************************/
2492
2493 /* Block on cmd ready and write CMD register */
2494 cmd->cmd = DST_CRCI_NAND_CMD;
2495 cmd->src = paddr(&data->sfcmd[2]);
2496 cmd->dst = NAND_SFLASHC_CMD;
2497 cmd->len = 4;
2498 cmd++;
2499
2500 /* Kick the execute command */
2501 cmd->cmd = 0;
2502 cmd->src = paddr(&data->sfexec);
2503 cmd->dst = NAND_SFLASHC_EXEC_CMD;
2504 cmd->len = 4;
2505 cmd++;
2506
2507 /* Block on data ready, and read the status register */
2508 cmd->cmd = SRC_CRCI_NAND_DATA;
2509 cmd->src = NAND_SFLASHC_STATUS;
2510 cmd->dst = paddr(&data->sfstat[2]);
2511 cmd->len = 4;
2512 cmd++;
2513
2514 /* Read the GENP3 register */
2515 cmd->cmd = 0;
2516 cmd->src = NAND_GENP_REG3;
2517 cmd->dst = paddr(&data->data3);
2518 cmd->len = 4;
2519 cmd++;
2520
2521 /* Read the DEVCMD4 register */
2522 cmd->cmd = 0;
2523 cmd->src = NAND_DEV_CMD4;
2524 cmd->dst = paddr(&data->data4);
2525 cmd->len = 4;
2526 cmd++;
2527
2528
2529 /*************************************************************/
2530 /* Read the data ram area from the onenand buffer ram */
2531 /*************************************************************/
2532
2533 if (addr) {
2534
2535 data->data3 = (CLEAN_DATA_16 << 16) |
2536 (ONENAND_CMDLOAD);
2537
2538 for (i = 0; i < 4; i++) {
2539
2540 /* Block on cmd ready and write CMD register */
2541 cmd->cmd = DST_CRCI_NAND_CMD;
2542 cmd->src = paddr(&data->sfcmd[3+i]);
2543 cmd->dst = NAND_SFLASHC_CMD;
2544 cmd->len = 4;
2545 cmd++;
2546
2547 /* Write the MACRO1 register */
2548 cmd->cmd = 0;
2549 cmd->src = paddr(&data->macro[i]);
2550 cmd->dst = NAND_MACRO1_REG;
2551 cmd->len = 4;
2552 cmd++;
2553
2554 /* Kick the execute command */
2555 cmd->cmd = 0;
2556 cmd->src = paddr(&data->sfexec);
2557 cmd->dst = NAND_SFLASHC_EXEC_CMD;
2558 cmd->len = 4;
2559 cmd++;
2560
2561 /* Block on data rdy, & read status register */
2562 cmd->cmd = SRC_CRCI_NAND_DATA;
2563 cmd->src = NAND_SFLASHC_STATUS;
2564 cmd->dst = paddr(&data->sfstat[3+i]);
2565 cmd->len = 4;
2566 cmd++;
2567
2568 /* Transfer nand ctlr buf contents to usr buf */
2569 cmd->cmd = 0;
2570 cmd->src = NAND_FLASH_BUFFER;
2571 cmd->dst = curr_addr;
2572 cmd->len = 512;
2573 curr_addr += 512;
2574 cmd++;
2575 }
2576 }
2577
Shashank Mittalad3d05c2009-11-19 15:53:57 -08002578 /* Read oob bytes in Raw Mode */
2579 if (raw_mode == 1)
2580 {
2581 /* Block on cmd ready and write CMD register */
2582 cmd->cmd = DST_CRCI_NAND_CMD;
2583 cmd->src = paddr(&data->sfcmd[7]);
2584 cmd->dst = NAND_SFLASHC_CMD;
2585 cmd->len = 4;
2586 cmd++;
2587
2588 /* Write the MACRO1 register */
2589 cmd->cmd = 0;
2590 cmd->src = paddr(&data->macro[4]);
2591 cmd->dst = NAND_MACRO1_REG;
2592 cmd->len = 4;
2593 cmd++;
2594
2595 /* Kick the execute command */
2596 cmd->cmd = 0;
2597 cmd->src = paddr(&data->sfexec);
2598 cmd->dst = NAND_SFLASHC_EXEC_CMD;
2599 cmd->len = 4;
2600 cmd++;
2601
2602 /* Block on data rdy, & read status register */
2603 cmd->cmd = SRC_CRCI_NAND_DATA;
2604 cmd->src = NAND_SFLASHC_STATUS;
2605 cmd->dst = paddr(&data->sfstat[7]);
2606 cmd->len = 4;
2607 cmd++;
2608
2609 /* Transfer nand ctlr buf contents to usr buf */
2610 cmd->cmd = 0;
2611 cmd->src = NAND_FLASH_BUFFER;
2612 cmd->dst = curr_addr;
2613 cmd->len = 64;
2614 curr_addr += 64;
2615 cmd++;
2616 }
2617
Shashank Mittalc20b5a12009-11-18 19:35:30 -08002618 /*************************************************************/
2619 /* Restore the necessary registers to proper values */
2620 /*************************************************************/
2621
2622 /* Block on cmd ready and write CMD register */
2623 cmd->cmd = DST_CRCI_NAND_CMD;
2624 cmd->src = paddr(&data->sfcmd[8]);
2625 cmd->dst = NAND_SFLASHC_CMD;
2626 cmd->len = 4;
2627 cmd++;
2628
2629 /* Kick the execute command */
2630 cmd->cmd = 0;
2631 cmd->src = paddr(&data->sfexec);
2632 cmd->dst = NAND_SFLASHC_EXEC_CMD;
2633 cmd->len = 4;
2634 cmd++;
2635
2636 /* Block on data ready, and read the status register */
2637 cmd->cmd = SRC_CRCI_NAND_DATA | CMD_OCU | CMD_LC;
2638 cmd->src = NAND_SFLASHC_STATUS;
2639 cmd->dst = paddr(&data->sfstat[8]);
2640 cmd->len = 4;
2641 cmd++;
2642
2643
2644 ptr[0] = (paddr(cmdlist) >> 3) | CMD_PTR_LP;
2645
2646 dmov_exec_cmdptr(DMOV_NAND_CHAN, ptr);
2647
2648
2649 ecc_status = (data->data3 >> 16) &
2650 0x0000FFFF;
2651 interrupt_status = (data->data4 >> 0) &
2652 0x0000FFFF;
2653 controller_status = (data->data4 >> 16) &
2654 0x0000FFFF;
2655
2656#if VERBOSE
2657 dprintf(INFO, "\n%s: sflash status %x %x %x %x %x %x %x"
2658 "%x %x\n", __func__,
2659 data->sfstat[0],
2660 data->sfstat[1],
2661 data->sfstat[2],
2662 data->sfstat[3],
2663 data->sfstat[4],
2664 data->sfstat[5],
2665 data->sfstat[6],
2666 data->sfstat[7]);
2667
2668 dprintf(INFO, "%s: controller_status = %x\n", __func__,
2669 controller_status);
2670 dprintf(INFO, "%s: interrupt_status = %x\n", __func__,
2671 interrupt_status);
2672 dprintf(INFO, "%s: ecc_status = %x\n", __func__,
2673 ecc_status);
2674#endif
2675 /* Check for errors, protection violations etc */
2676 if ((controller_status != 0)
2677 || (data->sfstat[0] & 0x110)
2678 || (data->sfstat[1] & 0x110)
2679 || (data->sfstat[2] & 0x110)
2680 || ((data->sfstat[3] & 0x110) &&
2681 (addr))
2682 || ((data->sfstat[4] & 0x110) &&
2683 (addr))
2684 || ((data->sfstat[5] & 0x110) &&
2685 (addr))
2686 || ((data->sfstat[6] & 0x110) &&
2687 (addr))) {
2688 dprintf(INFO, "%s: ECC/MPU/OP error\n", __func__);
2689 return -1;
2690 }
2691
2692#if VERBOSE
2693 dprintf(INFO, "read page %d: status: %x %x %x %x\n",
2694 page, data[5], data[6], data[7], data[8]);
2695 for(n = 0; n < 4; n++) {
2696 ptr = (unsigned*)(addr + 512 * n);
2697 dprintf(INFO, "data%d: %x %x %x %x\n", n, ptr[0], ptr[1], ptr[2], ptr[3]);
2698 ptr = (unsigned*)(spareaddr + 16 * n);
2699 dprintf(INFO, "spare data%d %x %x %x %x\n", n, ptr[0], ptr[1], ptr[2], ptr[3]);
2700 }
2701#endif
2702
2703 return 0;
2704}
2705
2706
2707struct data_onenand_write {
2708 unsigned sfbcfg;
2709 unsigned sfcmd[9];
2710 unsigned sfexec;
2711 unsigned sfstat[9];
2712 unsigned addr0;
2713 unsigned addr1;
2714 unsigned addr2;
2715 unsigned addr3;
2716 unsigned addr4;
2717 unsigned addr5;
2718 unsigned addr6;
2719 unsigned data0;
2720 unsigned data1;
2721 unsigned data2;
2722 unsigned data3;
2723 unsigned data4;
2724 unsigned data5;
2725 unsigned data6;
2726 unsigned macro[5];
2727};
2728
2729static int _flash_onenand_write_page(dmov_s *cmdlist, unsigned *ptrlist,
2730 unsigned page, const void *_addr,
Shashank Mittald0c836d2009-11-20 10:31:18 -08002731 const void *_spareaddr, unsigned raw_mode)
Shashank Mittalc20b5a12009-11-18 19:35:30 -08002732{
2733 dmov_s *cmd = cmdlist;
2734 unsigned *ptr = ptrlist;
2735 struct data_onenand_write *data = (void*) (ptrlist + 4);
2736 unsigned addr = (unsigned) _addr;
2737 unsigned addr_curr = (unsigned) _addr;
2738 char * spareaddr = (char *) _spareaddr;
2739 unsigned i, j, k;
2740
Channagoud Kadabibeb17d52011-03-25 17:14:00 +05302741 unsigned erasesize = (flash_pagesize * num_pages_per_blk);
Shashank Mittaldcc2e352009-11-19 19:11:16 -08002742 unsigned writesize = flash_pagesize;
Shashank Mittalc20b5a12009-11-18 19:35:30 -08002743
Shashank Mittaldcc2e352009-11-19 19:11:16 -08002744 unsigned onenand_startaddr1 = (page * flash_pagesize) / erasesize;
2745 unsigned onenand_startaddr8 = (((unsigned)(page * flash_pagesize) &
Shashank Mittalc20b5a12009-11-18 19:35:30 -08002746 (erasesize-1)) / writesize) << 2;
2747 unsigned onenand_startaddr2 = DEVICE_BUFFERRAM_0 << 15;
2748 unsigned onenand_startbuffer = DATARAM0_0 << 8;
Shashank Mittald0c836d2009-11-20 10:31:18 -08002749 unsigned onenand_sysconfig1 = (raw_mode == 1) ? ONENAND_SYSCFG1_ECCDIS :\
2750 ONENAND_SYSCFG1_ECCENA;
Shashank Mittalc20b5a12009-11-18 19:35:30 -08002751
2752 unsigned controller_status;
2753 unsigned interrupt_status;
2754 unsigned ecc_status;
2755
2756 char flash_oob[64];
2757
2758 unsigned oobfree_offset[8] = {2, 14, 18, 30, 34, 46, 50, 62};
2759 unsigned oobfree_length[8] = {3, 2, 3, 2, 3, 2, 3, 2};
2760
2761 for (i = 0; i < 64; i++)
2762 flash_oob[i] = 0xFF;
2763
2764 data->sfbcfg = SFLASH_BCFG;
2765 data->sfcmd[0] = SFLASH_PREPCMD(256, 0, 0,
2766 NAND_SFCMD_CMDXS,
2767 NAND_SFCMD_ASYNC,
2768 NAND_SFCMD_DATWR);
2769 data->sfcmd[1] = SFLASH_PREPCMD(256, 0, 0,
2770 NAND_SFCMD_CMDXS,
2771 NAND_SFCMD_ASYNC,
2772 NAND_SFCMD_DATWR);
2773 data->sfcmd[2] = SFLASH_PREPCMD(256, 0, 0,
2774 NAND_SFCMD_CMDXS,
2775 NAND_SFCMD_ASYNC,
2776 NAND_SFCMD_DATWR);
2777 data->sfcmd[3] = SFLASH_PREPCMD(256, 0, 0,
2778 NAND_SFCMD_CMDXS,
2779 NAND_SFCMD_ASYNC,
2780 NAND_SFCMD_DATWR);
2781 data->sfcmd[4] = SFLASH_PREPCMD(32, 0, 0,
2782 NAND_SFCMD_CMDXS,
2783 NAND_SFCMD_ASYNC,
2784 NAND_SFCMD_DATWR);
2785 data->sfcmd[5] = SFLASH_PREPCMD(7, 0, 0,
2786 NAND_SFCMD_CMDXS,
2787 NAND_SFCMD_ASYNC,
2788 NAND_SFCMD_REGWR);
2789 data->sfcmd[6] = SFLASH_PREPCMD(0, 0, 32,
2790 NAND_SFCMD_CMDXS,
2791 NAND_SFCMD_ASYNC,
2792 NAND_SFCMD_INTHI);
2793 data->sfcmd[7] = SFLASH_PREPCMD(3, 7, 0,
2794 NAND_SFCMD_DATXS,
2795 NAND_SFCMD_ASYNC,
2796 NAND_SFCMD_REGRD);
2797 data->sfcmd[8] = SFLASH_PREPCMD(4, 10, 0,
2798 NAND_SFCMD_CMDXS,
2799 NAND_SFCMD_ASYNC,
2800 NAND_SFCMD_REGWR);
2801 data->sfexec = 1;
2802
2803 data->sfstat[0] = CLEAN_DATA_32;
2804 data->sfstat[1] = CLEAN_DATA_32;
2805 data->sfstat[2] = CLEAN_DATA_32;
2806 data->sfstat[3] = CLEAN_DATA_32;
2807 data->sfstat[4] = CLEAN_DATA_32;
2808 data->sfstat[5] = CLEAN_DATA_32;
2809 data->sfstat[6] = CLEAN_DATA_32;
2810 data->sfstat[7] = CLEAN_DATA_32;
2811 data->sfstat[8] = CLEAN_DATA_32;
2812 data->addr0 = (ONENAND_INTERRUPT_STATUS << 16) |
2813 (ONENAND_SYSTEM_CONFIG_1);
2814 data->addr1 = (ONENAND_START_ADDRESS_8 << 16) |
2815 (ONENAND_START_ADDRESS_1);
2816 data->addr2 = (ONENAND_START_BUFFER << 16) |
2817 (ONENAND_START_ADDRESS_2);
2818 data->addr3 = (ONENAND_ECC_STATUS << 16) |
2819 (ONENAND_COMMAND);
2820 data->addr4 = (ONENAND_CONTROLLER_STATUS << 16) |
2821 (ONENAND_INTERRUPT_STATUS);
2822 data->addr5 = (ONENAND_INTERRUPT_STATUS << 16) |
2823 (ONENAND_SYSTEM_CONFIG_1);
2824 data->addr6 = (ONENAND_START_ADDRESS_3 << 16) |
2825 (ONENAND_START_ADDRESS_1);
2826 data->data0 = (ONENAND_CLRINTR << 16) |
2827 (onenand_sysconfig1);
2828 data->data1 = (onenand_startaddr8 << 16) |
2829 (onenand_startaddr1);
2830 data->data2 = (onenand_startbuffer << 16) |
2831 (onenand_startaddr2);
2832 data->data3 = (CLEAN_DATA_16 << 16) |
2833 (ONENAND_CMDPROGSPARE);
2834 data->data3 = (CLEAN_DATA_16 << 16) |
2835 (ONENAND_CMDPROGSPARE);
2836 data->data4 = (CLEAN_DATA_16 << 16) |
2837 (CLEAN_DATA_16);
2838 data->data5 = (ONENAND_CLRINTR << 16) |
2839 (ONENAND_SYSCFG1_ECCENA);
2840 data->data6 = (ONENAND_STARTADDR3_RES << 16) |
2841 (ONENAND_STARTADDR1_RES);
2842 data->macro[0] = 0x0200;
2843 data->macro[1] = 0x0300;
2844 data->macro[2] = 0x0400;
2845 data->macro[3] = 0x0500;
2846 data->macro[4] = 0x8010;
2847
2848
2849 /*************************************************************/
2850 /* Write the data ram area in the onenand buffer ram */
2851 /*************************************************************/
2852
2853 /* Enable and configure the SFlash controller */
2854 cmd->cmd = 0 | CMD_OCB;
2855 cmd->src = paddr(&data->sfbcfg);
2856 cmd->dst = NAND_SFLASHC_BURST_CFG;
2857 cmd->len = 4;
2858 cmd++;
2859
2860 if (addr) {
2861 data->data3 = (CLEAN_DATA_16 << 16) |
2862 (ONENAND_CMDPROG);
2863
2864 for (i = 0; i < 4; i++) {
2865
2866 /* Block on cmd ready and write CMD register */
2867 cmd->cmd = DST_CRCI_NAND_CMD;
2868 cmd->src = paddr(&data->sfcmd[i]);
2869 cmd->dst = NAND_SFLASHC_CMD;
2870 cmd->len = 4;
2871 cmd++;
2872
2873 /* Trnsfr usr buf contents to nand ctlr buf */
2874 cmd->cmd = 0;
2875 cmd->src = paddr(addr_curr);
2876 cmd->dst = NAND_FLASH_BUFFER;
2877 cmd->len = 512;
Shashank Mittald0c836d2009-11-20 10:31:18 -08002878 if(!raw_mode)
2879 addr_curr += 512;
Shashank Mittalc20b5a12009-11-18 19:35:30 -08002880 cmd++;
2881
2882 /* Write the MACRO1 register */
2883 cmd->cmd = 0;
2884 cmd->src = paddr(&data->macro[i]);
2885 cmd->dst = NAND_MACRO1_REG;
2886 cmd->len = 4;
2887 cmd++;
2888
2889 /* Kick the execute command */
2890 cmd->cmd = 0;
2891 cmd->src = paddr(&data->sfexec);
2892 cmd->dst = NAND_SFLASHC_EXEC_CMD;
2893 cmd->len = 4;
2894 cmd++;
2895
2896 /* Block on data rdy, & read status register */
2897 cmd->cmd = SRC_CRCI_NAND_DATA;
2898 cmd->src = NAND_SFLASHC_STATUS;
2899 cmd->dst = paddr(&data->sfstat[i]);
2900 cmd->len = 4;
2901 cmd++;
2902
2903 }
2904 }
2905
2906 /* Block on cmd ready and write CMD register */
2907 cmd->cmd = DST_CRCI_NAND_CMD;
2908 cmd->src = paddr(&data->sfcmd[4]);
2909 cmd->dst = NAND_SFLASHC_CMD;
2910 cmd->len = 4;
2911 cmd++;
2912
2913 if (spareaddr)
2914 {
2915 // Auto mode
2916 for (i = 0, k = 0; i < 8; i++) {
2917 for (j = 0; j < oobfree_length[i]; j++) {
2918 flash_oob[j+oobfree_offset[i]] = spareaddr[k];
2919 k++;
2920 }
2921 }
2922
2923 cmd->cmd = 0;
2924 cmd->src = paddr(&flash_oob);
2925 cmd->dst = NAND_FLASH_BUFFER;
2926 cmd->len = 64;
2927 cmd++;
2928 }
2929
Shashank Mittald0c836d2009-11-20 10:31:18 -08002930 if (raw_mode){
2931 cmd->cmd = 0;
2932 cmd->src = paddr(addr_curr);
2933 cmd->dst = NAND_FLASH_BUFFER;
2934 cmd->len = 64;
2935 cmd++;
2936 }
2937
Shashank Mittalc20b5a12009-11-18 19:35:30 -08002938 /* Write the MACRO1 register */
2939 cmd->cmd = 0;
2940 cmd->src = paddr(&data->macro[4]);
2941 cmd->dst = NAND_MACRO1_REG;
2942 cmd->len = 4;
2943 cmd++;
2944
2945 /* Kick the execute command */
2946 cmd->cmd = 0;
2947 cmd->src = paddr(&data->sfexec);
2948 cmd->dst = NAND_SFLASHC_EXEC_CMD;
2949 cmd->len = 4;
2950 cmd++;
2951
2952 /* Block on data ready, and read the status register */
2953 cmd->cmd = SRC_CRCI_NAND_DATA;
2954 cmd->src = NAND_SFLASHC_STATUS;
2955 cmd->dst = paddr(&data->sfstat[4]);
2956 cmd->len = 4;
2957 cmd++;
2958
2959 /*************************************************************/
2960 /* Write necessary address registers in the onenand device */
2961 /*************************************************************/
2962
2963 /* Block on cmd ready and write CMD register */
2964 cmd->cmd = DST_CRCI_NAND_CMD;
2965 cmd->src = paddr(&data->sfcmd[5]);
2966 cmd->dst = NAND_SFLASHC_CMD;
2967 cmd->len = 4;
2968 cmd++;
2969
2970 /* Write the ADDR0 and ADDR1 registers */
2971 cmd->cmd = 0;
2972 cmd->src = paddr(&data->addr0);
2973 cmd->dst = NAND_ADDR0;
2974 cmd->len = 8;
2975 cmd++;
2976
2977 /* Write the ADDR2 ADDR3 ADDR4 ADDR5 registers */
2978 cmd->cmd = 0;
2979 cmd->src = paddr(&data->addr2);
2980 cmd->dst = NAND_ADDR2;
2981 cmd->len = 16;
2982 cmd++;
2983
2984 /* Write the ADDR6 registers */
2985 cmd->cmd = 0;
2986 cmd->src = paddr(&data->addr6);
2987 cmd->dst = NAND_ADDR6;
2988 cmd->len = 4;
2989 cmd++;
2990
2991 /* Write the GENP0, GENP1, GENP2, GENP3 registers */
2992 cmd->cmd = 0;
2993 cmd->src = paddr(&data->data0);
2994 cmd->dst = NAND_GENP_REG0;
2995 cmd->len = 16;
2996 cmd++;
2997
2998 /* Write the FLASH_DEV_CMD4,5,6 registers */
2999 cmd->cmd = 0;
3000 cmd->src = paddr(&data->data4);
3001 cmd->dst = NAND_DEV_CMD4;
3002 cmd->len = 12;
3003 cmd++;
3004
3005 /* Kick the execute command */
3006 cmd->cmd = 0;
3007 cmd->src = paddr(&data->sfexec);
3008 cmd->dst = NAND_SFLASHC_EXEC_CMD;
3009 cmd->len = 4;
3010 cmd++;
3011
3012 /* Block on data ready, and read the status register */
3013 cmd->cmd = SRC_CRCI_NAND_DATA;
3014 cmd->src = NAND_SFLASHC_STATUS;
3015 cmd->dst = paddr(&data->sfstat[5]);
3016 cmd->len = 4;
3017 cmd++;
3018
3019 /*************************************************************/
3020 /* Wait for the interrupt from the Onenand device controller */
3021 /*************************************************************/
3022
3023 /* Block on cmd ready and write CMD register */
3024 cmd->cmd = DST_CRCI_NAND_CMD;
3025 cmd->src = paddr(&data->sfcmd[6]);
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;
3039 cmd->src = NAND_SFLASHC_STATUS;
3040 cmd->dst = paddr(&data->sfstat[6]);
3041 cmd->len = 4;
3042 cmd++;
3043
3044 /*************************************************************/
3045 /* Read necessary status registers from the onenand device */
3046 /*************************************************************/
3047
3048 /* Block on cmd ready and write CMD register */
3049 cmd->cmd = DST_CRCI_NAND_CMD;
3050 cmd->src = paddr(&data->sfcmd[7]);
3051 cmd->dst = NAND_SFLASHC_CMD;
3052 cmd->len = 4;
3053 cmd++;
3054
3055 /* Kick the execute command */
3056 cmd->cmd = 0;
3057 cmd->src = paddr(&data->sfexec);
3058 cmd->dst = NAND_SFLASHC_EXEC_CMD;
3059 cmd->len = 4;
3060 cmd++;
3061
3062 /* Block on data ready, and read the status register */
3063 cmd->cmd = SRC_CRCI_NAND_DATA;
3064 cmd->src = NAND_SFLASHC_STATUS;
3065 cmd->dst = paddr(&data->sfstat[7]);
3066 cmd->len = 4;
3067 cmd++;
3068
3069 /* Read the GENP3 register */
3070 cmd->cmd = 0;
3071 cmd->src = NAND_GENP_REG3;
3072 cmd->dst = paddr(&data->data3);
3073 cmd->len = 4;
3074 cmd++;
3075
3076 /* Read the DEVCMD4 register */
3077 cmd->cmd = 0;
3078 cmd->src = NAND_DEV_CMD4;
3079 cmd->dst = paddr(&data->data4);
3080 cmd->len = 4;
3081 cmd++;
3082
3083
3084 /*************************************************************/
3085 /* Restore the necessary registers to proper values */
3086 /*************************************************************/
3087
3088 /* Block on cmd ready and write CMD register */
3089 cmd->cmd = DST_CRCI_NAND_CMD;
3090 cmd->src = paddr(&data->sfcmd[8]);
3091 cmd->dst = NAND_SFLASHC_CMD;
3092 cmd->len = 4;
3093 cmd++;
3094
3095 /* Kick the execute command */
3096 cmd->cmd = 0;
3097 cmd->src = paddr(&data->sfexec);
3098 cmd->dst = NAND_SFLASHC_EXEC_CMD;
3099 cmd->len = 4;
3100 cmd++;
3101
3102 /* Block on data ready, and read the status register */
3103 cmd->cmd = SRC_CRCI_NAND_DATA | CMD_OCU | CMD_LC;
3104 cmd->src = NAND_SFLASHC_STATUS;
3105 cmd->dst = paddr(&data->sfstat[8]);
3106 cmd->len = 4;
3107 cmd++;
3108
3109
3110 ptr[0] = (paddr(cmdlist) >> 3) | CMD_PTR_LP;
3111
3112 dmov_exec_cmdptr(DMOV_NAND_CHAN, ptr);
3113
3114 ecc_status = (data->data3 >> 16) & 0x0000FFFF;
3115 interrupt_status = (data->data4 >> 0)&0x0000FFFF;
3116 controller_status = (data->data4 >> 16)&0x0000FFFF;
3117
3118#if VERBOSE
3119 dprintf(INFO, "\n%s: sflash status %x %x %x %x %x %x %x %x %x\n", __func__,
3120 data->sfstat[0],
3121 data->sfstat[1],
3122 data->sfstat[2],
3123 data->sfstat[3],
3124 data->sfstat[4],
3125 data->sfstat[5],
3126 data->sfstat[6],
3127 data->sfstat[7],
3128 data->sfstat[8]);
3129
3130 dprintf(INFO, "%s: controller_status = %x\n", __func__,
3131 controller_status);
3132 dprintf(INFO, "%s: interrupt_status = %x\n", __func__,
3133 interrupt_status);
3134 dprintf(INFO, "%s: ecc_status = %x\n", __func__,
3135 ecc_status);
3136#endif
3137 /* Check for errors, protection violations etc */
3138 if ((controller_status != 0)
3139 || (data->sfstat[5] & 0x110)
3140 || (data->sfstat[6] & 0x110)
3141 || (data->sfstat[7] & 0x110)
3142 || (data->sfstat[8] & 0x110)
3143 || ((data->sfstat[0] & 0x110) &&
3144 (addr))
3145 || ((data->sfstat[1] & 0x110) &&
3146 (addr))
3147 || ((data->sfstat[2] & 0x110) &&
3148 (addr))
3149 || ((data->sfstat[3] & 0x110) &&
3150 (addr))) {
3151 dprintf(CRITICAL, "%s: ECC/MPU/OP error\n", __func__);
3152 return -1;
3153 }
3154
3155
3156 return 0;
3157}
Shashank Mittald0c836d2009-11-20 10:31:18 -08003158
3159static int flash_onenand_mark_badblock(dmov_s *cmdlist, unsigned *ptrlist, unsigned page)
3160{
3161 memset(empty_buf,0,528);
3162 /* Going to first page of the block */
Channagoud Kadabibeb17d52011-03-25 17:14:00 +05303163 if(page & num_pages_per_blk_mask)
3164 page = page - (page & num_pages_per_blk_mask);
Shashank Mittald0c836d2009-11-20 10:31:18 -08003165 return _flash_onenand_write_page(cmdlist, ptrlist, page, empty_buf, 0, 1);
3166}
3167
3168static int flash_mark_badblock(dmov_s *cmdlist, unsigned *ptrlist, unsigned page)
3169{
3170 switch(flash_info.type) {
3171 case FLASH_8BIT_NAND_DEVICE:
3172 case FLASH_16BIT_NAND_DEVICE:
3173 return flash_nand_mark_badblock(cmdlist, ptrlist, page);
3174 case FLASH_ONENAND_DEVICE:
3175 return flash_onenand_mark_badblock(cmdlist, ptrlist, page);
3176 default:
3177 return -1;
3178 }
3179}
3180
3181
Channagoud Kadabi404a7062011-03-21 19:27:50 +05303182unsigned flash_ctrl_hwinfo(dmov_s *cmdlist, unsigned *ptrlist)
3183{
3184 dmov_s *cmd = cmdlist;
3185 unsigned *ptr = ptrlist;
3186 unsigned *data = ptrlist + 4;
3187
3188 unsigned rv;
3189
3190 data[0] = 0xeeeeeeee;
Channagoud Kadabi404a7062011-03-21 19:27:50 +05303191
Channagoud Kadabi690515d2011-06-29 21:50:27 +05303192 cmd[0].cmd = CMD_LC | CMD_OCB | CMD_OCU ;
Channagoud Kadabi404a7062011-03-21 19:27:50 +05303193 cmd[0].src = NAND_HW_INFO;
3194 cmd[0].dst = paddr(&data[0]);
3195 cmd[0].len = 4;
3196
Channagoud Kadabi404a7062011-03-21 19:27:50 +05303197 ptr[0] = (paddr(cmd) >> 3) | CMD_PTR_LP;
3198 dmov_exec_cmdptr(DMOV_NAND_CHAN, ptr);
3199 rv = data[0];
3200
3201 return rv;
3202}
3203
Shashank Mittalc20b5a12009-11-18 19:35:30 -08003204/* Wrapper functions */
3205static void flash_read_id(dmov_s *cmdlist, unsigned *ptrlist)
3206{
3207 int dev_found = 0;
3208 unsigned index;
3209
3210 // Try to read id
3211 flash_nand_read_id(cmdlist, ptrlist);
3212 // Check if we support the device
3213 for (index=1;
3214 index < (sizeof(supported_flash)/sizeof(struct flash_identification));
3215 index++)
3216 {
3217 if ((flash_info.id & supported_flash[index].mask) ==
3218 (supported_flash[index].flash_id &
3219 (supported_flash[index].mask))) {
3220 dev_found = 1;
3221 break;
3222 }
3223 }
3224
3225 if(!dev_found) {
3226 flash_onenand_read_id(cmdlist, ptrlist);
3227 for (index=1;
3228 index < (sizeof(supported_flash)/sizeof(struct flash_identification));
3229 index++)
3230 {
3231 if ((flash_info.id & supported_flash[index].mask) ==
3232 (supported_flash[index].flash_id &
3233 (supported_flash[index].mask))) {
3234 dev_found = 1;
3235 break;
3236 }
3237 }
3238 }
3239
3240
3241
3242 if(dev_found) {
3243 if (supported_flash[index].widebus)
3244 flash_info.type = FLASH_16BIT_NAND_DEVICE;
3245 else
3246 flash_info.type = FLASH_8BIT_NAND_DEVICE;
3247 if (supported_flash[index].onenand)
3248 flash_info.type = FLASH_ONENAND_DEVICE;
3249 flash_info.page_size = supported_flash[index].pagesize;
Shashank Mittaldcc2e352009-11-19 19:11:16 -08003250 flash_pagesize = flash_info.page_size;
Shashank Mittalc20b5a12009-11-18 19:35:30 -08003251 flash_info.block_size = supported_flash[index].blksize;
3252 flash_info.spare_size = supported_flash[index].oobsize;
3253 if (flash_info.block_size && flash_info.page_size)
3254 {
3255 flash_info.num_blocks = supported_flash[index].density;
Chandan Uddaraju40605112010-08-09 14:25:08 -07003256 flash_info.num_blocks /= (flash_info.block_size);
Shashank Mittalc20b5a12009-11-18 19:35:30 -08003257 }
3258 else
3259 {
3260 flash_info.num_blocks = 0;
3261 }
3262 ASSERT(flash_info.num_blocks);
Channagoud Kadabibeb17d52011-03-25 17:14:00 +05303263 // Use this for getting the next/current blocks
3264 num_pages_per_blk = flash_info.block_size / flash_pagesize;
3265 num_pages_per_blk_mask = num_pages_per_blk - 1;
Channagoud Kadabi404a7062011-03-21 19:27:50 +05303266 //Look for 8bit BCH ECC Nand, TODO: ECC Correctability >= 8
3267 if((flash_ctrl_hwinfo(cmdlist,ptrlist) == 0x307) && flash_info.id == 0x2600482c) {
3268 enable_bch_ecc = 1;
3269 }
Shashank Mittalc20b5a12009-11-18 19:35:30 -08003270 return;
3271 }
3272
3273 // Assume 8 bit nand device for backward compatability
3274 if (dev_found == 0) {
3275 dprintf(INFO, "Device not supported. Assuming 8 bit NAND device\n");
3276 flash_info.type = FLASH_8BIT_NAND_DEVICE;
3277 }
3278 dprintf(INFO, "nandid: 0x%x maker=0x%02x device=0x%02x page_size=%d\n",
3279 flash_info.id, flash_info.vendor, flash_info.device,
3280 flash_info.page_size);
3281 dprintf(INFO, " spare_size=%d block_size=%d num_blocks=%d\n",
3282 flash_info.spare_size, flash_info.block_size,
3283 flash_info.num_blocks);
3284}
3285
3286static int flash_erase_block(dmov_s *cmdlist, unsigned *ptrlist, unsigned page)
3287{
3288 switch(flash_info.type) {
3289 case FLASH_8BIT_NAND_DEVICE:
3290 case FLASH_16BIT_NAND_DEVICE:
3291 return flash_nand_erase_block(cmdlist, ptrlist, page);
3292 case FLASH_ONENAND_DEVICE:
3293 return flash_onenand_erase_block(cmdlist, ptrlist, page);
3294 default:
3295 return -1;
3296 }
3297}
3298
3299static int _flash_read_page(dmov_s *cmdlist, unsigned *ptrlist,
3300 unsigned page, void *_addr, void *_spareaddr)
3301{
3302 switch(flash_info.type) {
3303 case FLASH_8BIT_NAND_DEVICE:
3304 case FLASH_16BIT_NAND_DEVICE:
Chandan Uddaraju14e57eb2010-06-28 12:11:06 -07003305 if(interleaved_mode)
3306 return flash_nand_read_page_interleave(cmdlist, ptrlist, page, _addr, _spareaddr);
3307 else
Shashank Mittalc20b5a12009-11-18 19:35:30 -08003308 return _flash_nand_read_page(cmdlist, ptrlist, page, _addr, _spareaddr);
3309 case FLASH_ONENAND_DEVICE:
Shashank Mittalad3d05c2009-11-19 15:53:57 -08003310 return _flash_onenand_read_page(cmdlist, ptrlist, page, _addr, _spareaddr, 0);
Shashank Mittalc20b5a12009-11-18 19:35:30 -08003311 default:
3312 return -1;
3313 }
3314}
3315
Shashank Mittalad3d05c2009-11-19 15:53:57 -08003316static int _flash_block_isbad(dmov_s *cmdlist, unsigned *ptrlist, unsigned page)
3317{
3318 switch(flash_info.type) {
3319 case FLASH_8BIT_NAND_DEVICE:
3320 case FLASH_16BIT_NAND_DEVICE:
3321 return flash_nand_block_isbad(cmdlist, ptrlist, page);
3322 case FLASH_ONENAND_DEVICE:
3323 return flash_onenand_block_isbad(cmdlist, ptrlist, page);
3324 default:
3325 return -1;
3326 }
3327}
Shashank Mittalc20b5a12009-11-18 19:35:30 -08003328
3329static int _flash_write_page(dmov_s *cmdlist, unsigned *ptrlist,
3330 unsigned page, const void *_addr,
3331 const void *_spareaddr)
3332{
3333 switch(flash_info.type) {
3334 case FLASH_8BIT_NAND_DEVICE:
3335 case FLASH_16BIT_NAND_DEVICE:
Chandan Uddaraju14e57eb2010-06-28 12:11:06 -07003336 if(interleaved_mode)
3337 return flash_nand_write_page_interleave(cmdlist, ptrlist, page, _addr, _spareaddr, 0);
3338 else
Shashank Mittald0c836d2009-11-20 10:31:18 -08003339 return _flash_nand_write_page(cmdlist, ptrlist, page, _addr, _spareaddr, 0);
Shashank Mittalc20b5a12009-11-18 19:35:30 -08003340 case FLASH_ONENAND_DEVICE:
Shashank Mittald0c836d2009-11-20 10:31:18 -08003341 return _flash_onenand_write_page(cmdlist, ptrlist, page, _addr, _spareaddr, 0);
Shashank Mittalc20b5a12009-11-18 19:35:30 -08003342 default:
3343 return -1;
3344 }
3345}
3346
Dima Zavin03cf4312009-01-23 16:38:30 -08003347static unsigned *flash_ptrlist;
3348static dmov_s *flash_cmdlist;
Dima Zavin03cf4312009-01-23 16:38:30 -08003349
3350static struct ptable *flash_ptable = NULL;
3351
Dima Zavine5f64352009-03-02 16:04:20 -08003352void flash_init(void)
Dima Zavin03cf4312009-01-23 16:38:30 -08003353{
Dima Zavine5f64352009-03-02 16:04:20 -08003354 ASSERT(flash_ptable == NULL);
Dima Zavin03cf4312009-01-23 16:38:30 -08003355
3356 flash_ptrlist = memalign(32, 1024);
3357 flash_cmdlist = memalign(32, 1024);
Ajay Dudani232ce812009-12-02 00:14:11 -08003358 flash_data = memalign(32, 4096 + 128);
3359 flash_spare = memalign(32, 128);
Dima Zavin03cf4312009-01-23 16:38:30 -08003360
Dima Zavin03cf4312009-01-23 16:38:30 -08003361 flash_read_id(flash_cmdlist, flash_ptrlist);
Shashank Mittal83d16d02009-11-18 16:54:42 -08003362 if((FLASH_8BIT_NAND_DEVICE == flash_info.type)
3363 ||(FLASH_16BIT_NAND_DEVICE == flash_info.type)) {
Shashank Mittalc20b5a12009-11-18 19:35:30 -08003364 if(flash_nand_read_config(flash_cmdlist, flash_ptrlist)) {
Shashank Mittal83d16d02009-11-18 16:54:42 -08003365 dprintf(CRITICAL, "ERROR: could not read CFG0/CFG1 state\n");
3366 ASSERT(0);
3367 }
3368 }
Dima Zavin03cf4312009-01-23 16:38:30 -08003369}
3370
3371struct ptable *flash_get_ptable(void)
3372{
3373 return flash_ptable;
3374}
3375
Dima Zavine5f64352009-03-02 16:04:20 -08003376void flash_set_ptable(struct ptable *new_ptable)
3377{
3378 ASSERT(flash_ptable == NULL && new_ptable != NULL);
3379 flash_ptable = new_ptable;
3380}
3381
Dima Zavinca337f52009-03-02 16:41:44 -08003382struct flash_info *flash_get_info(void)
3383{
3384 return &flash_info;
3385}
3386
Dima Zavin03cf4312009-01-23 16:38:30 -08003387int flash_erase(struct ptentry *ptn)
3388{
3389 unsigned block = ptn->start;
3390 unsigned count = ptn->length;
3391
Shashank Mittal8e49dec2010-03-01 15:19:04 -08003392 set_nand_configuration(ptn->type);
Dima Zavin03cf4312009-01-23 16:38:30 -08003393 while(count-- > 0) {
Channagoud Kadabibeb17d52011-03-25 17:14:00 +05303394 if(flash_erase_block(flash_cmdlist, flash_ptrlist, block * num_pages_per_blk)) {
Dima Zavin03cf4312009-01-23 16:38:30 -08003395 dprintf(INFO, "cannot erase @ %d (bad block?)\n", block);
3396 }
3397 block++;
3398 }
3399 return 0;
3400}
3401
3402int flash_read_ext(struct ptentry *ptn, unsigned extra_per_page,
Shashank Mittalc20b5a12009-11-18 19:35:30 -08003403 unsigned offset, void *data, unsigned bytes)
Dima Zavin03cf4312009-01-23 16:38:30 -08003404{
Channagoud Kadabibeb17d52011-03-25 17:14:00 +05303405 unsigned page = (ptn->start * num_pages_per_blk) + (offset / flash_pagesize);
3406 unsigned lastpage = (ptn->start + ptn->length) * num_pages_per_blk;
Shashank Mittaldcc2e352009-11-19 19:11:16 -08003407 unsigned count = (bytes + flash_pagesize - 1 + extra_per_page) / (flash_pagesize + extra_per_page);
Dima Zavin03cf4312009-01-23 16:38:30 -08003408 unsigned *spare = (unsigned*) flash_spare;
3409 unsigned errors = 0;
3410 unsigned char *image = data;
Channagoud Kadabibeb17d52011-03-25 17:14:00 +05303411 unsigned current_block = (page - (page & num_pages_per_blk_mask)) / num_pages_per_blk;
Shashank Mittalad3d05c2009-11-19 15:53:57 -08003412 unsigned start_block = ptn->start;
3413 int result = 0;
3414 int isbad = 0;
Shashank Mittalfd1f04f2010-08-03 17:38:48 -07003415 int start_block_count = 0;
Dima Zavin03cf4312009-01-23 16:38:30 -08003416
Shashank Mittal8e49dec2010-03-01 15:19:04 -08003417 ASSERT(ptn->type == TYPE_APPS_PARTITION);
3418 set_nand_configuration(TYPE_APPS_PARTITION);
3419
Shashank Mittaldcc2e352009-11-19 19:11:16 -08003420 if(offset & (flash_pagesize - 1))
Dima Zavin03cf4312009-01-23 16:38:30 -08003421 return -1;
3422
Shashank Mittalfd1f04f2010-08-03 17:38:48 -07003423// Adjust page offset based on number of bad blocks from start to current page
3424 if (start_block < current_block)
3425 {
3426 start_block_count = (current_block - start_block);
3427 while (start_block_count && (start_block < (ptn->start + ptn->length))) {
Channagoud Kadabibeb17d52011-03-25 17:14:00 +05303428 isbad = _flash_block_isbad(flash_cmdlist, flash_ptrlist, start_block*num_pages_per_blk);
Shashank Mittalfd1f04f2010-08-03 17:38:48 -07003429 if (isbad)
Channagoud Kadabibeb17d52011-03-25 17:14:00 +05303430 page += num_pages_per_blk;
Shashank Mittalfd1f04f2010-08-03 17:38:48 -07003431 else
3432 start_block_count--;
3433 start_block++;
3434 }
Shashank Mittalad3d05c2009-11-19 15:53:57 -08003435 }
3436
Shashank Mittalfd1f04f2010-08-03 17:38:48 -07003437 while((page < lastpage) && !start_block_count) {
Dima Zavin03cf4312009-01-23 16:38:30 -08003438 if(count == 0) {
3439 dprintf(INFO, "flash_read_image: success (%d errors)\n", errors);
3440 return 0;
3441 }
3442
Shashank Mittalad3d05c2009-11-19 15:53:57 -08003443 result = _flash_read_page(flash_cmdlist, flash_ptrlist, page, image, spare);
3444
3445 if (result == -1) {
3446 // bad page, go to next page
3447 page++;
Dima Zavin03cf4312009-01-23 16:38:30 -08003448 errors++;
3449 continue;
3450 }
Shashank Mittalad3d05c2009-11-19 15:53:57 -08003451 else if (result == -2) {
3452 // bad block, go to next block same offset
Channagoud Kadabibeb17d52011-03-25 17:14:00 +05303453 page += num_pages_per_blk;
Shashank Mittalad3d05c2009-11-19 15:53:57 -08003454 errors++;
3455 continue;
3456 }
3457
3458 page++;
Shashank Mittaldcc2e352009-11-19 19:11:16 -08003459 image += flash_pagesize;
Dima Zavin03cf4312009-01-23 16:38:30 -08003460 memcpy(image, spare, extra_per_page);
3461 image += extra_per_page;
3462 count -= 1;
3463 }
3464
3465 /* could not find enough valid pages before we hit the end */
3466 dprintf(INFO, "flash_read_image: failed (%d errors)\n", errors);
3467 return 0xffffffff;
3468}
3469
3470int flash_write(struct ptentry *ptn, unsigned extra_per_page, const void *data,
3471 unsigned bytes)
3472{
Channagoud Kadabibeb17d52011-03-25 17:14:00 +05303473 unsigned page = ptn->start * num_pages_per_blk;
3474 unsigned lastpage = (ptn->start + ptn->length) * num_pages_per_blk;
Dima Zavin03cf4312009-01-23 16:38:30 -08003475 unsigned *spare = (unsigned*) flash_spare;
3476 const unsigned char *image = data;
Shashank Mittaldcc2e352009-11-19 19:11:16 -08003477 unsigned wsize = flash_pagesize + extra_per_page;
Dima Zavin03cf4312009-01-23 16:38:30 -08003478 unsigned n;
3479 int r;
3480
Shashank Mittal8e49dec2010-03-01 15:19:04 -08003481 if ((flash_info.type == FLASH_ONENAND_DEVICE) && (ptn->type == TYPE_MODEM_PARTITION))
3482 {
3483 dprintf(CRITICAL, "flash_write_image: feature not supported\n");
3484 return -1;
3485 }
3486
3487 set_nand_configuration(ptn->type);
Dima Zavin03cf4312009-01-23 16:38:30 -08003488 for(n = 0; n < 16; n++) spare[n] = 0xffffffff;
3489
3490 while(bytes > 0) {
3491 if(bytes < wsize) {
3492 dprintf(CRITICAL, "flash_write_image: image undersized (%d < %d)\n", bytes, wsize);
3493 return -1;
3494 }
3495 if(page >= lastpage) {
3496 dprintf(CRITICAL, "flash_write_image: out of space\n");
3497 return -1;
3498 }
3499
Channagoud Kadabibeb17d52011-03-25 17:14:00 +05303500 if((page & num_pages_per_blk_mask) == 0) {
Dima Zavin03cf4312009-01-23 16:38:30 -08003501 if(flash_erase_block(flash_cmdlist, flash_ptrlist, page)) {
Channagoud Kadabibeb17d52011-03-25 17:14:00 +05303502 dprintf(INFO, "flash_write_image: bad block @ %d\n", page / num_pages_per_blk);
3503 page += num_pages_per_blk;
Dima Zavin03cf4312009-01-23 16:38:30 -08003504 continue;
3505 }
3506 }
3507
3508 if(extra_per_page) {
Shashank Mittald0c836d2009-11-20 10:31:18 -08003509 r = _flash_write_page(flash_cmdlist, flash_ptrlist, page, image, image + flash_pagesize);
Dima Zavin03cf4312009-01-23 16:38:30 -08003510 } else {
Shashank Mittald0c836d2009-11-20 10:31:18 -08003511 r = _flash_write_page(flash_cmdlist, flash_ptrlist, page, image, spare);
Dima Zavin03cf4312009-01-23 16:38:30 -08003512 }
3513 if(r) {
3514 dprintf(INFO, "flash_write_image: write failure @ page %d (src %d)\n", page, image - (const unsigned char *)data);
Channagoud Kadabibeb17d52011-03-25 17:14:00 +05303515 image -= (page & num_pages_per_blk_mask) * wsize;
3516 bytes += (page & num_pages_per_blk_mask) * wsize;
3517 page &= ~num_pages_per_blk_mask;
Dima Zavin03cf4312009-01-23 16:38:30 -08003518 if(flash_erase_block(flash_cmdlist, flash_ptrlist, page)) {
3519 dprintf(INFO, "flash_write_image: erase failure @ page %d\n", page);
3520 }
Shashank Mittal8e49dec2010-03-01 15:19:04 -08003521 if (ptn->type != TYPE_MODEM_PARTITION) {
3522 flash_mark_badblock(flash_cmdlist, flash_ptrlist, page);
3523 }
Dima Zavin03cf4312009-01-23 16:38:30 -08003524 dprintf(INFO, "flash_write_image: restart write @ page %d (src %d)\n", page, image - (const unsigned char *)data);
Channagoud Kadabibeb17d52011-03-25 17:14:00 +05303525 page += num_pages_per_blk;
Dima Zavin03cf4312009-01-23 16:38:30 -08003526 continue;
3527 }
Shashank Mittald0c836d2009-11-20 10:31:18 -08003528 page++;
Dima Zavin03cf4312009-01-23 16:38:30 -08003529 image += wsize;
3530 bytes -= wsize;
3531 }
3532
3533 /* erase any remaining pages in the partition */
Channagoud Kadabibeb17d52011-03-25 17:14:00 +05303534 page = (page + num_pages_per_blk_mask) & (~num_pages_per_blk_mask);
Dima Zavin03cf4312009-01-23 16:38:30 -08003535 while(page < lastpage){
3536 if(flash_erase_block(flash_cmdlist, flash_ptrlist, page)) {
Channagoud Kadabibeb17d52011-03-25 17:14:00 +05303537 dprintf(INFO, "flash_write_image: bad block @ %d\n", page / num_pages_per_blk);
Dima Zavin03cf4312009-01-23 16:38:30 -08003538 }
Channagoud Kadabibeb17d52011-03-25 17:14:00 +05303539 page += num_pages_per_blk;
Dima Zavin03cf4312009-01-23 16:38:30 -08003540 }
3541
3542 dprintf(INFO, "flash_write_image: success\n");
3543 return 0;
3544}
3545
3546#if 0
3547static int flash_read_page(unsigned page, void *data, void *extra)
3548{
3549 return _flash_read_page(flash_cmdlist, flash_ptrlist,
3550 page, data, extra);
3551}
3552#endif
Shashank Mittaldcc2e352009-11-19 19:11:16 -08003553
3554unsigned flash_page_size(void)
3555{
3556 return flash_pagesize;
3557}
Chandan Uddaraju14e57eb2010-06-28 12:11:06 -07003558
3559void enable_interleave_mode(int status)
3560{
3561 interleaved_mode = status;
3562 if(status)
3563 {
3564 flash_pagesize *= 2;
3565 platform_config_interleaved_mode_gpios();
3566 }
3567 return;
3568}
Channagoud Kadabi404a7062011-03-21 19:27:50 +05303569
3570int flash_ecc_bch_enabled()
3571{
3572 return enable_bch_ecc;
3573}