blob: 6bb1f272afb92e9910e47e39f2b1d51c38ee5987 [file] [log] [blame]
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001/*
2 * Copyright (c) 2008, Google Inc.
3 * All rights reserved.
4 * Copyright (c) 2009-2012, The Linux Foundation. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in
12 * the documentation and/or other materials provided with the
13 * distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29#include <qpic_nand.h>
30#include <bam.h>
31#include <dev/flash.h>
32#include <lib/ptable.h>
33#include <debug.h>
34#include <string.h>
35#include <malloc.h>
36#include <sys/types.h>
Deepa Dinamani0bf2f442012-10-19 11:41:06 -070037#include <platform.h>
Amol Jadib726c3b2012-09-13 13:51:23 -070038#include <platform/clock.h>
Deepa Dinamanie4573be2012-08-03 16:32:29 -070039
40static uint32_t nand_base;
41static struct ptable *flash_ptable;
42static struct flash_info flash;
43static unsigned char *flash_spare_bytes;
44static uint32_t cfg0;
45static uint32_t cfg1;
46static uint32_t cfg0_raw;
47static uint32_t cfg1_raw;
48static uint32_t ecc_bch_cfg;
49
50struct cmd_element ce_array[100];
51
52#define QPIC_BAM_DATA_FIFO_SIZE 64
53#define QPIC_BAM_CMD_FIFO_SIZE 64
54
55static struct bam_desc cmd_desc_fifo[QPIC_BAM_CMD_FIFO_SIZE] __attribute__ ((aligned(BAM_DESC_SIZE)));
56static struct bam_desc data_desc_fifo[QPIC_BAM_DATA_FIFO_SIZE] __attribute__ ((aligned(BAM_DESC_SIZE)));
57
58static struct bam_instance bam;
59static uint8_t *bbtbl;
60
Deepa Dinamani0bf2f442012-10-19 11:41:06 -070061static uint8_t* rdwr_buf;
62
Deepa Dinamanie4573be2012-08-03 16:32:29 -070063static struct flash_id supported_flash[] = {
64 /* Flash ID ID Mask Density(MB) Wid Pgsz Blksz oobsz onenand Manuf */
65 {0x1590aa2c, 0xFFFFFFFF, (256 << 20), 0, 2048, (2048 << 6), 64, 0, 0}, /*Micr */
66 /* Note: Width flag is 0 for 8 bit Flash and 1 for 16 bit flash */
67 /* Note: Onenand flag is 0 for NAND Flash and 1 for OneNAND flash */
68};
69
70static nand_result_t
71qpic_nand_check_status(uint32_t status)
72{
73 /* Check for errors */
74 if (status & NAND_FLASH_ERR)
75 {
76 dprintf(CRITICAL, "Nand Flash error for Fetch id cmd. Status = %d\n",
77 status);
78 if (status & NAND_FLASH_TIMEOUT_ERR)
79 return NANDC_RESULT_TIMEOUT;
80 else
81 return NANDC_RESULT_FAILURE;
82 }
83 return NANDC_RESULT_SUCCESS;
84}
85
86static void
87qpic_nand_wait_for_cmd_exec(uint32_t num_desc)
88{
89 /* Create a read/write event to notify the periperal of the added desc. */
90 bam_sys_gen_event(&bam, CMD_PIPE_INDEX, num_desc);
91
92 /* Wait for the descriptors to be processed */
93 bam_wait_for_interrupt(&bam, CMD_PIPE_INDEX, P_PRCSD_DESC_EN_MASK);
94
95 /* Read offset update for the circular FIFO */
96 bam_read_offset_update(&bam, CMD_PIPE_INDEX);
97}
98
99static void
100qpic_nand_wait_for_data(uint32_t pipe_num)
101{
102 /* Wait for the descriptors to be processed */
103 bam_wait_for_interrupt(&bam, pipe_num, P_PRCSD_DESC_EN_MASK);
104
105 /* Read offset update for the circular FIFO */
106 bam_read_offset_update(&bam, pipe_num);
107}
108
109static uint32_t
110qpic_nand_read_reg(uint32_t reg_addr,
111 uint8_t flags,
112 struct cmd_element *cmd_list_ptr)
113{
114 uint32_t val;
115
Deepa Dinamani0bf2f442012-10-19 11:41:06 -0700116 bam_add_cmd_element(cmd_list_ptr, reg_addr, (uint32_t)PA((addr_t)&val), CE_READ_TYPE);
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700117
118 /* Enqueue the desc for the above command */
119 bam_add_one_desc(&bam,
120 CMD_PIPE_INDEX,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -0700121 (unsigned char*)PA((addr_t)cmd_list_ptr),
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700122 BAM_CE_SIZE,
123 BAM_DESC_CMD_FLAG| BAM_DESC_INT_FLAG | flags);
124
125 qpic_nand_wait_for_cmd_exec(1);
126
127 return val;
128}
129
130static uint32_t
131qpic_nand_fetch_id(struct flash_info *flash)
132{
133 struct cmd_element *cmd_list_ptr = ce_array;
134 struct cmd_element *cmd_list_ptr_start = ce_array;
135 int num_desc = 0;
136 uint32_t status;
137 uint32_t id;
138 uint32_t flash_cmd = NAND_CMD_FETCH_ID;
139 uint32_t exec_cmd = 1;
140 int nand_ret = NANDC_RESULT_SUCCESS;
141
142 /* Issue the Fetch id command to the NANDc */
143 bam_add_cmd_element(cmd_list_ptr, NAND_FLASH_CMD, (uint32_t)flash_cmd, CE_WRITE_TYPE);
144 cmd_list_ptr++;
145
146 /* Execute the cmd */
147 bam_add_cmd_element(cmd_list_ptr, NAND_EXEC_CMD, (uint32_t)exec_cmd, CE_WRITE_TYPE);
148 cmd_list_ptr++;
149
150 /* Prepare the cmd desc for the above commands */
151 bam_add_one_desc(&bam,
152 CMD_PIPE_INDEX,
153 (unsigned char*)cmd_list_ptr_start,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -0700154 PA((uint32_t)cmd_list_ptr - (uint32_t)cmd_list_ptr_start),
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700155 BAM_DESC_LOCK_FLAG | BAM_DESC_INT_FLAG |
156 BAM_DESC_NWD_FLAG | BAM_DESC_CMD_FLAG);
157
158 /* Keep track of the number of desc added. */
159 num_desc++;
160 qpic_nand_wait_for_cmd_exec(num_desc);
161
162 cmd_list_ptr_start = ce_array;
163 cmd_list_ptr = ce_array;
164
165 /* Read the status register */
166 status = qpic_nand_read_reg(NAND_FLASH_STATUS, 0, cmd_list_ptr);
167
168 /* Check for errors */
169 nand_ret = qpic_nand_check_status(status);
170 if (nand_ret)
171 {
172 dprintf( CRITICAL, "Read ID cmd status failed\n");
173 goto qpic_nand_fetch_id_err;
174 }
175
176 /* Read the id */
177 id = qpic_nand_read_reg(NAND_READ_ID, BAM_DESC_UNLOCK_FLAG, cmd_list_ptr);
178
179 flash->id = id;
180 flash->vendor = id & 0xff;
181 flash->device = (id >> 8) & 0xff;
182 flash->dev_cfg = (id >> 24) & 0xFF;
183 flash->widebus = 0;
184 flash->widebus &= (id >> 24) & 0xFF;
185 flash->widebus = flash->widebus? 1: 0;
186
187qpic_nand_fetch_id_err:
188 return nand_ret;
189}
190
191static int
192qpic_bam_init(uint32_t bam_base, struct qpic_nand_bam_pipes *pipes)
193{
194 uint32_t bam_ret = NANDC_RESULT_SUCCESS;
195
196 bam.base = bam_base;
197 /* Set Read pipe params. */
198 bam.pipe[DATA_PRODUCER_PIPE_INDEX].pipe_num = pipes->read_pipe;
199 /* System consumer */
200 bam.pipe[DATA_PRODUCER_PIPE_INDEX].trans_type = BAM2SYS;
201 bam.pipe[DATA_PRODUCER_PIPE_INDEX].fifo.size = QPIC_BAM_DATA_FIFO_SIZE;
202 bam.pipe[DATA_PRODUCER_PIPE_INDEX].fifo.head = data_desc_fifo;
203
204 /* Set Write pipe params. */
205 bam.pipe[DATA_CONSUMER_PIPE_INDEX].pipe_num = pipes->write_pipe;
206 /* System producer */
207 bam.pipe[DATA_CONSUMER_PIPE_INDEX].trans_type = SYS2BAM;
208 bam.pipe[DATA_CONSUMER_PIPE_INDEX].fifo.size = QPIC_BAM_DATA_FIFO_SIZE;
209 bam.pipe[DATA_CONSUMER_PIPE_INDEX].fifo.head = data_desc_fifo;
210
211 /* Set Cmd pipe params. */
212 bam.pipe[CMD_PIPE_INDEX].pipe_num = pipes->cmd_pipe;
213 /* System consumer */
214 bam.pipe[CMD_PIPE_INDEX].trans_type = BAM2SYS;
215 bam.pipe[CMD_PIPE_INDEX].fifo.size = QPIC_BAM_CMD_FIFO_SIZE;
216 bam.pipe[CMD_PIPE_INDEX].fifo.head = cmd_desc_fifo;
217
218 /* Programs the threshold for BAM transfer
219 * When this threshold is reached, BAM signals the peripheral via the pipe_bytes_available
220 * interface.
221 * The peripheral is signalled with this notification in the following cases:
222 * a. It has accumulated all the descriptors.
223 * b. It has accumulated more than threshold bytes.
224 * c. It has reached EOT (End Of Transfer).
225 * Note: this value needs to be set by the h/w folks and is specific for each peripheral.
226 */
227 bam.threshold = 32;
228
229 /* BAM Init. */
230 bam_init(&bam);
231
232 /* Initialize BAM QPIC read pipe */
233 bam_sys_pipe_init(&bam, DATA_PRODUCER_PIPE_INDEX);
234
235 /* Init read fifo */
236 bam_ret = bam_pipe_fifo_init(&bam, bam.pipe[DATA_PRODUCER_PIPE_INDEX].pipe_num);
237
238 if (bam_ret)
239 {
240 dprintf(CRITICAL, "QPIC:NANDc BAM Read FIFO init error\n");
241 bam_ret = NANDC_RESULT_FAILURE;
242 goto qpic_nand_bam_init_error;
243 }
244
245 /* Initialize BAM QPIC write pipe */
246 bam_sys_pipe_init(&bam, DATA_CONSUMER_PIPE_INDEX);
247
248 /* Init write fifo. Use the same fifo as read fifo. */
249 bam_ret = bam_pipe_fifo_init(&bam, bam.pipe[DATA_CONSUMER_PIPE_INDEX].pipe_num);
250
251 if (bam_ret)
252 {
253 dprintf(CRITICAL, "QPIC: NANDc: BAM Write FIFO init error\n");
254 bam_ret = NANDC_RESULT_FAILURE;
255 goto qpic_nand_bam_init_error;
256 }
257
258 /* Initialize BAM QPIC cmd pipe */
259 bam_sys_pipe_init(&bam, CMD_PIPE_INDEX);
260
261 /* Init cmd fifo */
262 bam_ret = bam_pipe_fifo_init(&bam, bam.pipe[CMD_PIPE_INDEX].pipe_num);
263
264 if (bam_ret)
265 {
266 dprintf(CRITICAL, "QPIC:NANDc BAM CMD FIFO init error\n");
267 bam_ret = NANDC_RESULT_FAILURE;
268 goto qpic_nand_bam_init_error;
269 }
270
271qpic_nand_bam_init_error:
272return bam_ret;
273}
274
275/* Adds command elements for addr and cfg register writes.
276 * cfg: Defines the configuration for the flash cmd.
277 * start: Address where the command elements are added.
278 *
279 * Returns the address where the next cmd element can be added.
280 */
281static struct cmd_element*
282qpic_nand_add_addr_n_cfg_ce(struct cfg_params *cfg,
283 struct cmd_element *start)
284{
285 struct cmd_element *cmd_list_ptr = start;
286
287 bam_add_cmd_element(cmd_list_ptr, NAND_ADDR0, (uint32_t)cfg->addr0, CE_WRITE_TYPE);
288 cmd_list_ptr++;
289 bam_add_cmd_element(cmd_list_ptr, NAND_ADDR1, (uint32_t)cfg->addr1, CE_WRITE_TYPE);
290 cmd_list_ptr++;
291 bam_add_cmd_element(cmd_list_ptr, NAND_DEV0_CFG0, (uint32_t)cfg->cfg0, CE_WRITE_TYPE);
292 cmd_list_ptr++;
293 bam_add_cmd_element(cmd_list_ptr, NAND_DEV0_CFG1, (uint32_t)cfg->cfg1, CE_WRITE_TYPE);
294 cmd_list_ptr++;
295
296 return cmd_list_ptr;
297}
298
299
300static struct cmd_element*
301qpic_nand_add_onfi_probe_ce(struct onfi_probe_params *params,
302 struct cmd_element *start)
303{
304 struct cmd_element *cmd_list_ptr = start;
305
306 cmd_list_ptr = qpic_nand_add_addr_n_cfg_ce(&params->cfg, cmd_list_ptr);
307
308 bam_add_cmd_element(cmd_list_ptr, NAND_DEV_CMD1, (uint32_t)params->dev_cmd1, CE_WRITE_TYPE);
309 cmd_list_ptr++;
310 bam_add_cmd_element(cmd_list_ptr, NAND_DEV_CMD_VLD, (uint32_t)params->vld, CE_WRITE_TYPE);
311 cmd_list_ptr++;
312 bam_add_cmd_element(cmd_list_ptr, NAND_READ_LOCATION_n(0), (uint32_t)params->cfg.addr_loc_0, CE_WRITE_TYPE);
313 cmd_list_ptr++;
314 bam_add_cmd_element(cmd_list_ptr, NAND_FLASH_CMD, (uint32_t)params->cfg.cmd, CE_WRITE_TYPE);
315 cmd_list_ptr++;
316 bam_add_cmd_element(cmd_list_ptr, NAND_EXEC_CMD, (uint32_t)params->cfg.exec, CE_WRITE_TYPE);
317 cmd_list_ptr++;
318
319 return cmd_list_ptr;
320}
321
322static int
323onfi_probe_cmd_exec(struct onfi_probe_params *params,
324 unsigned char* data_ptr,
325 int data_len)
326{
327 struct cmd_element *cmd_list_ptr = ce_array;
328 struct cmd_element *cmd_list_ptr_start = ce_array;
329 int num_desc = 0;
330 uint32_t status = 0;
331 int nand_ret = NANDC_RESULT_SUCCESS;
332 uint8_t desc_flags = BAM_DESC_NWD_FLAG | BAM_DESC_CMD_FLAG
333 | BAM_DESC_LOCK_FLAG | BAM_DESC_INT_FLAG;
334
335 params->cfg.addr_loc_0 = 0;
336 params->cfg.addr_loc_0 |= NAND_RD_LOC_LAST_BIT(1);
337 params->cfg.addr_loc_0 |= NAND_RD_LOC_OFFSET(0);
338 params->cfg.addr_loc_0 |= NAND_RD_LOC_SIZE(data_len);
339
340 cmd_list_ptr = qpic_nand_add_onfi_probe_ce(params, cmd_list_ptr);
341
342 /* Enqueue the desc for the above commands */
343 bam_add_one_desc(&bam,
344 CMD_PIPE_INDEX,
345 (unsigned char*)cmd_list_ptr_start,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -0700346 PA((addr_t)(uint32_t)cmd_list_ptr - (uint32_t)cmd_list_ptr_start),
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700347 desc_flags);
348
349 cmd_list_ptr_start = cmd_list_ptr;
350 num_desc++;
351
352 /* Add Data desc */
353 bam_add_desc(&bam,
354 DATA_PRODUCER_PIPE_INDEX,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -0700355 (unsigned char *)PA((addr_t)data_ptr),
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700356 data_len,
357 BAM_DESC_INT_FLAG);
358
359 /* Wait for the commands to be executed */
360 qpic_nand_wait_for_cmd_exec(num_desc);
361
362 /* Read buffer status and check for errors. */
363 status = qpic_nand_read_reg(NAND_FLASH_STATUS, 0, cmd_list_ptr++);
364
365 if (qpic_nand_check_status(status))
366 {
367 nand_ret = NANDC_RESULT_FAILURE;
368 goto onfi_probe_exec_err;
369 }
370
371 /* Wait for data to be available */
372 qpic_nand_wait_for_data(DATA_PRODUCER_PIPE_INDEX);
373
374 /* Check for errors */
375 nand_ret = qpic_nand_check_status(status);
376
377onfi_probe_exec_err:
378 return nand_ret;
379}
380
381/* TODO: check why both vld and cmd need to be written. */
382void
383qpic_nand_onfi_probe_cleanup(uint32_t vld, uint32_t dev_cmd1)
384{
385 struct cmd_element *cmd_list_ptr = ce_array;
386 struct cmd_element *cmd_list_ptr_start = ce_array;
387
388 bam_add_cmd_element(cmd_list_ptr, NAND_DEV_CMD1, dev_cmd1, CE_WRITE_TYPE);
389 cmd_list_ptr++;
390 bam_add_cmd_element(cmd_list_ptr, NAND_DEV_CMD_VLD, vld, CE_WRITE_TYPE);
391 cmd_list_ptr++;
392
393 /* Enqueue the desc for the above commands */
394 bam_add_one_desc(&bam,
395 CMD_PIPE_INDEX,
396 (unsigned char*)cmd_list_ptr_start,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -0700397 PA((uint32_t)cmd_list_ptr - (uint32_t)cmd_list_ptr_start),
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700398 BAM_DESC_UNLOCK_FLAG | BAM_DESC_CMD_FLAG| BAM_DESC_INT_FLAG);
399
400 qpic_nand_wait_for_cmd_exec(1);
401}
402
403static int
404qpic_nand_onfi_save_params(struct onfi_param_page *param_page, struct flash_info *flash)
405{
406 int onfi_ret = NANDC_RESULT_SUCCESS;
407 uint32_t ecc_bits;
408
409 onfi_ret = qpic_nand_fetch_id(flash);
410
411 if (onfi_ret)
412 {
413 dprintf(CRITICAL, "Fetch ID cmd failed\n");
414 goto onfi_save_params_err;
415 }
416
417 flash->page_size = param_page->data_per_pg;
418 flash->block_size = param_page->pgs_per_blk * flash->page_size;
419 flash->num_blocks = param_page->blks_per_LUN;
420 flash->widebus = param_page->feature_supported & 0x1;
421 flash->density = param_page->blks_per_LUN * flash->blksize;
422 flash->spare_size = param_page->spare_per_pg;
423 ecc_bits = param_page->num_bits_ecc_correctability;
424 flash->num_pages_per_blk = param_page->pgs_per_blk;
425 flash->num_pages_per_blk_mask = param_page->pgs_per_blk - 1;
426
427 if (ecc_bits >= 8)
428 flash->ecc_width = NAND_WITH_8_BIT_ECC;
429 else
430 flash->ecc_width = NAND_WITH_4_BIT_ECC;
431
432 onfi_save_params_err:
433 return onfi_ret;
434}
435
436static void
437qpic_nand_save_config(struct flash_info *flash)
438{
439
440 /* Save Configurations */
441 flash->cws_per_page = flash->page_size >> NAND_CW_DIV_RIGHT_SHIFT;
442
443 /* Codeword Size = UD_SIZE_BYTES + ECC_PARITY_SIZE_BYTES
444 * + SPARE_SIZE_BYTES + Bad Block size
445 */
446 if (flash->ecc_width & NAND_WITH_8_BIT_ECC)
447 {
448 flash->cw_size = NAND_CW_SIZE_8_BIT_ECC;
449 ecc_bch_cfg |= (1 << NAND_DEV0_ECC_MODE_SHIFT); /* Use 8-bit ecc */
450
451 if (flash->widebus)
452 {
453 cfg0 |= (0 << NAND_DEV0_CFG0_SPARE_SZ_BYTES_SHIFT); /* spare size bytes in each CW */
454 ecc_bch_cfg |= (14 << NAND_DEV0_ECC_PARITY_SZ_BYTES_SHIFT); /* parity bytes in each CW */
455 }
456 else
457 {
458 cfg0 |= (2 << NAND_DEV0_CFG0_SPARE_SZ_BYTES_SHIFT); /* spare size bytes in each CW */
459 ecc_bch_cfg |= (13 << NAND_DEV0_ECC_PARITY_SZ_BYTES_SHIFT); /* parity bytes in each CW */
460 }
461 }
462 else
463 {
464 flash->cw_size = NAND_CW_SIZE_4_BIT_ECC;
465
466 if (flash->widebus)
467 {
468 cfg0 |= (2 << NAND_DEV0_CFG0_SPARE_SZ_BYTES_SHIFT); /* spare size bytes in each CW */
469 ecc_bch_cfg |= (8 << NAND_DEV0_ECC_PARITY_SZ_BYTES_SHIFT); /* parity bytes in each CW */
470 }
471 else
472 {
473 cfg0 |= (4 << NAND_DEV0_CFG0_SPARE_SZ_BYTES_SHIFT); /* spare size bytes in each CW */
474 ecc_bch_cfg |= (7 << NAND_DEV0_ECC_PARITY_SZ_BYTES_SHIFT); /* parity bytes in each CW */
475 }
476 }
477
478 /* BAD_BLOCK_BYTE_NUM = Page Size -
479 * (CW_PER_PAGE * Codeword Size) + 1
480 * Note: Set CW_PER_PAGE to 1 less than the actual number.
481 */
482 flash->bad_blk_loc = flash->page_size - flash->cw_size * (flash->cws_per_page - 1) + 1;
483
484 cfg0 |= ((flash->cws_per_page - 1) << NAND_DEV0_CFG0_CW_PER_PAGE_SHIFT) /* 4/8 cw/pg for 2/4k */
485 |(DATA_BYTES_IN_IMG_PER_CW << NAND_DEV0_CFG0_UD_SIZE_BYTES_SHIFT) /* 516 user data bytes */
486 |(5 << NAND_DEV0_CFG0_ADDR_CYCLE_SHIFT) /* 5 address cycles */
487 |(0 << NAND_DEV0_CFG0_DIS_STS_AFTER_WR_SHIFT);/* Send read status cmd after each write. */
488
489 cfg1 |= (7 << NAND_DEV0_CFG1_RECOVERY_CYCLES_SHIFT) /* 8 recovery cycles */
490 |(0 << NAND_DEV0_CFG1_CS_ACTIVE_BSY_SHIFT) /* Allow CS deassertion */
491 |(flash->bad_blk_loc << NAND_DEV0_CFG1_BAD_BLK_BYTE_NUM_SHIFT)/* Bad block marker location */
492 |(0 << NAND_DEV0_CFG1_BAD_BLK_IN_SPARE_SHIFT) /* Bad block in user data area */
493 |(2 << NAND_DEV0_CFG1_WR_RD_BSY_GAP_SHIFT) /* 8 cycle tWB/tRB */
494 |(flash->widebus << NAND_DEV0_CFG1_WIDE_BUS_SHIFT); /* preserve wide flash flag */
495
496 cfg0_raw = ((flash->cws_per_page- 1) << NAND_DEV0_CFG0_CW_PER_PAGE_SHIFT)
497 |(5 << NAND_DEV0_CFG0_ADDR_CYCLE_SHIFT)
498 |(516 << NAND_DEV0_CFG0_UD_SIZE_BYTES_SHIFT) //figure out the size of cw
499 | (1 << NAND_DEV0_CFG0_DIS_STS_AFTER_WR_SHIFT);
500
501 cfg1_raw = (7 << NAND_DEV0_CFG1_RECOVERY_CYCLES_SHIFT)
502 | (0 << NAND_DEV0_CFG1_CS_ACTIVE_BSY_SHIFT)
503 | (17 << NAND_DEV0_CFG1_BAD_BLK_BYTE_NUM_SHIFT)
504 | (1 << NAND_DEV0_CFG1_BAD_BLK_IN_SPARE_SHIFT)
505 | (2 << NAND_DEV0_CFG1_WR_RD_BSY_GAP_SHIFT)
506 | (flash->widebus << NAND_DEV0_CFG1_WIDE_BUS_SHIFT)
507 |1 ; /* to disable reed solomon ecc..this feild is now read only. */
508
509 ecc_bch_cfg |= (0 << NAND_DEV0_ECC_DISABLE_SHIFT) /* Enable ECC */
510 | (0 << NAND_DEV0_ECC_SW_RESET_SHIFT) /* Put ECC core in op mode */
511 | (DATA_BYTES_IN_IMG_PER_CW << NAND_DEV0_ECC_NUM_DATA_BYTES)
512 | (1 << NAND_DEV0_ECC_FORCE_CLK_OPEN_SHIFT); /* Enable all clocks */
513}
514
515/* Onfi probe should issue the following commands to the flash device:
516 * 1. Read ID - with addr ONFI_READ_ID_ADDR.
517 * This returns the ONFI ASCII string indicating support for ONFI.
518 * 2. Read Prameter Page - with addr ONFI_READ_PARAM_PAGE_ADDR.
519 * This returns the params for the device.
520 * Each command inturn issues commands- ADDR0, ADDR1, chip_select,
521 * cfg0, cfg1, cmd_vld, dev_cmd1, read_loc0, flash, exec.
522 */
523static int
524qpic_nand_onfi_probe(struct flash_info *flash)
525{
526 struct onfi_probe_params params;
527 uint32_t vld;
528 uint32_t dev_cmd1;
529 unsigned char *buffer;
530 unsigned char onfi_str[4];
531 uint32_t *id;
532 struct onfi_param_page *param_page;
533 int onfi_ret = NANDC_RESULT_SUCCESS;
534
535 /* Allocate memory required to read the onfi param page */
536 buffer = (unsigned char*) malloc(ONFI_READ_PARAM_PAGE_BUFFER_SIZE);
537
538 /* Read the vld and dev_cmd1 registers before modifying */
539 vld = qpic_nand_read_reg(NAND_DEV_CMD_VLD, 0, ce_array);
540 dev_cmd1 = qpic_nand_read_reg(NAND_DEV_CMD1, 0, ce_array);
541
542 /* Initialize flash cmd */
543 params.cfg.cmd = NAND_CMD_PAGE_READ;
544 params.cfg.exec = 1;
545
546 /* Execute Read ID cmd */
547
548 /* Initialize the config */
549 params.cfg.cfg0 = NAND_CFG0_RAW_ONFI_ID;
550 params.cfg.cfg1 = NAND_CFG1_RAW_ONFI_ID;
551
552 /* Initialize the cmd and vld */
553 params.dev_cmd1 = (dev_cmd1 & 0xFFFFFF00) | ONFI_READ_ID_CMD;
554 params.vld = vld & 0xFFFFFFFE;
555
556 /* Initialize the address
557 * addr1 is not used bcos of the cfg.
558 */
559 params.cfg.addr0 = ONFI_READ_ID_ADDR;
560 params.cfg.addr1 = 0;
561
562 /* Lock the pipe and execute the cmd. */
563 onfi_ret = onfi_probe_cmd_exec(&params, onfi_str, ONFI_READ_ID_BUFFER_SIZE);
564 if (onfi_ret)
565 {
566 dprintf(CRITICAL, "ONFI Read id cmd failed\n");
567 goto qpic_nand_onfi_probe_err;
568 }
569
570 /* Write back vld and cmd and unlock the pipe. */
571 qpic_nand_onfi_probe_cleanup(vld, dev_cmd1);
572
573 /* Check for onfi string */
574 id = (uint32_t*)onfi_str;
575 if (*id != ONFI_SIGNATURE)
576 {
577 dprintf(CRITICAL, "Not an ONFI device\n");
578 /* Not an onfi device. Return error. */
579 onfi_ret = NANDC_RESULT_DEV_NOT_SUPPORTED;
580 goto qpic_nand_onfi_probe_err;
581 }
582
583 dprintf(INFO, "ONFI device found\n");
584 /* Now read the param page */
585 /* Initialize the config */
586 params.cfg.cfg0 = NAND_CFG0_RAW_ONFI_PARAM_PAGE;
587 params.cfg.cfg1 = NAND_CFG1_RAW_ONFI_PARAM_PAGE;
588
589 /* Initialize the cmd and vld */
590 params.dev_cmd1 = (dev_cmd1 & 0xFFFFFF00) | ONFI_READ_PARAM_PAGE_CMD;
591 params.vld = vld & 0xFFFFFFFE;
592
593 /* Initialize the address
594 * addr1 is not used bcos of the cfg.
595 */
596 params.cfg.addr0 = ONFI_READ_PARAM_PAGE_ADDR;
597 params.cfg.addr1 = 0;
598
599 /* Lock the pipe and execute the cmd. */
600 onfi_ret = onfi_probe_cmd_exec(&params, buffer, ONFI_READ_PARAM_PAGE_BUFFER_SIZE);
601 if (onfi_ret)
602 {
603 dprintf(CRITICAL, "ONFI Read param page failed\n");
604 goto qpic_nand_onfi_probe_err;
605 }
606
607 /* Write back vld and cmd and unlock the pipe. */
608 qpic_nand_onfi_probe_cleanup(vld, dev_cmd1);
609
610 /* Verify the integrity of the returned page */
611 param_page = (struct onfi_param_page*)buffer;
612
613 /* TODO: Add CRC check to validate the param page. */
614
615 /* Save the parameter values */
616 onfi_ret = qpic_nand_onfi_save_params(param_page, flash);
617
618qpic_nand_onfi_probe_err:
619 if (onfi_ret)
620 dprintf(CRITICAL, "ONFI probe failed\n");
621
622 free(buffer);
623
624 return onfi_ret;
625}
626
627/* Enquues a desc for a flash cmd with NWD flag set:
628 * cfg: Defines the configuration for the flash cmd.
629 * start: Address where the command elements are added.
630 *
631 * Returns the address where the next cmd element can be added.
632 */
633struct cmd_element*
634qpic_nand_add_cmd_ce(struct cfg_params *cfg,
635 struct cmd_element *start)
636{
637 struct cmd_element *cmd_list_ptr;
638
639 cmd_list_ptr = qpic_nand_add_addr_n_cfg_ce(cfg, start);
640
641 bam_add_cmd_element(cmd_list_ptr, NAND_FLASH_CMD, (uint32_t)cfg->cmd, CE_WRITE_TYPE);
642 cmd_list_ptr++;
643
644 bam_add_cmd_element(cmd_list_ptr, NAND_EXEC_CMD, (uint32_t)cfg->exec, CE_WRITE_TYPE);
645 cmd_list_ptr++;
646
647 return cmd_list_ptr;
648}
649
650/* Reads nand_flash_status and resets nand_flash_status and nand_read_status */
651struct cmd_element*
652qpic_nand_add_read_n_reset_status_ce(struct cmd_element *start,
653 uint32_t *flash_status_read,
654 uint32_t read_status)
655{
656 struct cmd_element *cmd_list_ptr = start;
657 uint32_t flash_status_reset;
658 uint32_t read_status_reset;
659
660 /* Read and reset the status registers. */
661 flash_status_reset = NAND_FLASH_STATUS_RESET;
662 read_status_reset = NAND_READ_STATUS_RESET;
663
Deepa Dinamani0bf2f442012-10-19 11:41:06 -0700664 bam_add_cmd_element(cmd_list_ptr, NAND_FLASH_STATUS, (uint32_t)PA((addr_t)flash_status_read), CE_READ_TYPE);
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700665 cmd_list_ptr++;
666 bam_add_cmd_element(cmd_list_ptr, NAND_FLASH_STATUS, (uint32_t)flash_status_reset, CE_WRITE_TYPE);
667 cmd_list_ptr++;
668
669 if (read_status)
670 {
671 bam_add_cmd_element(cmd_list_ptr, NAND_READ_STATUS, (uint32_t)read_status_reset, CE_WRITE_TYPE);
672 cmd_list_ptr++;
673 }
674
675 return cmd_list_ptr;
676}
677
678struct cmd_element*
679qpic_nand_add_isbad_cmd_ce(struct cfg_params *cfg,
680 struct cmd_element *start)
681{
682 struct cmd_element *cmd_list_ptr = start;
683
684 bam_add_cmd_element(cmd_list_ptr, NAND_DEV0_ECC_CFG, (uint32_t)cfg->ecc_cfg, CE_WRITE_TYPE);
685 cmd_list_ptr++;
686
687 bam_add_cmd_element(cmd_list_ptr, NAND_READ_LOCATION_n(0), (uint32_t)cfg->addr_loc_0, CE_WRITE_TYPE);
688 cmd_list_ptr++;
689
690 cmd_list_ptr = qpic_nand_add_cmd_ce(cfg, cmd_list_ptr);
691
692 return cmd_list_ptr;
693}
694
695static int
696qpic_nand_block_isbad_exec(struct cfg_params *params,
697 uint8_t *bad_block)
698{
699
700 struct cmd_element *cmd_list_ptr = ce_array;
701 struct cmd_element *cmd_list_ptr_start = ce_array;
702 uint8_t desc_flags = BAM_DESC_NWD_FLAG | BAM_DESC_CMD_FLAG
703 | BAM_DESC_LOCK_FLAG | BAM_DESC_INT_FLAG;
704 int num_desc = 0;
705 uint32_t status = 0;
706 int nand_ret = NANDC_RESULT_SUCCESS;
707
708 cmd_list_ptr = qpic_nand_add_isbad_cmd_ce(params, cmd_list_ptr);
709
710 /* Enqueue the desc for the above commands */
711 bam_add_one_desc(&bam,
712 CMD_PIPE_INDEX,
713 (unsigned char*)cmd_list_ptr_start,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -0700714 PA((uint32_t)cmd_list_ptr - (uint32_t)cmd_list_ptr_start),
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700715 desc_flags);
716
717 num_desc++;
718
719 /* Add Data desc */
720 bam_add_desc(&bam,
721 DATA_PRODUCER_PIPE_INDEX,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -0700722 (unsigned char *)PA((addr_t)bad_block),
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700723 4,
724 BAM_DESC_INT_FLAG);
725
726 qpic_nand_wait_for_cmd_exec(num_desc);
727
728 status = qpic_nand_read_reg(NAND_FLASH_STATUS, BAM_DESC_UNLOCK_FLAG, cmd_list_ptr);
729
730 if ((nand_ret = qpic_nand_check_status(status)))
731 return NANDC_RESULT_FAILURE;
732
733 qpic_nand_wait_for_data(DATA_PRODUCER_PIPE_INDEX);
734
735 return nand_ret;
736}
737
738static int
739qpic_nand_block_isbad(unsigned block)
740{
741 unsigned cwperpage;
742 struct cfg_params params;
743 uint8_t bad_block[4];
744 unsigned nand_ret = NANDC_RESULT_SUCCESS;
745
746 if (bbtbl[block] == NAND_BAD_BLK_VALUE_IS_GOOD)
747 return NANDC_RESULT_SUCCESS;
748 else if (bbtbl[block] == NAND_BAD_BLK_VALUE_IS_BAD)
749 return NANDC_RESULT_BAD_BLOCK;
750 else
751 {
752 /* Read the bad block value from the flash.
753 * Bad block value is stored in the first page of the block.
754 */
755 /* Read the first page in the block. */
756 cwperpage = flash.cws_per_page;
757
758 /* Read page cmd */
759 params.cmd = NAND_CMD_PAGE_READ;
760 /* Clear the CW per page bits */
761 params.cfg0 = cfg0_raw & ~(7U << NAND_DEV0_CFG0_CW_PER_PAGE_SHIFT);
762 params.cfg1 = cfg1_raw;
763 /* addr0 - Write column addr + few bits in row addr upto 32 bits.
764 * Figure out the bad block status offset.
765 */
766 if (flash.widebus)
767 {
768 if (flash.ecc_width == NAND_WITH_8_BIT_ECC)
769 params.addr0 = ((block << 16) | ((532 * (cwperpage - 1)) >> 1));
770 else
771 params.addr0 = ((block << 16) | ((528 * (cwperpage - 1)) >> 1));
772 }
773 else
774 {
775 if (flash.ecc_width == NAND_WITH_8_BIT_ECC)
776 params.addr0 = (block << 16) | (532 * (cwperpage - 1));
777 else
778 params.addr0 = (block << 16) | (528 * (cwperpage - 1));
779 }
780
781 /* addr1 - Write rest of row addr.
782 * This will be all 0s.
783 */
784 params.addr1 = (block >> 16) & 0xff;
785 params.addr_loc_0 = NAND_RD_LOC_OFFSET(0);
786 params.addr_loc_0 |= NAND_RD_LOC_LAST_BIT(1);
787 params.addr_loc_0 |= NAND_RD_LOC_SIZE(4); /* Read 4 bytes */
788 params.ecc_cfg = ecc_bch_cfg & 0xFFFFFFFE; /* Disable ECC */
789 params.exec = 1;
790
791 if (qpic_nand_block_isbad_exec(&params, bad_block))
792 {
793 dprintf(CRITICAL,
794 "Could not read bad block value\n");
795 return NANDC_RESULT_FAILURE;
796 }
797
798 if (flash.widebus)
799 {
800 if (bad_block[0] != 0xFF && bad_block[1] != 0xFF)
801 {
802 bbtbl[block] = NAND_BAD_BLK_VALUE_IS_BAD;
803 nand_ret = NANDC_RESULT_BAD_BLOCK;
804 }
805 }
806 else if (bad_block[0] != 0xFF)
807 {
808 bbtbl[block] = NAND_BAD_BLK_VALUE_IS_BAD;
809 nand_ret = NANDC_RESULT_BAD_BLOCK;
810 }
811 else
812 bbtbl[block] = NAND_BAD_BLK_VALUE_IS_GOOD;
813
814 return nand_ret;
815 }
816}
817
818/* Function to erase a block on the nand.
819 * page: Starting page address for the block.
820 */
821static int
822qpic_nand_blk_erase(uint32_t page)
823{
824 struct cfg_params cfg;
825 struct cmd_element *cmd_list_ptr = ce_array;
826 struct cmd_element *cmd_list_ptr_start = ce_array;
827 uint32_t status;
828 int num_desc = 0;
829 uint32_t blk_addr = page / flash.num_pages_per_blk;
830
831 /* Erase only if the block is not bad */
832 if (qpic_nand_block_isbad(blk_addr))
833 {
834 dprintf(CRITICAL,
835 "NAND Erase error: Block address belongs to bad block: %d\n",
836 blk_addr);
837 return NANDC_RESULT_FAILURE;
838 }
839
840 /* Fill in params for the erase flash cmd */
841 cfg.addr0 = page;
842 cfg.addr1 = 0;
843 /* Clear CW_PER_PAGE in cfg0 */
844 cfg.cfg0 = cfg0 & ~(7U << NAND_DEV0_CFG0_CW_PER_PAGE_SHIFT);
845 cfg.cfg1 = cfg1;
846 cfg.cmd = NAND_CMD_BLOCK_ERASE;
847 cfg.exec = 1;
848
849 cmd_list_ptr = qpic_nand_add_cmd_ce(&cfg, cmd_list_ptr);
850
851 /* Enqueue the desc for the above commands */
852 bam_add_one_desc(&bam,
853 CMD_PIPE_INDEX,
854 (unsigned char*)cmd_list_ptr_start,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -0700855 PA((uint32_t)cmd_list_ptr - (uint32_t)cmd_list_ptr_start),
Deepa Dinamani2467bbb2012-10-02 13:59:58 -0700856 BAM_DESC_NWD_FLAG | BAM_DESC_CMD_FLAG | BAM_DESC_INT_FLAG | BAM_DESC_LOCK_FLAG);
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700857
858 cmd_list_ptr_start = cmd_list_ptr;
859 num_desc++;
860
861 qpic_nand_wait_for_cmd_exec(num_desc);
862
863 status = qpic_nand_read_reg(NAND_FLASH_STATUS, 0, cmd_list_ptr);
864
865 cmd_list_ptr++;
866 cmd_list_ptr_start = cmd_list_ptr;
867
868 /* QPIC controller automatically sends
869 * GET_STATUS cmd to the nand card because
870 * of the configuration programmed.
871 * Read the result of GET_STATUS cmd.
872 */
873 cmd_list_ptr = qpic_nand_add_read_n_reset_status_ce(cmd_list_ptr, &status, 1);
874
875 /* Enqueue the desc for the above commands */
876 bam_add_one_desc(&bam,
877 CMD_PIPE_INDEX,
878 (unsigned char*)cmd_list_ptr_start,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -0700879 PA((uint32_t)cmd_list_ptr - (uint32_t)cmd_list_ptr_start),
Deepa Dinamani2467bbb2012-10-02 13:59:58 -0700880 BAM_DESC_INT_FLAG | BAM_DESC_CMD_FLAG | BAM_DESC_UNLOCK_FLAG) ;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700881
882 num_desc = 1;
883 qpic_nand_wait_for_cmd_exec(num_desc);
884
885 /* Check for status errors*/
886 if (qpic_nand_check_status(status))
887 {
888 dprintf(CRITICAL,
889 "NAND Erase error: Block address belongs to bad block: %d\n",
890 blk_addr);
891 return NANDC_RESULT_FAILURE;
892 }
893
894 /* Check for PROG_ERASE_OP_RESULT bit for the result of erase operation. */
Deepa Dinamani2467bbb2012-10-02 13:59:58 -0700895 if (!(status & PROG_ERASE_OP_RESULT))
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700896 return NANDC_RESULT_SUCCESS;
897
898 return NANDC_RESULT_FAILURE;
899}
900
901/* Return num of desc added. */
902static int
903qpic_nand_add_wr_page_cws_cmd_desc(struct cfg_params *cfg,
904 uint32_t status[],
905 enum nand_cfg_value cfg_mode)
906{
907 struct cmd_element *cmd_list_ptr = ce_array;
908 struct cmd_element *cmd_list_ptr_start = ce_array;
909 uint32_t ecc;
910 int num_desc = 0;
911 int int_flag = 0;
912
913 if (cfg_mode == NAND_CFG)
914 ecc = ecc_bch_cfg;
915 else
916 ecc = ecc_bch_cfg & 0xFFFFFFFE; /* Disable ECC */
917
918 /* Add ECC configuration */
919 bam_add_cmd_element(cmd_list_ptr, NAND_DEV0_ECC_CFG,
920 (uint32_t)ecc, CE_WRITE_TYPE);
921 cmd_list_ptr++;
922 cmd_list_ptr = qpic_nand_add_addr_n_cfg_ce(cfg, cmd_list_ptr);
923
924 bam_add_cmd_element(cmd_list_ptr, NAND_FLASH_CMD,
925 (uint32_t)cfg->cmd, CE_WRITE_TYPE);
926 cmd_list_ptr++;
927
928 /* Enqueue the desc for the above commands */
929 bam_add_one_desc(&bam,
930 CMD_PIPE_INDEX,
931 (unsigned char*)cmd_list_ptr_start,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -0700932 PA((uint32_t)cmd_list_ptr - (uint32_t)cmd_list_ptr_start),
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700933 BAM_DESC_CMD_FLAG | BAM_DESC_LOCK_FLAG);
934
935 num_desc++;
936
937 /* Add CE for all the CWs */
938 for (unsigned i = 0; i < flash.cws_per_page; i++)
939 {
940 cmd_list_ptr_start = cmd_list_ptr;
941
942 bam_add_cmd_element(cmd_list_ptr, NAND_EXEC_CMD, (uint32_t)cfg->exec, CE_WRITE_TYPE);
943 cmd_list_ptr++;
944
945 /* Enqueue the desc for the above commands */
946 bam_add_one_desc(&bam,
947 CMD_PIPE_INDEX,
948 (unsigned char*)cmd_list_ptr_start,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -0700949 PA((uint32_t)cmd_list_ptr - (uint32_t)cmd_list_ptr_start),
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700950 BAM_DESC_NWD_FLAG | BAM_DESC_CMD_FLAG);
951
952 num_desc++;
953 cmd_list_ptr_start = cmd_list_ptr;
954
955 /* Set interrupt bit only for the last CW */
956 if (i == flash.cws_per_page - 1)
957 {
958 cmd_list_ptr = qpic_nand_add_read_n_reset_status_ce(cmd_list_ptr,
959 &status[i],
960 1);
961 int_flag = BAM_DESC_INT_FLAG | BAM_DESC_UNLOCK_FLAG;
962 }
963 else
964 cmd_list_ptr = qpic_nand_add_read_n_reset_status_ce(cmd_list_ptr,
965 &status[i],
966 0);
967
968 /* Enqueue the desc for the above commands */
969 bam_add_one_desc(&bam,
970 CMD_PIPE_INDEX,
971 (unsigned char*)cmd_list_ptr_start,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -0700972 PA((uint32_t)cmd_list_ptr - (uint32_t)cmd_list_ptr_start),
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700973 int_flag | BAM_DESC_CMD_FLAG);
974 num_desc++;
975 }
976 return num_desc;
977}
978
979void
980qpic_add_wr_page_cws_data_desc(const void *buffer,
981 enum nand_cfg_value cfg_mode,
982 const void *spareaddr)
983{
984 int len;
985 int flags;
986 uint32_t start;
987 unsigned num_desc = 0;
988
989 for( unsigned i = 0; i < flash.cws_per_page; i++)
990 {
991 flags = 0;
992
993 /* Set the interrupt flag on the last CW write for the page. */
994 if( i == flash.cws_per_page - 1)
995 flags |= BAM_DESC_INT_FLAG;
996
997 if (cfg_mode != NAND_CFG_RAW)
998 {
999 start = (uint32_t)buffer + i * DATA_BYTES_IN_IMG_PER_CW;
1000
1001 if (i < (flash.cws_per_page - 1))
1002 {
1003 len = DATA_BYTES_IN_IMG_PER_CW;
1004 flags |= BAM_DESC_EOT_FLAG;
1005 }
1006 else
1007 {
1008 /* Allow space for spare bytes in the last page */
1009 len = USER_DATA_BYTES_PER_CW - ((flash.cws_per_page - 1) << 2);
1010 flags = 0;
1011 }
1012 }
1013 else
1014 {
1015 start = (uint32_t)buffer;
1016 len = flash.cw_size;
1017 flags |= BAM_DESC_EOT_FLAG;
1018 }
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001019 bam_add_one_desc(&bam, DATA_CONSUMER_PIPE_INDEX, (unsigned char*)PA(start), len, flags);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001020 num_desc++;
1021
1022 if ((i == (flash.cws_per_page - 1)) && (cfg_mode == NAND_CFG))
1023 {
1024 /* write extra data */
1025 start = (uint32_t)spareaddr;
1026 len = (flash.cws_per_page << 2);
1027 flags = BAM_DESC_EOT_FLAG | BAM_DESC_INT_FLAG;
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001028 bam_add_one_desc(&bam, DATA_CONSUMER_PIPE_INDEX, (unsigned char*)PA(start), len, flags);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001029 num_desc++;
1030 }
1031 }
1032
1033 bam_sys_gen_event(&bam, DATA_CONSUMER_PIPE_INDEX, num_desc);
1034}
1035
1036static nand_result_t
1037qpic_nand_write_page(uint32_t pg_addr,
1038 enum nand_cfg_value cfg_mode,
1039 const void* buffer,
1040 const void* spareaddr)
1041{
1042 struct cfg_params cfg;
1043 uint32_t status[4];
1044 int num_cmd_desc = 0;
1045 int nand_ret = NANDC_RESULT_SUCCESS;
1046
1047 if (cfg_mode == NAND_CFG_RAW)
1048 {
1049 cfg.cfg0 = cfg0_raw;
1050 cfg.cfg1 = cfg1_raw;
1051 }
1052 else
1053 {
1054 cfg.cfg0 = cfg0;
1055 cfg.cfg1 = cfg1;
1056 }
1057
1058 cfg.cmd = NAND_CMD_PRG_PAGE;
1059 cfg.exec = 1;
1060
1061 cfg.addr0 = pg_addr << 16;
1062 cfg.addr1 = (pg_addr >> 16) & 0xff;
1063
1064 num_cmd_desc = qpic_nand_add_wr_page_cws_cmd_desc(&cfg, status, cfg_mode);
1065
1066 qpic_add_wr_page_cws_data_desc(buffer, cfg_mode, spareaddr);
1067
1068 /* Wait for the commands to be executed */
1069 qpic_nand_wait_for_cmd_exec(num_cmd_desc);
1070
1071 /* Check for errors */
1072 for(unsigned i = 0; i < flash.cws_per_page; i++)
1073 {
1074 nand_ret = qpic_nand_check_status(status[i]);
1075 if (nand_ret)
1076 {
1077 dprintf(CRITICAL,
1078 "Failed to write CW %d for page: %d\n",
1079 i, pg_addr);
1080 break;
1081 }
1082 }
1083
1084 /* Wait for data to be available */
1085 qpic_nand_wait_for_data(DATA_CONSUMER_PIPE_INDEX);
1086
1087 return nand_ret;
1088}
1089
1090static int
1091qpic_nand_mark_badblock(uint32_t page)
1092{
1093 char empty_buf[NAND_CW_SIZE_8_BIT_ECC];
1094
1095 memset(empty_buf, 0, NAND_CW_SIZE_8_BIT_ECC);
1096
1097 /* Going to first page of the block */
1098 if (page & flash.num_pages_per_blk_mask)
1099 page = page - (page & flash.num_pages_per_blk_mask);
1100
1101 return qpic_nand_write_page(page, NAND_CFG_RAW, empty_buf, 0);
1102}
1103
1104static void
1105qpic_nand_non_onfi_probe(struct flash_info *flash)
1106{
1107 int dev_found = 0;
1108 unsigned index;
1109 uint32_t ecc_bits;
1110
1111 /* Read the nand id. */
1112 qpic_nand_fetch_id(flash);
1113
1114 /* Check if we support the device */
1115 for (index = 1; index < (ARRAY_SIZE(supported_flash)); index++)
1116 {
1117 if ((flash->id & supported_flash[index].mask) ==
1118 (supported_flash[index].flash_id & (supported_flash[index].mask)))
1119 {
1120 dev_found = 1;
1121 break;
1122 }
1123 }
1124
1125 if (dev_found)
1126 {
1127 flash->page_size = supported_flash[index].pagesize;
1128 flash->block_size = supported_flash[index].blksize;
1129 flash->spare_size = supported_flash[index].oobsize;
1130 ecc_bits = supported_flash[index].ecc_8_bits;
1131
1132 /* Make sure that the block size and page size are defined. */
1133 ASSERT(flash->block_size);
1134 ASSERT(flash->page_size);
1135
1136 flash->num_blocks = supported_flash[index].density;
1137 flash->num_blocks /= (flash->block_size);
1138 flash->num_pages_per_blk = flash->block_size / flash->page_size;
1139 flash->num_pages_per_blk_mask = flash->num_pages_per_blk - 1;
1140
1141 /* Look for 8bit BCH ECC Nand, TODO: ECC Correctability >= 8 */
1142 if (ecc_bits)
1143 flash->ecc_width = NAND_WITH_8_BIT_ECC;
1144 else
1145 flash->ecc_width = NAND_WITH_4_BIT_ECC;
1146
1147 flash->density = supported_flash[index].density;
1148 flash->widebus = supported_flash[index].widebus;
1149
1150 return;
1151 }
1152
1153 /* Flash device is not supported, print flash device info and halt */
1154 if (dev_found == 0)
1155 {
1156 dprintf(CRITICAL, "NAND device is not supported: nandid: 0x%x"
1157 "maker=0x%02x device=0x%02x\n",
1158 flash->id,
1159 flash->vendor,
1160 flash->device);
1161 ASSERT(0);
1162 }
1163
1164 dprintf(INFO, "nandid: 0x%x maker=0x%02x device=0x%02x page_size=%d\n",
1165 flash->id,
1166 flash->vendor,
1167 flash->device,
1168 flash->page_size);
1169
1170 dprintf(INFO, "spare_size=%d block_size=%d num_blocks=%d\n",
1171 flash->spare_size,
1172 flash->block_size,
1173 flash->num_blocks);
1174}
1175
1176void
1177qpic_nand_init(struct qpic_nand_init_config *config)
1178{
1179 uint32_t i;
1180 int nand_ret;
1181
Amol Jadib726c3b2012-09-13 13:51:23 -07001182 qpic_nand_clock_init();
1183
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001184 nand_base = config->nand_base;
1185
1186 qpic_bam_init(config->bam_base, &(config->pipes));
1187
1188 /* Do an ONFI probe. */
1189 nand_ret = qpic_nand_onfi_probe(&flash);
1190
1191 if (nand_ret == NANDC_RESULT_DEV_NOT_SUPPORTED)
1192 {
1193 /* Not an ONFI Device.
1194 * Check if it is one of the devices we support.
1195 */
1196 qpic_nand_non_onfi_probe(&flash);
1197
1198 }
1199
1200 /* Save the RAW and read/write configs */
1201 qpic_nand_save_config(&flash);
1202
1203 flash_spare_bytes = (unsigned char *)malloc(flash.spare_size);
1204
1205 if (flash_spare_bytes == NULL)
1206 {
1207 dprintf(CRITICAL, "Failed to allocate memory for spare bytes\n");
1208 return;
1209 }
1210
1211 /* Create a bad block table */
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001212 bbtbl = (uint8_t *) malloc(sizeof(uint8_t) * flash.num_blocks);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001213
1214 if (bbtbl == NULL)
1215 {
1216 dprintf(CRITICAL, "Failed to allocate memory for bad block table\n");
1217 return;
1218 }
1219
1220 for (i = 0; i < flash.num_blocks; i++)
1221 bbtbl[i] = NAND_BAD_BLK_VALUE_NOT_READ;
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001222
1223 /* Set aside contiguous memory for reads/writes.
1224 * This is needed as the BAM transfers only work with
1225 * physically contiguous buffers.
1226 * We will copy any data to be written/ to be read from
1227 * nand to this buffer and this buffer will be submitted to BAM.
1228 */
1229 rdwr_buf = (uint8_t*) malloc(flash.page_size + flash.spare_size);
1230
1231 if (rdwr_buf == NULL)
1232 {
1233 dprintf(CRITICAL, "Failed to allocate memory for page reads or writes\n");
1234 return;
1235 }
1236
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001237}
1238
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -07001239unsigned
1240flash_page_size(void)
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001241{
1242 return flash.page_size;
1243}
1244
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -07001245unsigned
1246flash_block_size(void)
1247{
1248 return flash.block_size;
1249}
1250
Deepa Dinamani8e6b2432012-10-17 17:12:44 -07001251unsigned
1252flash_num_blocks(void)
1253{
1254 return flash.num_blocks;
1255}
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -07001256
1257struct ptable *
1258flash_get_ptable(void)
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001259{
1260 return flash_ptable;
1261}
1262
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -07001263void
Deepa Dinamani87feab82012-10-04 14:28:05 -07001264qpic_nand_uninit()
1265{
1266 bam_pipe_reset(&bam, DATA_PRODUCER_PIPE_INDEX);
1267 bam_pipe_reset(&bam, DATA_CONSUMER_PIPE_INDEX);
1268 bam_pipe_reset(&bam, CMD_PIPE_INDEX);
1269
1270}
1271void
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -07001272flash_set_ptable(struct ptable *new_ptable)
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001273{
1274 ASSERT(flash_ptable == NULL && new_ptable != NULL);
1275 flash_ptable = new_ptable;
1276}
1277
1278/* Note: No support for raw reads. */
1279static int
1280qpic_nand_read_page(uint32_t page, unsigned char* buffer, unsigned char* spareaddr)
1281{
1282 struct cfg_params params;
1283 uint32_t ecc;
1284 uint32_t flash_sts[4];
1285 uint32_t buffer_sts[4];
1286 uint32_t addr_loc_0;
1287 uint32_t addr_loc_1;
1288 struct cmd_element *cmd_list_ptr = ce_array;
1289 struct cmd_element *cmd_list_ptr_start = ce_array;
1290 uint32_t num_cmd_desc = 0;
1291 uint32_t num_data_desc = 0;
1292 uint32_t status;
1293 uint32_t i;
1294 int nand_ret = NANDC_RESULT_SUCCESS;
1295 /* UD bytes in last CW is 512 - cws_per_page *4.
1296 * Since each of the CW read earlier reads 4 spare bytes.
1297 */
1298 uint16_t ud_bytes_in_last_cw = USER_DATA_BYTES_PER_CW - ((flash.cws_per_page - 1) << 2);
1299 uint16_t oob_bytes = DATA_BYTES_IN_IMG_PER_CW - ud_bytes_in_last_cw;
1300
1301 params.addr0 = page << 16;
1302 params.addr1 = (page >> 16) & 0xff;
1303 params.cfg0 = cfg0;
1304 params.cfg1 = cfg1;
1305 params.cmd = NAND_CMD_PAGE_READ_ALL;
1306 params.exec = 1;
1307 ecc = ecc_bch_cfg;
1308
1309 /* Read all the Data bytes in the first 3 CWs. */
1310 addr_loc_0 = NAND_RD_LOC_OFFSET(0);
1311 addr_loc_0 |= NAND_RD_LOC_SIZE(DATA_BYTES_IN_IMG_PER_CW);
1312 addr_loc_0 |= NAND_RD_LOC_LAST_BIT(1);
1313
1314
1315 addr_loc_1 = NAND_RD_LOC_OFFSET(ud_bytes_in_last_cw);
1316 addr_loc_1 |= NAND_RD_LOC_SIZE(oob_bytes);
1317 addr_loc_1 |= NAND_RD_LOC_LAST_BIT(1);
1318
1319 status = qpic_nand_block_isbad(page / flash.num_pages_per_blk);
1320
1321 if (status)
1322 return status;
1323
1324 for (i = 0; i < flash.cws_per_page; i++)
1325 {
1326 num_cmd_desc = 0;
1327 num_data_desc = 0;
1328
1329 if (i == 0)
1330 {
1331 cmd_list_ptr = qpic_nand_add_addr_n_cfg_ce(&params, cmd_list_ptr);
1332
1333 bam_add_cmd_element(cmd_list_ptr, NAND_DEV0_ECC_CFG,(uint32_t)ecc, CE_WRITE_TYPE);
1334 cmd_list_ptr++;
1335 }
1336 else
1337 cmd_list_ptr_start = cmd_list_ptr;
1338
1339 bam_add_cmd_element(cmd_list_ptr, NAND_FLASH_CMD, (uint32_t)params.cmd, CE_WRITE_TYPE);
1340 cmd_list_ptr++;
1341
1342 if (i == flash.cws_per_page - 1)
1343 {
1344 addr_loc_0 = NAND_RD_LOC_OFFSET(0);
1345 addr_loc_0 |= NAND_RD_LOC_SIZE(ud_bytes_in_last_cw);
1346 addr_loc_0 |= NAND_RD_LOC_LAST_BIT(0);
1347
1348 /* Write addr loc 1 only for the last CW. */
1349 bam_add_cmd_element(cmd_list_ptr, NAND_READ_LOCATION_n(1), (uint32_t)addr_loc_1, CE_WRITE_TYPE);
1350 cmd_list_ptr++;
1351
1352 /* Add Data desc */
1353 bam_add_one_desc(&bam,
1354 DATA_PRODUCER_PIPE_INDEX,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001355 (unsigned char *)PA((addr_t)buffer),
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001356 ud_bytes_in_last_cw,
1357 0);
1358 num_data_desc++;
1359
1360 bam_add_one_desc(&bam,
1361 DATA_PRODUCER_PIPE_INDEX,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001362 (unsigned char *)PA((addr_t)spareaddr),
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001363 oob_bytes,
1364 BAM_DESC_INT_FLAG);
1365 num_data_desc++;
1366
1367 bam_sys_gen_event(&bam, DATA_PRODUCER_PIPE_INDEX, num_data_desc);
1368 }
1369 else
1370 {
1371 /* Add Data desc */
1372 bam_add_one_desc(&bam,
1373 DATA_PRODUCER_PIPE_INDEX,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001374 (unsigned char *)PA((addr_t)buffer),
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001375 DATA_BYTES_IN_IMG_PER_CW,
1376 BAM_DESC_INT_FLAG);
1377 num_data_desc++;
1378 bam_sys_gen_event(&bam, DATA_PRODUCER_PIPE_INDEX, num_data_desc);
1379 }
1380
1381 /* Write addr loc 0. */
1382 bam_add_cmd_element(cmd_list_ptr,
1383 NAND_READ_LOCATION_n(0),
1384 (uint32_t)addr_loc_0,
1385 CE_WRITE_TYPE);
1386
1387 cmd_list_ptr++;
1388 bam_add_cmd_element(cmd_list_ptr,
1389 NAND_EXEC_CMD,
1390 (uint32_t)params.exec,
1391 CE_WRITE_TYPE);
1392 cmd_list_ptr++;
1393
1394 /* Enqueue the desc for the above commands */
1395 bam_add_one_desc(&bam,
1396 CMD_PIPE_INDEX,
1397 (unsigned char*)cmd_list_ptr_start,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001398 PA((uint32_t)cmd_list_ptr - (uint32_t)cmd_list_ptr_start),
Deepa Dinamani4b718ec2012-09-20 11:24:47 -07001399 BAM_DESC_NWD_FLAG | BAM_DESC_CMD_FLAG | BAM_DESC_INT_FLAG | BAM_DESC_LOCK_FLAG);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001400 num_cmd_desc++;
1401
1402 qpic_nand_wait_for_cmd_exec(num_cmd_desc);
1403
1404 qpic_nand_wait_for_data(DATA_PRODUCER_PIPE_INDEX);
1405
1406 /* Save the status registers. */
1407 flash_sts[i] = qpic_nand_read_reg(NAND_FLASH_STATUS, 0, cmd_list_ptr++);
1408 buffer_sts[i] = qpic_nand_read_reg(NAND_BUFFER_STATUS, 0, cmd_list_ptr++);
1409
1410 buffer += DATA_BYTES_IN_IMG_PER_CW;
1411 }
1412
Deepa Dinamani2467bbb2012-10-02 13:59:58 -07001413 /* Read the buffer status again so that we can unlock the bam with this desc. */
1414 buffer_sts[--i] = qpic_nand_read_reg(NAND_BUFFER_STATUS, BAM_DESC_UNLOCK_FLAG, cmd_list_ptr++);
Deepa Dinamani4b718ec2012-09-20 11:24:47 -07001415
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001416 /* Check status */
1417 for (i = 0; i < flash.cws_per_page ; i ++)
1418 if (qpic_nand_check_status(flash_sts[i]))
1419 {
1420 nand_ret = NANDC_RESULT_BAD_PAGE;
1421 dprintf(CRITICAL, "NAND page read failed. page: %x\n", page);
1422 goto qpic_nand_read_page_error;
1423 }
1424
1425qpic_nand_read_page_error:
1426return nand_ret;
1427}
1428
1429/* Function to read a flash partition.
1430 * ptn : Partition to read.
1431 * extra_per_page : Spare data to be read.
1432 * offset : Num of bytes offset into the partition.
1433 * data : Buffer to read the data into.
1434 * bytes : Num of bytes to be read.
1435 */
1436 /* TODO: call this func read_partition. */
1437int
1438flash_read_ext(struct ptentry *ptn,
1439 unsigned extra_per_page,
1440 unsigned offset,
1441 void *data,
1442 unsigned bytes)
1443{
1444 uint32_t page =
1445 (ptn->start * flash.num_pages_per_blk) + (offset / flash.page_size);
1446 uint32_t lastpage = (ptn->start + ptn->length) * flash.num_pages_per_blk;
1447 uint32_t count =
1448 (bytes + flash.page_size - 1 + extra_per_page) / (flash.page_size +
1449 extra_per_page);
1450 uint32_t *spare = (unsigned *)flash_spare_bytes;
1451 uint32_t errors = 0;
1452 unsigned char *image = data;
1453 int result = 0;
1454 uint32_t current_block =
1455 (page - (page & flash.num_pages_per_blk_mask)) / flash.num_pages_per_blk;
1456 uint32_t start_block = ptn->start;
1457 uint32_t start_block_count = 0;
1458 uint32_t isbad = 0;
1459
1460 /* Verify first byte is at page boundary. */
1461 if (offset & (flash.page_size - 1))
1462 {
1463 dprintf(CRITICAL, "Read request start not at page boundary: %d\n",
1464 offset);
1465 return NANDC_RESULT_PARAM_INVALID;
1466 }
1467
1468 /* Adjust page offset based on number of bad blocks from start to current page */
1469 if (start_block < current_block)
1470 {
1471 start_block_count = (current_block - start_block);
1472 while (start_block_count
1473 && (start_block < (ptn->start + ptn->length)))
1474 {
Deepa Dinamani4b718ec2012-09-20 11:24:47 -07001475 isbad = qpic_nand_block_isbad(start_block);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001476 if (isbad)
1477 page += flash.num_pages_per_blk;
1478 else
1479 start_block_count--;
1480 start_block++;
1481 }
1482 }
1483
1484 while ((page < lastpage) && !start_block_count)
1485 {
1486 if (count == 0)
1487 {
1488 dprintf(INFO, "flash_read_image: success (%d errors)\n",
1489 errors);
1490 return NANDC_RESULT_SUCCESS;
1491 }
1492
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001493 result = qpic_nand_read_page(page, rdwr_buf, (unsigned char *)spare);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001494
1495 if (result == NANDC_RESULT_BAD_PAGE)
1496 {
1497 /* bad page, go to next page. */
1498 page++;
1499 errors++;
1500 continue;
1501 }
1502 else if (result == NANDC_RESULT_BAD_BLOCK)
1503 {
1504 /* bad block, go to next block same offset. */
1505 page += flash.num_pages_per_blk;
1506 errors++;
1507 continue;
1508 }
1509
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001510 /* Copy the read page into correct location. */
1511 memcpy(image, rdwr_buf, flash.page_size);
1512
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001513 page++;
1514 image += flash.page_size;
1515 /* Copy spare bytes to image */
1516 memcpy(image, spare, extra_per_page);
1517 image += extra_per_page;
1518 count -= 1;
1519 }
1520
1521 /* could not find enough valid pages before we hit the end */
1522 dprintf(CRITICAL, "flash_read_image: failed (%d errors)\n", errors);
1523 return NANDC_RESULT_FAILURE;
1524}
1525
1526int
1527flash_erase(struct ptentry *ptn)
1528{
Deepa Dinamani2467bbb2012-10-02 13:59:58 -07001529 int ret = 0;
1530
1531 ret = qpic_nand_blk_erase(ptn->start * flash.num_pages_per_blk);
1532
1533 if (ret)
1534 dprintf(CRITICAL, "Erase operation failed \n");
1535
1536 return ret;
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001537}
Deepa Dinamani2467bbb2012-10-02 13:59:58 -07001538
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001539int
1540flash_ecc_bch_enabled()
1541{
1542 return (flash.ecc_width == NAND_WITH_4_BIT_ECC)? 0 : 1;
1543}
1544
1545int
1546flash_write(struct ptentry *ptn,
1547 unsigned extra_per_page,
1548 const void *data,
1549 unsigned bytes)
1550{
1551 uint32_t page = ptn->start * flash.num_pages_per_blk;
1552 uint32_t lastpage = (ptn->start + ptn->length) * flash.num_pages_per_blk;
1553 uint32_t *spare = (unsigned *)flash_spare_bytes;
1554 const unsigned char *image = data;
1555 uint32_t wsize = flash.page_size + extra_per_page;
1556 int r;
1557
1558 memset(spare, 0xff, (flash.spare_size / flash.cws_per_page));
1559
1560 while (bytes > 0)
1561 {
1562 if (bytes < wsize)
1563 {
1564 dprintf(CRITICAL,
1565 "flash_write_image: image undersized (%d < %d)\n",
1566 bytes,
1567 wsize);
1568 return -1;
1569 }
1570
1571 if (page >= lastpage)
1572 {
1573 dprintf(CRITICAL, "flash_write_image: out of space\n");
1574 return -1;
1575 }
1576
1577 if ((page & flash.num_pages_per_blk_mask) == 0)
1578 {
Deepa Dinamani2467bbb2012-10-02 13:59:58 -07001579 if (qpic_nand_blk_erase(page))
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001580 {
1581 dprintf(INFO,
1582 "flash_write_image: bad block @ %d\n",
1583 page / flash.num_pages_per_blk);
1584
1585 page += flash.num_pages_per_blk;
1586 continue;
1587 }
1588 }
1589
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001590 memcpy(rdwr_buf, image, flash.page_size);
1591
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001592 if (extra_per_page)
1593 {
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001594 memcpy(rdwr_buf + flash.page_size, image + flash.page_size, extra_per_page);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001595 r = qpic_nand_write_page(page,
1596 NAND_CFG,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001597 rdwr_buf,
1598 rdwr_buf + flash.page_size);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001599 }
1600 else
1601 {
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001602 r = qpic_nand_write_page(page, NAND_CFG, rdwr_buf, spare);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001603 }
1604
1605 if (r)
1606 {
1607 dprintf(INFO,
1608 "flash_write_image: write failure @ page %d (src %d)\n",
1609 page,
1610 image - (const unsigned char *)data);
1611
1612 image -= (page & flash.num_pages_per_blk_mask) * wsize;
1613 bytes += (page & flash.num_pages_per_blk_mask) * wsize;
1614 page &= ~flash.num_pages_per_blk_mask;
1615 if (qpic_nand_blk_erase(page))
1616 {
1617 dprintf(INFO,
1618 "flash_write_image: erase failure @ page %d\n",
1619 page);
1620 }
1621
1622 qpic_nand_mark_badblock(page);
1623
1624 dprintf(INFO,
1625 "flash_write_image: restart write @ page %d (src %d)\n",
1626 page, image - (const unsigned char *)data);
1627
1628 page += flash.num_pages_per_blk;
1629 continue;
1630 }
1631 page++;
1632 image += wsize;
1633 bytes -= wsize;
1634 }
1635
1636 /* erase any remaining pages in the partition */
1637 page = (page + flash.num_pages_per_blk_mask) & (~flash.num_pages_per_blk_mask);
1638
1639 while (page < lastpage)
1640 {
1641 if (qpic_nand_blk_erase(page))
1642 {
1643 dprintf(INFO, "flash_write_image: bad block @ %d\n",
1644 page / flash.num_pages_per_blk);
1645 }
1646 page += flash.num_pages_per_blk;
1647 }
1648
1649 dprintf(INFO, "flash_write_image: success\n");
1650 return 0;
1651}