blob: ecb5bbb77929c6c26891c5c6fcd6d41bc843ec87 [file] [log] [blame]
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001/*
2 * Copyright (c) 2008, Google Inc.
3 * All rights reserved.
Joonwoo Park342b2362014-08-25 15:41:39 -07004 * Copyright (c) 2009-2014, The Linux Foundation. All rights reserved.
Deepa Dinamanie4573be2012-08-03 16:32:29 -07005 * 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>
Smita Ghoshf5431c62014-09-18 14:11:14 -070039#include <platform/iomap.h>
Deepa Dinamanie4573be2012-08-03 16:32:29 -070040
41static uint32_t nand_base;
42static struct ptable *flash_ptable;
43static struct flash_info flash;
44static unsigned char *flash_spare_bytes;
45static uint32_t cfg0;
46static uint32_t cfg1;
47static uint32_t cfg0_raw;
48static uint32_t cfg1_raw;
49static uint32_t ecc_bch_cfg;
50
51struct cmd_element ce_array[100];
52
53#define QPIC_BAM_DATA_FIFO_SIZE 64
54#define QPIC_BAM_CMD_FIFO_SIZE 64
55
56static struct bam_desc cmd_desc_fifo[QPIC_BAM_CMD_FIFO_SIZE] __attribute__ ((aligned(BAM_DESC_SIZE)));
57static struct bam_desc data_desc_fifo[QPIC_BAM_DATA_FIFO_SIZE] __attribute__ ((aligned(BAM_DESC_SIZE)));
58
59static struct bam_instance bam;
60static uint8_t *bbtbl;
61
Deepa Dinamani0bf2f442012-10-19 11:41:06 -070062static uint8_t* rdwr_buf;
63
Deepa Dinamanie4573be2012-08-03 16:32:29 -070064static struct flash_id supported_flash[] = {
Deepa Dinamani649a94a2013-03-07 14:37:31 -080065 /* Flash ID ID Mask Density(MB) Wid Pgsz Blksz oobsz 8-bit ECCf */
66 {0x1590AC2C, 0xFFFFFFFF, 0x20000000, 0, 2048, 0x00020000, 0x40, 0},
Sundarajan Srinivasand4e21952013-08-27 15:59:10 -070067 {0x1590AA2C, 0xFFFFFFFF, 0x10000000, 0, 2048, 0x00020000, 0xE0, 1},
Deepa Dinamani649a94a2013-03-07 14:37:31 -080068 {0x2690AC2C, 0xFFFFFFFF, 0x20000000, 0, 4096, 0x00040000, 0xE0, 1},
Sundarajan Srinivasand69c0d32013-08-09 16:47:33 -070069 {0x1590ACAD, 0xFFFFFFFF, 0x20000000, 0, 2048, 0x00020000, 0x80, 0},
Joonwoo Park342b2362014-08-25 15:41:39 -070070 {0x9590DC2C, 0xFFFFFFFF, 0x10000000, 0, 2048, 0x00020000, 0x40, 0},
Channagoud Kadabi12b96932014-09-23 15:18:11 -070071 {0x1590aa98, 0xFFFFFFFF, 0x10000000, 0, 2048, 0x00020000, 0x80, 1},
Deepa Dinamanie4573be2012-08-03 16:32:29 -070072 /* Note: Width flag is 0 for 8 bit Flash and 1 for 16 bit flash */
Deepa Dinamanie4573be2012-08-03 16:32:29 -070073};
74
Deepa Dinamanie4573be2012-08-03 16:32:29 -070075static void
76qpic_nand_wait_for_cmd_exec(uint32_t num_desc)
77{
78 /* Create a read/write event to notify the periperal of the added desc. */
79 bam_sys_gen_event(&bam, CMD_PIPE_INDEX, num_desc);
80
81 /* Wait for the descriptors to be processed */
82 bam_wait_for_interrupt(&bam, CMD_PIPE_INDEX, P_PRCSD_DESC_EN_MASK);
83
84 /* Read offset update for the circular FIFO */
85 bam_read_offset_update(&bam, CMD_PIPE_INDEX);
86}
87
88static void
89qpic_nand_wait_for_data(uint32_t pipe_num)
90{
91 /* Wait for the descriptors to be processed */
92 bam_wait_for_interrupt(&bam, pipe_num, P_PRCSD_DESC_EN_MASK);
93
94 /* Read offset update for the circular FIFO */
95 bam_read_offset_update(&bam, pipe_num);
96}
97
98static uint32_t
99qpic_nand_read_reg(uint32_t reg_addr,
100 uint8_t flags,
101 struct cmd_element *cmd_list_ptr)
102{
103 uint32_t val;
104
Deepa Dinamani0bf2f442012-10-19 11:41:06 -0700105 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 -0700106
107 /* Enqueue the desc for the above command */
108 bam_add_one_desc(&bam,
109 CMD_PIPE_INDEX,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -0700110 (unsigned char*)PA((addr_t)cmd_list_ptr),
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700111 BAM_CE_SIZE,
112 BAM_DESC_CMD_FLAG| BAM_DESC_INT_FLAG | flags);
113
114 qpic_nand_wait_for_cmd_exec(1);
115
116 return val;
117}
118
Deepa Dinamani19530062012-10-03 14:43:05 -0700119/* Assume the BAM is in a locked state. */
120void
sundarajan srinivasan7ced6482013-03-21 16:01:18 -0700121qpic_nand_erased_status_reset(struct cmd_element *cmd_list_ptr, uint8_t flags)
Deepa Dinamani19530062012-10-03 14:43:05 -0700122{
123 uint32_t val = 0;
124
125 /* Reset the Erased Codeword/Page detection controller. */
126 val = NAND_ERASED_CW_DETECT_CFG_RESET_CTRL;
127
128 bam_add_cmd_element(cmd_list_ptr, NAND_ERASED_CW_DETECT_CFG, val, CE_WRITE_TYPE);
129
130 /* Enqueue the desc for the above command */
131 bam_add_one_desc(&bam,
132 CMD_PIPE_INDEX,
133 (unsigned char*)cmd_list_ptr,
134 BAM_CE_SIZE,
sundarajan srinivasan7ced6482013-03-21 16:01:18 -0700135 BAM_DESC_CMD_FLAG | BAM_DESC_INT_FLAG | flags);
Deepa Dinamani19530062012-10-03 14:43:05 -0700136
137 qpic_nand_wait_for_cmd_exec(1);
138
139 /* Enable the Erased Codeword/Page detection
140 * controller to check the data as it arrives.
141 * Also disable ECC reporting for an erased CW.
142 */
143 val = NAND_ERASED_CW_DETECT_CFG_ACTIVATE_CTRL | NAND_ERASED_CW_DETECT_ERASED_CW_ECC_MASK;
144
145 bam_add_cmd_element(cmd_list_ptr, NAND_ERASED_CW_DETECT_CFG, val, CE_WRITE_TYPE);
146
147 /* Enqueue the desc for the above command */
148 bam_add_one_desc(&bam,
149 CMD_PIPE_INDEX,
150 (unsigned char*)cmd_list_ptr,
151 BAM_CE_SIZE,
152 BAM_DESC_CMD_FLAG | BAM_DESC_INT_FLAG);
153
154 qpic_nand_wait_for_cmd_exec(1);
155}
156
157static nand_result_t
158qpic_nand_check_status(uint32_t status)
159{
160 uint32_t erase_sts;
161
162 /* Check for errors */
163 if (status & NAND_FLASH_ERR)
164 {
165 /* Check if this is an ECC error on an erased page. */
166 if (status & NAND_FLASH_OP_ERR)
167 {
168 erase_sts = qpic_nand_read_reg(NAND_ERASED_CW_DETECT_STATUS, 0, ce_array);
169 if ((erase_sts & (1 << NAND_ERASED_CW_DETECT_STATUS_PAGE_ALL_ERASED)))
170 {
171 /* Mask the OP ERROR. */
172 status &= ~NAND_FLASH_OP_ERR;
sundarajan srinivasan7ced6482013-03-21 16:01:18 -0700173 qpic_nand_erased_status_reset(ce_array, 0);
Deepa Dinamani19530062012-10-03 14:43:05 -0700174 }
175 }
176
177 /* ECC error flagged on an erased page read.
178 * Ignore and return success.
179 */
180 if (!(status & NAND_FLASH_ERR))
181 return NANDC_RESULT_SUCCESS;
182
183 dprintf(CRITICAL, "Nand Flash error. Status = %d\n", status);
184
185 if (status & NAND_FLASH_TIMEOUT_ERR)
186 return NANDC_RESULT_TIMEOUT;
187 else
188 return NANDC_RESULT_FAILURE;
189 }
190
191 return NANDC_RESULT_SUCCESS;
192}
193
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700194static uint32_t
195qpic_nand_fetch_id(struct flash_info *flash)
196{
197 struct cmd_element *cmd_list_ptr = ce_array;
198 struct cmd_element *cmd_list_ptr_start = ce_array;
199 int num_desc = 0;
200 uint32_t status;
201 uint32_t id;
202 uint32_t flash_cmd = NAND_CMD_FETCH_ID;
203 uint32_t exec_cmd = 1;
204 int nand_ret = NANDC_RESULT_SUCCESS;
205
206 /* Issue the Fetch id command to the NANDc */
207 bam_add_cmd_element(cmd_list_ptr, NAND_FLASH_CMD, (uint32_t)flash_cmd, CE_WRITE_TYPE);
208 cmd_list_ptr++;
209
210 /* Execute the cmd */
211 bam_add_cmd_element(cmd_list_ptr, NAND_EXEC_CMD, (uint32_t)exec_cmd, CE_WRITE_TYPE);
212 cmd_list_ptr++;
213
214 /* Prepare the cmd desc for the above commands */
215 bam_add_one_desc(&bam,
216 CMD_PIPE_INDEX,
217 (unsigned char*)cmd_list_ptr_start,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -0700218 PA((uint32_t)cmd_list_ptr - (uint32_t)cmd_list_ptr_start),
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700219 BAM_DESC_LOCK_FLAG | BAM_DESC_INT_FLAG |
220 BAM_DESC_NWD_FLAG | BAM_DESC_CMD_FLAG);
221
222 /* Keep track of the number of desc added. */
223 num_desc++;
224 qpic_nand_wait_for_cmd_exec(num_desc);
225
226 cmd_list_ptr_start = ce_array;
227 cmd_list_ptr = ce_array;
228
229 /* Read the status register */
230 status = qpic_nand_read_reg(NAND_FLASH_STATUS, 0, cmd_list_ptr);
231
232 /* Check for errors */
233 nand_ret = qpic_nand_check_status(status);
234 if (nand_ret)
235 {
236 dprintf( CRITICAL, "Read ID cmd status failed\n");
237 goto qpic_nand_fetch_id_err;
238 }
239
240 /* Read the id */
241 id = qpic_nand_read_reg(NAND_READ_ID, BAM_DESC_UNLOCK_FLAG, cmd_list_ptr);
242
243 flash->id = id;
244 flash->vendor = id & 0xff;
245 flash->device = (id >> 8) & 0xff;
246 flash->dev_cfg = (id >> 24) & 0xFF;
247 flash->widebus = 0;
248 flash->widebus &= (id >> 24) & 0xFF;
249 flash->widebus = flash->widebus? 1: 0;
250
251qpic_nand_fetch_id_err:
252 return nand_ret;
253}
254
255static int
Deepa Dinamanie9ded132012-11-27 15:03:38 -0800256qpic_bam_init(struct qpic_nand_init_config *config)
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700257{
258 uint32_t bam_ret = NANDC_RESULT_SUCCESS;
259
Deepa Dinamanie9ded132012-11-27 15:03:38 -0800260 bam.base = config->bam_base;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700261 /* Set Read pipe params. */
Deepa Dinamanie9ded132012-11-27 15:03:38 -0800262 bam.pipe[DATA_PRODUCER_PIPE_INDEX].pipe_num = config->pipes.read_pipe;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700263 /* System consumer */
264 bam.pipe[DATA_PRODUCER_PIPE_INDEX].trans_type = BAM2SYS;
265 bam.pipe[DATA_PRODUCER_PIPE_INDEX].fifo.size = QPIC_BAM_DATA_FIFO_SIZE;
266 bam.pipe[DATA_PRODUCER_PIPE_INDEX].fifo.head = data_desc_fifo;
Deepa Dinamani536d3f82013-07-09 13:05:56 -0700267 bam.pipe[DATA_PRODUCER_PIPE_INDEX].lock_grp = config->pipes.read_pipe_grp;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700268
269 /* Set Write pipe params. */
Deepa Dinamanie9ded132012-11-27 15:03:38 -0800270 bam.pipe[DATA_CONSUMER_PIPE_INDEX].pipe_num = config->pipes.write_pipe;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700271 /* System producer */
272 bam.pipe[DATA_CONSUMER_PIPE_INDEX].trans_type = SYS2BAM;
273 bam.pipe[DATA_CONSUMER_PIPE_INDEX].fifo.size = QPIC_BAM_DATA_FIFO_SIZE;
274 bam.pipe[DATA_CONSUMER_PIPE_INDEX].fifo.head = data_desc_fifo;
Deepa Dinamani536d3f82013-07-09 13:05:56 -0700275 bam.pipe[DATA_CONSUMER_PIPE_INDEX].lock_grp = config->pipes.write_pipe_grp;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700276
277 /* Set Cmd pipe params. */
Deepa Dinamanie9ded132012-11-27 15:03:38 -0800278 bam.pipe[CMD_PIPE_INDEX].pipe_num = config->pipes.cmd_pipe;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700279 /* System consumer */
Sundarajan Srinivasan357c35a2013-07-23 17:00:54 -0700280 bam.pipe[CMD_PIPE_INDEX].trans_type = SYS2BAM;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700281 bam.pipe[CMD_PIPE_INDEX].fifo.size = QPIC_BAM_CMD_FIFO_SIZE;
282 bam.pipe[CMD_PIPE_INDEX].fifo.head = cmd_desc_fifo;
Deepa Dinamani536d3f82013-07-09 13:05:56 -0700283 bam.pipe[CMD_PIPE_INDEX].lock_grp = config->pipes.cmd_pipe_grp;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700284
285 /* Programs the threshold for BAM transfer
286 * When this threshold is reached, BAM signals the peripheral via the pipe_bytes_available
287 * interface.
288 * The peripheral is signalled with this notification in the following cases:
289 * a. It has accumulated all the descriptors.
290 * b. It has accumulated more than threshold bytes.
291 * c. It has reached EOT (End Of Transfer).
292 * Note: this value needs to be set by the h/w folks and is specific for each peripheral.
293 */
294 bam.threshold = 32;
295
Deepa Dinamanie9ded132012-11-27 15:03:38 -0800296 /* Set the EE. */
297 bam.ee = config->ee;
298
299 /* Set the max desc length for this BAM. */
300 bam.max_desc_len = config->max_desc_len;
301
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700302 /* BAM Init. */
303 bam_init(&bam);
304
305 /* Initialize BAM QPIC read pipe */
306 bam_sys_pipe_init(&bam, DATA_PRODUCER_PIPE_INDEX);
307
308 /* Init read fifo */
309 bam_ret = bam_pipe_fifo_init(&bam, bam.pipe[DATA_PRODUCER_PIPE_INDEX].pipe_num);
310
311 if (bam_ret)
312 {
313 dprintf(CRITICAL, "QPIC:NANDc BAM Read FIFO init error\n");
314 bam_ret = NANDC_RESULT_FAILURE;
315 goto qpic_nand_bam_init_error;
316 }
317
318 /* Initialize BAM QPIC write pipe */
319 bam_sys_pipe_init(&bam, DATA_CONSUMER_PIPE_INDEX);
320
321 /* Init write fifo. Use the same fifo as read fifo. */
322 bam_ret = bam_pipe_fifo_init(&bam, bam.pipe[DATA_CONSUMER_PIPE_INDEX].pipe_num);
323
324 if (bam_ret)
325 {
326 dprintf(CRITICAL, "QPIC: NANDc: BAM Write FIFO init error\n");
327 bam_ret = NANDC_RESULT_FAILURE;
328 goto qpic_nand_bam_init_error;
329 }
330
331 /* Initialize BAM QPIC cmd pipe */
332 bam_sys_pipe_init(&bam, CMD_PIPE_INDEX);
333
334 /* Init cmd fifo */
335 bam_ret = bam_pipe_fifo_init(&bam, bam.pipe[CMD_PIPE_INDEX].pipe_num);
336
337 if (bam_ret)
338 {
339 dprintf(CRITICAL, "QPIC:NANDc BAM CMD FIFO init error\n");
340 bam_ret = NANDC_RESULT_FAILURE;
341 goto qpic_nand_bam_init_error;
342 }
343
344qpic_nand_bam_init_error:
345return bam_ret;
346}
347
348/* Adds command elements for addr and cfg register writes.
349 * cfg: Defines the configuration for the flash cmd.
350 * start: Address where the command elements are added.
351 *
352 * Returns the address where the next cmd element can be added.
353 */
354static struct cmd_element*
355qpic_nand_add_addr_n_cfg_ce(struct cfg_params *cfg,
356 struct cmd_element *start)
357{
358 struct cmd_element *cmd_list_ptr = start;
359
360 bam_add_cmd_element(cmd_list_ptr, NAND_ADDR0, (uint32_t)cfg->addr0, CE_WRITE_TYPE);
361 cmd_list_ptr++;
362 bam_add_cmd_element(cmd_list_ptr, NAND_ADDR1, (uint32_t)cfg->addr1, CE_WRITE_TYPE);
363 cmd_list_ptr++;
364 bam_add_cmd_element(cmd_list_ptr, NAND_DEV0_CFG0, (uint32_t)cfg->cfg0, CE_WRITE_TYPE);
365 cmd_list_ptr++;
366 bam_add_cmd_element(cmd_list_ptr, NAND_DEV0_CFG1, (uint32_t)cfg->cfg1, CE_WRITE_TYPE);
367 cmd_list_ptr++;
368
369 return cmd_list_ptr;
370}
371
372
373static struct cmd_element*
374qpic_nand_add_onfi_probe_ce(struct onfi_probe_params *params,
375 struct cmd_element *start)
376{
377 struct cmd_element *cmd_list_ptr = start;
378
379 cmd_list_ptr = qpic_nand_add_addr_n_cfg_ce(&params->cfg, cmd_list_ptr);
380
381 bam_add_cmd_element(cmd_list_ptr, NAND_DEV_CMD1, (uint32_t)params->dev_cmd1, CE_WRITE_TYPE);
382 cmd_list_ptr++;
383 bam_add_cmd_element(cmd_list_ptr, NAND_DEV_CMD_VLD, (uint32_t)params->vld, CE_WRITE_TYPE);
384 cmd_list_ptr++;
385 bam_add_cmd_element(cmd_list_ptr, NAND_READ_LOCATION_n(0), (uint32_t)params->cfg.addr_loc_0, CE_WRITE_TYPE);
386 cmd_list_ptr++;
387 bam_add_cmd_element(cmd_list_ptr, NAND_FLASH_CMD, (uint32_t)params->cfg.cmd, CE_WRITE_TYPE);
388 cmd_list_ptr++;
389 bam_add_cmd_element(cmd_list_ptr, NAND_EXEC_CMD, (uint32_t)params->cfg.exec, CE_WRITE_TYPE);
390 cmd_list_ptr++;
391
392 return cmd_list_ptr;
393}
394
395static int
396onfi_probe_cmd_exec(struct onfi_probe_params *params,
397 unsigned char* data_ptr,
398 int data_len)
399{
400 struct cmd_element *cmd_list_ptr = ce_array;
401 struct cmd_element *cmd_list_ptr_start = ce_array;
402 int num_desc = 0;
403 uint32_t status = 0;
404 int nand_ret = NANDC_RESULT_SUCCESS;
405 uint8_t desc_flags = BAM_DESC_NWD_FLAG | BAM_DESC_CMD_FLAG
406 | BAM_DESC_LOCK_FLAG | BAM_DESC_INT_FLAG;
407
408 params->cfg.addr_loc_0 = 0;
409 params->cfg.addr_loc_0 |= NAND_RD_LOC_LAST_BIT(1);
410 params->cfg.addr_loc_0 |= NAND_RD_LOC_OFFSET(0);
411 params->cfg.addr_loc_0 |= NAND_RD_LOC_SIZE(data_len);
412
413 cmd_list_ptr = qpic_nand_add_onfi_probe_ce(params, cmd_list_ptr);
414
415 /* Enqueue the desc for the above commands */
416 bam_add_one_desc(&bam,
417 CMD_PIPE_INDEX,
418 (unsigned char*)cmd_list_ptr_start,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -0700419 PA((addr_t)(uint32_t)cmd_list_ptr - (uint32_t)cmd_list_ptr_start),
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700420 desc_flags);
421
422 cmd_list_ptr_start = cmd_list_ptr;
423 num_desc++;
424
425 /* Add Data desc */
426 bam_add_desc(&bam,
427 DATA_PRODUCER_PIPE_INDEX,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -0700428 (unsigned char *)PA((addr_t)data_ptr),
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700429 data_len,
430 BAM_DESC_INT_FLAG);
431
432 /* Wait for the commands to be executed */
433 qpic_nand_wait_for_cmd_exec(num_desc);
434
435 /* Read buffer status and check for errors. */
436 status = qpic_nand_read_reg(NAND_FLASH_STATUS, 0, cmd_list_ptr++);
437
438 if (qpic_nand_check_status(status))
439 {
440 nand_ret = NANDC_RESULT_FAILURE;
441 goto onfi_probe_exec_err;
442 }
443
444 /* Wait for data to be available */
445 qpic_nand_wait_for_data(DATA_PRODUCER_PIPE_INDEX);
446
447 /* Check for errors */
448 nand_ret = qpic_nand_check_status(status);
449
450onfi_probe_exec_err:
451 return nand_ret;
452}
453
454/* TODO: check why both vld and cmd need to be written. */
455void
456qpic_nand_onfi_probe_cleanup(uint32_t vld, uint32_t dev_cmd1)
457{
458 struct cmd_element *cmd_list_ptr = ce_array;
459 struct cmd_element *cmd_list_ptr_start = ce_array;
460
461 bam_add_cmd_element(cmd_list_ptr, NAND_DEV_CMD1, dev_cmd1, CE_WRITE_TYPE);
462 cmd_list_ptr++;
463 bam_add_cmd_element(cmd_list_ptr, NAND_DEV_CMD_VLD, vld, CE_WRITE_TYPE);
464 cmd_list_ptr++;
465
466 /* Enqueue the desc for the above commands */
467 bam_add_one_desc(&bam,
468 CMD_PIPE_INDEX,
469 (unsigned char*)cmd_list_ptr_start,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -0700470 PA((uint32_t)cmd_list_ptr - (uint32_t)cmd_list_ptr_start),
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700471 BAM_DESC_UNLOCK_FLAG | BAM_DESC_CMD_FLAG| BAM_DESC_INT_FLAG);
472
473 qpic_nand_wait_for_cmd_exec(1);
474}
475
476static int
477qpic_nand_onfi_save_params(struct onfi_param_page *param_page, struct flash_info *flash)
478{
479 int onfi_ret = NANDC_RESULT_SUCCESS;
480 uint32_t ecc_bits;
481
482 onfi_ret = qpic_nand_fetch_id(flash);
483
484 if (onfi_ret)
485 {
486 dprintf(CRITICAL, "Fetch ID cmd failed\n");
487 goto onfi_save_params_err;
488 }
489
490 flash->page_size = param_page->data_per_pg;
491 flash->block_size = param_page->pgs_per_blk * flash->page_size;
492 flash->num_blocks = param_page->blks_per_LUN;
493 flash->widebus = param_page->feature_supported & 0x1;
494 flash->density = param_page->blks_per_LUN * flash->blksize;
495 flash->spare_size = param_page->spare_per_pg;
496 ecc_bits = param_page->num_bits_ecc_correctability;
497 flash->num_pages_per_blk = param_page->pgs_per_blk;
498 flash->num_pages_per_blk_mask = param_page->pgs_per_blk - 1;
499
500 if (ecc_bits >= 8)
501 flash->ecc_width = NAND_WITH_8_BIT_ECC;
502 else
503 flash->ecc_width = NAND_WITH_4_BIT_ECC;
504
505 onfi_save_params_err:
506 return onfi_ret;
507}
508
509static void
510qpic_nand_save_config(struct flash_info *flash)
511{
512
513 /* Save Configurations */
514 flash->cws_per_page = flash->page_size >> NAND_CW_DIV_RIGHT_SHIFT;
515
Deepa Dinamani16663a62013-02-07 16:25:59 -0800516 /* Verify that we have enough buffer to handle all the cws in a page. */
517 ASSERT(flash->cws_per_page <= QPIC_NAND_MAX_CWS_IN_PAGE);
518
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700519 /* Codeword Size = UD_SIZE_BYTES + ECC_PARITY_SIZE_BYTES
520 * + SPARE_SIZE_BYTES + Bad Block size
521 */
522 if (flash->ecc_width & NAND_WITH_8_BIT_ECC)
523 {
524 flash->cw_size = NAND_CW_SIZE_8_BIT_ECC;
525 ecc_bch_cfg |= (1 << NAND_DEV0_ECC_MODE_SHIFT); /* Use 8-bit ecc */
526
527 if (flash->widebus)
528 {
529 cfg0 |= (0 << NAND_DEV0_CFG0_SPARE_SZ_BYTES_SHIFT); /* spare size bytes in each CW */
530 ecc_bch_cfg |= (14 << NAND_DEV0_ECC_PARITY_SZ_BYTES_SHIFT); /* parity bytes in each CW */
531 }
532 else
533 {
534 cfg0 |= (2 << NAND_DEV0_CFG0_SPARE_SZ_BYTES_SHIFT); /* spare size bytes in each CW */
535 ecc_bch_cfg |= (13 << NAND_DEV0_ECC_PARITY_SZ_BYTES_SHIFT); /* parity bytes in each CW */
536 }
537 }
538 else
539 {
540 flash->cw_size = NAND_CW_SIZE_4_BIT_ECC;
541
542 if (flash->widebus)
543 {
544 cfg0 |= (2 << NAND_DEV0_CFG0_SPARE_SZ_BYTES_SHIFT); /* spare size bytes in each CW */
545 ecc_bch_cfg |= (8 << NAND_DEV0_ECC_PARITY_SZ_BYTES_SHIFT); /* parity bytes in each CW */
546 }
547 else
548 {
549 cfg0 |= (4 << NAND_DEV0_CFG0_SPARE_SZ_BYTES_SHIFT); /* spare size bytes in each CW */
550 ecc_bch_cfg |= (7 << NAND_DEV0_ECC_PARITY_SZ_BYTES_SHIFT); /* parity bytes in each CW */
551 }
552 }
553
554 /* BAD_BLOCK_BYTE_NUM = Page Size -
555 * (CW_PER_PAGE * Codeword Size) + 1
556 * Note: Set CW_PER_PAGE to 1 less than the actual number.
557 */
558 flash->bad_blk_loc = flash->page_size - flash->cw_size * (flash->cws_per_page - 1) + 1;
559
560 cfg0 |= ((flash->cws_per_page - 1) << NAND_DEV0_CFG0_CW_PER_PAGE_SHIFT) /* 4/8 cw/pg for 2/4k */
561 |(DATA_BYTES_IN_IMG_PER_CW << NAND_DEV0_CFG0_UD_SIZE_BYTES_SHIFT) /* 516 user data bytes */
562 |(5 << NAND_DEV0_CFG0_ADDR_CYCLE_SHIFT) /* 5 address cycles */
563 |(0 << NAND_DEV0_CFG0_DIS_STS_AFTER_WR_SHIFT);/* Send read status cmd after each write. */
564
565 cfg1 |= (7 << NAND_DEV0_CFG1_RECOVERY_CYCLES_SHIFT) /* 8 recovery cycles */
566 |(0 << NAND_DEV0_CFG1_CS_ACTIVE_BSY_SHIFT) /* Allow CS deassertion */
567 |(flash->bad_blk_loc << NAND_DEV0_CFG1_BAD_BLK_BYTE_NUM_SHIFT)/* Bad block marker location */
568 |(0 << NAND_DEV0_CFG1_BAD_BLK_IN_SPARE_SHIFT) /* Bad block in user data area */
569 |(2 << NAND_DEV0_CFG1_WR_RD_BSY_GAP_SHIFT) /* 8 cycle tWB/tRB */
570 |(flash->widebus << NAND_DEV0_CFG1_WIDE_BUS_SHIFT); /* preserve wide flash flag */
571
572 cfg0_raw = ((flash->cws_per_page- 1) << NAND_DEV0_CFG0_CW_PER_PAGE_SHIFT)
573 |(5 << NAND_DEV0_CFG0_ADDR_CYCLE_SHIFT)
574 |(516 << NAND_DEV0_CFG0_UD_SIZE_BYTES_SHIFT) //figure out the size of cw
575 | (1 << NAND_DEV0_CFG0_DIS_STS_AFTER_WR_SHIFT);
576
577 cfg1_raw = (7 << NAND_DEV0_CFG1_RECOVERY_CYCLES_SHIFT)
578 | (0 << NAND_DEV0_CFG1_CS_ACTIVE_BSY_SHIFT)
579 | (17 << NAND_DEV0_CFG1_BAD_BLK_BYTE_NUM_SHIFT)
580 | (1 << NAND_DEV0_CFG1_BAD_BLK_IN_SPARE_SHIFT)
581 | (2 << NAND_DEV0_CFG1_WR_RD_BSY_GAP_SHIFT)
582 | (flash->widebus << NAND_DEV0_CFG1_WIDE_BUS_SHIFT)
583 |1 ; /* to disable reed solomon ecc..this feild is now read only. */
584
585 ecc_bch_cfg |= (0 << NAND_DEV0_ECC_DISABLE_SHIFT) /* Enable ECC */
586 | (0 << NAND_DEV0_ECC_SW_RESET_SHIFT) /* Put ECC core in op mode */
587 | (DATA_BYTES_IN_IMG_PER_CW << NAND_DEV0_ECC_NUM_DATA_BYTES)
588 | (1 << NAND_DEV0_ECC_FORCE_CLK_OPEN_SHIFT); /* Enable all clocks */
589}
590
591/* Onfi probe should issue the following commands to the flash device:
592 * 1. Read ID - with addr ONFI_READ_ID_ADDR.
593 * This returns the ONFI ASCII string indicating support for ONFI.
594 * 2. Read Prameter Page - with addr ONFI_READ_PARAM_PAGE_ADDR.
595 * This returns the params for the device.
596 * Each command inturn issues commands- ADDR0, ADDR1, chip_select,
597 * cfg0, cfg1, cmd_vld, dev_cmd1, read_loc0, flash, exec.
598 */
599static int
600qpic_nand_onfi_probe(struct flash_info *flash)
601{
602 struct onfi_probe_params params;
603 uint32_t vld;
604 uint32_t dev_cmd1;
605 unsigned char *buffer;
606 unsigned char onfi_str[4];
607 uint32_t *id;
608 struct onfi_param_page *param_page;
609 int onfi_ret = NANDC_RESULT_SUCCESS;
610
611 /* Allocate memory required to read the onfi param page */
612 buffer = (unsigned char*) malloc(ONFI_READ_PARAM_PAGE_BUFFER_SIZE);
Maria Yu71909742014-07-04 17:30:00 +0800613 ASSERT(buffer != NULL);
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700614
615 /* Read the vld and dev_cmd1 registers before modifying */
616 vld = qpic_nand_read_reg(NAND_DEV_CMD_VLD, 0, ce_array);
617 dev_cmd1 = qpic_nand_read_reg(NAND_DEV_CMD1, 0, ce_array);
618
619 /* Initialize flash cmd */
620 params.cfg.cmd = NAND_CMD_PAGE_READ;
621 params.cfg.exec = 1;
622
623 /* Execute Read ID cmd */
624
625 /* Initialize the config */
626 params.cfg.cfg0 = NAND_CFG0_RAW_ONFI_ID;
627 params.cfg.cfg1 = NAND_CFG1_RAW_ONFI_ID;
628
629 /* Initialize the cmd and vld */
630 params.dev_cmd1 = (dev_cmd1 & 0xFFFFFF00) | ONFI_READ_ID_CMD;
631 params.vld = vld & 0xFFFFFFFE;
632
633 /* Initialize the address
634 * addr1 is not used bcos of the cfg.
635 */
636 params.cfg.addr0 = ONFI_READ_ID_ADDR;
637 params.cfg.addr1 = 0;
638
639 /* Lock the pipe and execute the cmd. */
640 onfi_ret = onfi_probe_cmd_exec(&params, onfi_str, ONFI_READ_ID_BUFFER_SIZE);
641 if (onfi_ret)
642 {
643 dprintf(CRITICAL, "ONFI Read id cmd failed\n");
644 goto qpic_nand_onfi_probe_err;
645 }
646
647 /* Write back vld and cmd and unlock the pipe. */
648 qpic_nand_onfi_probe_cleanup(vld, dev_cmd1);
649
650 /* Check for onfi string */
651 id = (uint32_t*)onfi_str;
652 if (*id != ONFI_SIGNATURE)
653 {
654 dprintf(CRITICAL, "Not an ONFI device\n");
655 /* Not an onfi device. Return error. */
656 onfi_ret = NANDC_RESULT_DEV_NOT_SUPPORTED;
657 goto qpic_nand_onfi_probe_err;
658 }
659
660 dprintf(INFO, "ONFI device found\n");
661 /* Now read the param page */
662 /* Initialize the config */
663 params.cfg.cfg0 = NAND_CFG0_RAW_ONFI_PARAM_PAGE;
664 params.cfg.cfg1 = NAND_CFG1_RAW_ONFI_PARAM_PAGE;
665
666 /* Initialize the cmd and vld */
667 params.dev_cmd1 = (dev_cmd1 & 0xFFFFFF00) | ONFI_READ_PARAM_PAGE_CMD;
668 params.vld = vld & 0xFFFFFFFE;
669
670 /* Initialize the address
671 * addr1 is not used bcos of the cfg.
672 */
673 params.cfg.addr0 = ONFI_READ_PARAM_PAGE_ADDR;
674 params.cfg.addr1 = 0;
675
676 /* Lock the pipe and execute the cmd. */
677 onfi_ret = onfi_probe_cmd_exec(&params, buffer, ONFI_READ_PARAM_PAGE_BUFFER_SIZE);
678 if (onfi_ret)
679 {
680 dprintf(CRITICAL, "ONFI Read param page failed\n");
681 goto qpic_nand_onfi_probe_err;
682 }
683
684 /* Write back vld and cmd and unlock the pipe. */
685 qpic_nand_onfi_probe_cleanup(vld, dev_cmd1);
686
687 /* Verify the integrity of the returned page */
688 param_page = (struct onfi_param_page*)buffer;
689
690 /* TODO: Add CRC check to validate the param page. */
691
692 /* Save the parameter values */
693 onfi_ret = qpic_nand_onfi_save_params(param_page, flash);
694
695qpic_nand_onfi_probe_err:
696 if (onfi_ret)
697 dprintf(CRITICAL, "ONFI probe failed\n");
698
699 free(buffer);
700
701 return onfi_ret;
702}
703
704/* Enquues a desc for a flash cmd with NWD flag set:
705 * cfg: Defines the configuration for the flash cmd.
706 * start: Address where the command elements are added.
707 *
708 * Returns the address where the next cmd element can be added.
709 */
710struct cmd_element*
711qpic_nand_add_cmd_ce(struct cfg_params *cfg,
712 struct cmd_element *start)
713{
714 struct cmd_element *cmd_list_ptr;
715
716 cmd_list_ptr = qpic_nand_add_addr_n_cfg_ce(cfg, start);
717
718 bam_add_cmd_element(cmd_list_ptr, NAND_FLASH_CMD, (uint32_t)cfg->cmd, CE_WRITE_TYPE);
719 cmd_list_ptr++;
720
721 bam_add_cmd_element(cmd_list_ptr, NAND_EXEC_CMD, (uint32_t)cfg->exec, CE_WRITE_TYPE);
722 cmd_list_ptr++;
723
724 return cmd_list_ptr;
725}
726
727/* Reads nand_flash_status and resets nand_flash_status and nand_read_status */
728struct cmd_element*
729qpic_nand_add_read_n_reset_status_ce(struct cmd_element *start,
730 uint32_t *flash_status_read,
731 uint32_t read_status)
732{
733 struct cmd_element *cmd_list_ptr = start;
734 uint32_t flash_status_reset;
735 uint32_t read_status_reset;
736
737 /* Read and reset the status registers. */
738 flash_status_reset = NAND_FLASH_STATUS_RESET;
739 read_status_reset = NAND_READ_STATUS_RESET;
740
Deepa Dinamani0bf2f442012-10-19 11:41:06 -0700741 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 -0700742 cmd_list_ptr++;
743 bam_add_cmd_element(cmd_list_ptr, NAND_FLASH_STATUS, (uint32_t)flash_status_reset, CE_WRITE_TYPE);
744 cmd_list_ptr++;
745
746 if (read_status)
747 {
748 bam_add_cmd_element(cmd_list_ptr, NAND_READ_STATUS, (uint32_t)read_status_reset, CE_WRITE_TYPE);
749 cmd_list_ptr++;
750 }
751
752 return cmd_list_ptr;
753}
754
755struct cmd_element*
756qpic_nand_add_isbad_cmd_ce(struct cfg_params *cfg,
757 struct cmd_element *start)
758{
759 struct cmd_element *cmd_list_ptr = start;
760
761 bam_add_cmd_element(cmd_list_ptr, NAND_DEV0_ECC_CFG, (uint32_t)cfg->ecc_cfg, CE_WRITE_TYPE);
762 cmd_list_ptr++;
763
764 bam_add_cmd_element(cmd_list_ptr, NAND_READ_LOCATION_n(0), (uint32_t)cfg->addr_loc_0, CE_WRITE_TYPE);
765 cmd_list_ptr++;
766
767 cmd_list_ptr = qpic_nand_add_cmd_ce(cfg, cmd_list_ptr);
768
769 return cmd_list_ptr;
770}
771
772static int
773qpic_nand_block_isbad_exec(struct cfg_params *params,
774 uint8_t *bad_block)
775{
776
777 struct cmd_element *cmd_list_ptr = ce_array;
778 struct cmd_element *cmd_list_ptr_start = ce_array;
779 uint8_t desc_flags = BAM_DESC_NWD_FLAG | BAM_DESC_CMD_FLAG
780 | BAM_DESC_LOCK_FLAG | BAM_DESC_INT_FLAG;
781 int num_desc = 0;
782 uint32_t status = 0;
783 int nand_ret = NANDC_RESULT_SUCCESS;
784
785 cmd_list_ptr = qpic_nand_add_isbad_cmd_ce(params, cmd_list_ptr);
786
787 /* Enqueue the desc for the above commands */
788 bam_add_one_desc(&bam,
789 CMD_PIPE_INDEX,
790 (unsigned char*)cmd_list_ptr_start,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -0700791 PA((uint32_t)cmd_list_ptr - (uint32_t)cmd_list_ptr_start),
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700792 desc_flags);
793
794 num_desc++;
795
796 /* Add Data desc */
797 bam_add_desc(&bam,
798 DATA_PRODUCER_PIPE_INDEX,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -0700799 (unsigned char *)PA((addr_t)bad_block),
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700800 4,
801 BAM_DESC_INT_FLAG);
802
803 qpic_nand_wait_for_cmd_exec(num_desc);
804
Deepa Dinamani19530062012-10-03 14:43:05 -0700805 status = qpic_nand_read_reg(NAND_FLASH_STATUS, 0, cmd_list_ptr);
806
807 nand_ret = qpic_nand_check_status(status);
808
809 /* Dummy read to unlock pipe. */
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700810 status = qpic_nand_read_reg(NAND_FLASH_STATUS, BAM_DESC_UNLOCK_FLAG, cmd_list_ptr);
811
Deepa Dinamani19530062012-10-03 14:43:05 -0700812 if (nand_ret)
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700813 return NANDC_RESULT_FAILURE;
814
815 qpic_nand_wait_for_data(DATA_PRODUCER_PIPE_INDEX);
816
817 return nand_ret;
818}
819
820static int
Deepa Dinamanidc1381e2012-11-15 14:53:24 -0800821qpic_nand_block_isbad(unsigned page)
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700822{
823 unsigned cwperpage;
824 struct cfg_params params;
825 uint8_t bad_block[4];
826 unsigned nand_ret = NANDC_RESULT_SUCCESS;
Deepa Dinamanidc1381e2012-11-15 14:53:24 -0800827 uint32_t blk = page / flash.num_pages_per_blk;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700828
Deepa Dinamanidc1381e2012-11-15 14:53:24 -0800829 if (bbtbl[blk] == NAND_BAD_BLK_VALUE_IS_GOOD)
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700830 return NANDC_RESULT_SUCCESS;
Deepa Dinamanidc1381e2012-11-15 14:53:24 -0800831 else if (bbtbl[blk] == NAND_BAD_BLK_VALUE_IS_BAD)
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700832 return NANDC_RESULT_BAD_BLOCK;
833 else
834 {
835 /* Read the bad block value from the flash.
836 * Bad block value is stored in the first page of the block.
837 */
838 /* Read the first page in the block. */
839 cwperpage = flash.cws_per_page;
840
841 /* Read page cmd */
Deepa Dinamanidc1381e2012-11-15 14:53:24 -0800842 params.cmd = NAND_CMD_PAGE_READ_ECC;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700843 /* Clear the CW per page bits */
844 params.cfg0 = cfg0_raw & ~(7U << NAND_DEV0_CFG0_CW_PER_PAGE_SHIFT);
845 params.cfg1 = cfg1_raw;
Deepa Dinamanidc1381e2012-11-15 14:53:24 -0800846 /* addr0 - Write column addr + few bits in row addr upto 32 bits. */
847 params.addr0 = (page << 16) | (USER_DATA_BYTES_PER_CW * cwperpage);
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700848
849 /* addr1 - Write rest of row addr.
850 * This will be all 0s.
851 */
Deepa Dinamanidc1381e2012-11-15 14:53:24 -0800852 params.addr1 = (page >> 16) & 0xff;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700853 params.addr_loc_0 = NAND_RD_LOC_OFFSET(0);
854 params.addr_loc_0 |= NAND_RD_LOC_LAST_BIT(1);
855 params.addr_loc_0 |= NAND_RD_LOC_SIZE(4); /* Read 4 bytes */
Deepa Dinamanidc1381e2012-11-15 14:53:24 -0800856 params.ecc_cfg = ecc_bch_cfg | 0x1; /* Disable ECC */
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700857 params.exec = 1;
858
859 if (qpic_nand_block_isbad_exec(&params, bad_block))
860 {
861 dprintf(CRITICAL,
862 "Could not read bad block value\n");
863 return NANDC_RESULT_FAILURE;
864 }
865
866 if (flash.widebus)
867 {
868 if (bad_block[0] != 0xFF && bad_block[1] != 0xFF)
869 {
Deepa Dinamanidc1381e2012-11-15 14:53:24 -0800870 bbtbl[blk] = NAND_BAD_BLK_VALUE_IS_BAD;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700871 nand_ret = NANDC_RESULT_BAD_BLOCK;
872 }
873 }
874 else if (bad_block[0] != 0xFF)
875 {
Deepa Dinamanidc1381e2012-11-15 14:53:24 -0800876 bbtbl[blk] = NAND_BAD_BLK_VALUE_IS_BAD;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700877 nand_ret = NANDC_RESULT_BAD_BLOCK;
878 }
879 else
Deepa Dinamanidc1381e2012-11-15 14:53:24 -0800880 bbtbl[blk] = NAND_BAD_BLK_VALUE_IS_GOOD;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700881
882 return nand_ret;
883 }
884}
885
886/* Function to erase a block on the nand.
887 * page: Starting page address for the block.
888 */
889static int
890qpic_nand_blk_erase(uint32_t page)
891{
892 struct cfg_params cfg;
893 struct cmd_element *cmd_list_ptr = ce_array;
894 struct cmd_element *cmd_list_ptr_start = ce_array;
895 uint32_t status;
896 int num_desc = 0;
897 uint32_t blk_addr = page / flash.num_pages_per_blk;
Deepa Dinamani19530062012-10-03 14:43:05 -0700898 int nand_ret;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700899
900 /* Erase only if the block is not bad */
Deepa Dinamanidc1381e2012-11-15 14:53:24 -0800901 if (qpic_nand_block_isbad(page))
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700902 {
903 dprintf(CRITICAL,
904 "NAND Erase error: Block address belongs to bad block: %d\n",
905 blk_addr);
906 return NANDC_RESULT_FAILURE;
907 }
908
909 /* Fill in params for the erase flash cmd */
910 cfg.addr0 = page;
911 cfg.addr1 = 0;
912 /* Clear CW_PER_PAGE in cfg0 */
913 cfg.cfg0 = cfg0 & ~(7U << NAND_DEV0_CFG0_CW_PER_PAGE_SHIFT);
914 cfg.cfg1 = cfg1;
915 cfg.cmd = NAND_CMD_BLOCK_ERASE;
916 cfg.exec = 1;
917
918 cmd_list_ptr = qpic_nand_add_cmd_ce(&cfg, cmd_list_ptr);
919
920 /* Enqueue the desc for the above commands */
921 bam_add_one_desc(&bam,
922 CMD_PIPE_INDEX,
923 (unsigned char*)cmd_list_ptr_start,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -0700924 PA((uint32_t)cmd_list_ptr - (uint32_t)cmd_list_ptr_start),
Deepa Dinamani2467bbb2012-10-02 13:59:58 -0700925 BAM_DESC_NWD_FLAG | BAM_DESC_CMD_FLAG | BAM_DESC_INT_FLAG | BAM_DESC_LOCK_FLAG);
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700926
927 cmd_list_ptr_start = cmd_list_ptr;
928 num_desc++;
929
930 qpic_nand_wait_for_cmd_exec(num_desc);
931
932 status = qpic_nand_read_reg(NAND_FLASH_STATUS, 0, cmd_list_ptr);
933
934 cmd_list_ptr++;
935 cmd_list_ptr_start = cmd_list_ptr;
936
937 /* QPIC controller automatically sends
938 * GET_STATUS cmd to the nand card because
939 * of the configuration programmed.
940 * Read the result of GET_STATUS cmd.
941 */
942 cmd_list_ptr = qpic_nand_add_read_n_reset_status_ce(cmd_list_ptr, &status, 1);
943
944 /* Enqueue the desc for the above commands */
945 bam_add_one_desc(&bam,
946 CMD_PIPE_INDEX,
947 (unsigned char*)cmd_list_ptr_start,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -0700948 PA((uint32_t)cmd_list_ptr - (uint32_t)cmd_list_ptr_start),
Deepa Dinamani19530062012-10-03 14:43:05 -0700949 BAM_DESC_INT_FLAG | BAM_DESC_CMD_FLAG) ;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700950
951 num_desc = 1;
952 qpic_nand_wait_for_cmd_exec(num_desc);
953
Deepa Dinamani19530062012-10-03 14:43:05 -0700954 status = qpic_nand_check_status(status);
955
956 /* Dummy read to unlock pipe. */
957 nand_ret = qpic_nand_read_reg(NAND_FLASH_STATUS, BAM_DESC_UNLOCK_FLAG, cmd_list_ptr);
958
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700959 /* Check for status errors*/
Deepa Dinamani19530062012-10-03 14:43:05 -0700960 if (status)
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700961 {
962 dprintf(CRITICAL,
963 "NAND Erase error: Block address belongs to bad block: %d\n",
964 blk_addr);
965 return NANDC_RESULT_FAILURE;
966 }
967
968 /* Check for PROG_ERASE_OP_RESULT bit for the result of erase operation. */
Deepa Dinamani2467bbb2012-10-02 13:59:58 -0700969 if (!(status & PROG_ERASE_OP_RESULT))
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700970 return NANDC_RESULT_SUCCESS;
971
972 return NANDC_RESULT_FAILURE;
973}
974
975/* Return num of desc added. */
Deepa Dinamani19530062012-10-03 14:43:05 -0700976static void
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700977qpic_nand_add_wr_page_cws_cmd_desc(struct cfg_params *cfg,
978 uint32_t status[],
979 enum nand_cfg_value cfg_mode)
980{
981 struct cmd_element *cmd_list_ptr = ce_array;
982 struct cmd_element *cmd_list_ptr_start = ce_array;
983 uint32_t ecc;
984 int num_desc = 0;
985 int int_flag = 0;
986
987 if (cfg_mode == NAND_CFG)
988 ecc = ecc_bch_cfg;
989 else
Deepa Dinamanidc1381e2012-11-15 14:53:24 -0800990 ecc = ecc_bch_cfg | 0x1; /* Disable ECC */
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700991
992 /* Add ECC configuration */
993 bam_add_cmd_element(cmd_list_ptr, NAND_DEV0_ECC_CFG,
994 (uint32_t)ecc, CE_WRITE_TYPE);
995 cmd_list_ptr++;
996 cmd_list_ptr = qpic_nand_add_addr_n_cfg_ce(cfg, cmd_list_ptr);
997
998 bam_add_cmd_element(cmd_list_ptr, NAND_FLASH_CMD,
999 (uint32_t)cfg->cmd, CE_WRITE_TYPE);
1000 cmd_list_ptr++;
1001
1002 /* Enqueue the desc for the above commands */
1003 bam_add_one_desc(&bam,
1004 CMD_PIPE_INDEX,
1005 (unsigned char*)cmd_list_ptr_start,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001006 PA((uint32_t)cmd_list_ptr - (uint32_t)cmd_list_ptr_start),
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001007 BAM_DESC_CMD_FLAG | BAM_DESC_LOCK_FLAG);
1008
1009 num_desc++;
1010
1011 /* Add CE for all the CWs */
1012 for (unsigned i = 0; i < flash.cws_per_page; i++)
1013 {
1014 cmd_list_ptr_start = cmd_list_ptr;
Deepa Dinamani19530062012-10-03 14:43:05 -07001015 int_flag = BAM_DESC_INT_FLAG;
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001016
1017 bam_add_cmd_element(cmd_list_ptr, NAND_EXEC_CMD, (uint32_t)cfg->exec, CE_WRITE_TYPE);
1018 cmd_list_ptr++;
1019
1020 /* Enqueue the desc for the above commands */
1021 bam_add_one_desc(&bam,
1022 CMD_PIPE_INDEX,
1023 (unsigned char*)cmd_list_ptr_start,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001024 PA((uint32_t)cmd_list_ptr - (uint32_t)cmd_list_ptr_start),
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001025 BAM_DESC_NWD_FLAG | BAM_DESC_CMD_FLAG);
1026
1027 num_desc++;
1028 cmd_list_ptr_start = cmd_list_ptr;
1029
1030 /* Set interrupt bit only for the last CW */
1031 if (i == flash.cws_per_page - 1)
1032 {
1033 cmd_list_ptr = qpic_nand_add_read_n_reset_status_ce(cmd_list_ptr,
1034 &status[i],
1035 1);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001036 }
1037 else
1038 cmd_list_ptr = qpic_nand_add_read_n_reset_status_ce(cmd_list_ptr,
1039 &status[i],
1040 0);
1041
1042 /* Enqueue the desc for the above commands */
1043 bam_add_one_desc(&bam,
1044 CMD_PIPE_INDEX,
1045 (unsigned char*)cmd_list_ptr_start,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001046 PA((uint32_t)cmd_list_ptr - (uint32_t)cmd_list_ptr_start),
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001047 int_flag | BAM_DESC_CMD_FLAG);
1048 num_desc++;
Deepa Dinamani19530062012-10-03 14:43:05 -07001049
1050 qpic_nand_wait_for_cmd_exec(num_desc);
1051
1052 status[i] = qpic_nand_check_status(status[i]);
1053
1054 num_desc = 0;
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001055 }
Deepa Dinamani19530062012-10-03 14:43:05 -07001056 return;
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001057}
1058
1059void
1060qpic_add_wr_page_cws_data_desc(const void *buffer,
1061 enum nand_cfg_value cfg_mode,
1062 const void *spareaddr)
1063{
1064 int len;
1065 int flags;
1066 uint32_t start;
1067 unsigned num_desc = 0;
1068
1069 for( unsigned i = 0; i < flash.cws_per_page; i++)
1070 {
1071 flags = 0;
1072
1073 /* Set the interrupt flag on the last CW write for the page. */
1074 if( i == flash.cws_per_page - 1)
1075 flags |= BAM_DESC_INT_FLAG;
1076
1077 if (cfg_mode != NAND_CFG_RAW)
1078 {
1079 start = (uint32_t)buffer + i * DATA_BYTES_IN_IMG_PER_CW;
1080
1081 if (i < (flash.cws_per_page - 1))
1082 {
1083 len = DATA_BYTES_IN_IMG_PER_CW;
1084 flags |= BAM_DESC_EOT_FLAG;
1085 }
1086 else
1087 {
1088 /* Allow space for spare bytes in the last page */
1089 len = USER_DATA_BYTES_PER_CW - ((flash.cws_per_page - 1) << 2);
1090 flags = 0;
1091 }
1092 }
1093 else
1094 {
1095 start = (uint32_t)buffer;
1096 len = flash.cw_size;
1097 flags |= BAM_DESC_EOT_FLAG;
1098 }
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001099 bam_add_one_desc(&bam, DATA_CONSUMER_PIPE_INDEX, (unsigned char*)PA(start), len, flags);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001100 num_desc++;
1101
1102 if ((i == (flash.cws_per_page - 1)) && (cfg_mode == NAND_CFG))
1103 {
1104 /* write extra data */
1105 start = (uint32_t)spareaddr;
1106 len = (flash.cws_per_page << 2);
1107 flags = BAM_DESC_EOT_FLAG | BAM_DESC_INT_FLAG;
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001108 bam_add_one_desc(&bam, DATA_CONSUMER_PIPE_INDEX, (unsigned char*)PA(start), len, flags);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001109 num_desc++;
1110 }
1111 }
1112
1113 bam_sys_gen_event(&bam, DATA_CONSUMER_PIPE_INDEX, num_desc);
1114}
1115
1116static nand_result_t
1117qpic_nand_write_page(uint32_t pg_addr,
1118 enum nand_cfg_value cfg_mode,
1119 const void* buffer,
1120 const void* spareaddr)
1121{
1122 struct cfg_params cfg;
Deepa Dinamani16663a62013-02-07 16:25:59 -08001123 uint32_t status[QPIC_NAND_MAX_CWS_IN_PAGE];
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001124 int nand_ret = NANDC_RESULT_SUCCESS;
1125
1126 if (cfg_mode == NAND_CFG_RAW)
1127 {
1128 cfg.cfg0 = cfg0_raw;
1129 cfg.cfg1 = cfg1_raw;
1130 }
1131 else
1132 {
1133 cfg.cfg0 = cfg0;
1134 cfg.cfg1 = cfg1;
1135 }
1136
1137 cfg.cmd = NAND_CMD_PRG_PAGE;
1138 cfg.exec = 1;
1139
1140 cfg.addr0 = pg_addr << 16;
1141 cfg.addr1 = (pg_addr >> 16) & 0xff;
1142
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001143 qpic_add_wr_page_cws_data_desc(buffer, cfg_mode, spareaddr);
1144
Deepa Dinamani19530062012-10-03 14:43:05 -07001145 qpic_nand_add_wr_page_cws_cmd_desc(&cfg, status, cfg_mode);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001146
1147 /* Check for errors */
1148 for(unsigned i = 0; i < flash.cws_per_page; i++)
1149 {
1150 nand_ret = qpic_nand_check_status(status[i]);
1151 if (nand_ret)
1152 {
1153 dprintf(CRITICAL,
1154 "Failed to write CW %d for page: %d\n",
1155 i, pg_addr);
1156 break;
1157 }
1158 }
1159
1160 /* Wait for data to be available */
1161 qpic_nand_wait_for_data(DATA_CONSUMER_PIPE_INDEX);
1162
1163 return nand_ret;
1164}
1165
1166static int
1167qpic_nand_mark_badblock(uint32_t page)
1168{
1169 char empty_buf[NAND_CW_SIZE_8_BIT_ECC];
1170
1171 memset(empty_buf, 0, NAND_CW_SIZE_8_BIT_ECC);
1172
1173 /* Going to first page of the block */
1174 if (page & flash.num_pages_per_blk_mask)
1175 page = page - (page & flash.num_pages_per_blk_mask);
1176
1177 return qpic_nand_write_page(page, NAND_CFG_RAW, empty_buf, 0);
1178}
1179
1180static void
1181qpic_nand_non_onfi_probe(struct flash_info *flash)
1182{
1183 int dev_found = 0;
1184 unsigned index;
1185 uint32_t ecc_bits;
1186
1187 /* Read the nand id. */
1188 qpic_nand_fetch_id(flash);
1189
1190 /* Check if we support the device */
Deepa Dinamani649a94a2013-03-07 14:37:31 -08001191 for (index = 0; index < (ARRAY_SIZE(supported_flash)); index++)
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001192 {
1193 if ((flash->id & supported_flash[index].mask) ==
1194 (supported_flash[index].flash_id & (supported_flash[index].mask)))
1195 {
1196 dev_found = 1;
1197 break;
1198 }
1199 }
1200
1201 if (dev_found)
1202 {
1203 flash->page_size = supported_flash[index].pagesize;
1204 flash->block_size = supported_flash[index].blksize;
1205 flash->spare_size = supported_flash[index].oobsize;
1206 ecc_bits = supported_flash[index].ecc_8_bits;
1207
1208 /* Make sure that the block size and page size are defined. */
1209 ASSERT(flash->block_size);
1210 ASSERT(flash->page_size);
1211
1212 flash->num_blocks = supported_flash[index].density;
1213 flash->num_blocks /= (flash->block_size);
1214 flash->num_pages_per_blk = flash->block_size / flash->page_size;
1215 flash->num_pages_per_blk_mask = flash->num_pages_per_blk - 1;
1216
1217 /* Look for 8bit BCH ECC Nand, TODO: ECC Correctability >= 8 */
1218 if (ecc_bits)
1219 flash->ecc_width = NAND_WITH_8_BIT_ECC;
1220 else
1221 flash->ecc_width = NAND_WITH_4_BIT_ECC;
1222
1223 flash->density = supported_flash[index].density;
1224 flash->widebus = supported_flash[index].widebus;
1225
1226 return;
1227 }
1228
1229 /* Flash device is not supported, print flash device info and halt */
1230 if (dev_found == 0)
1231 {
1232 dprintf(CRITICAL, "NAND device is not supported: nandid: 0x%x"
1233 "maker=0x%02x device=0x%02x\n",
1234 flash->id,
1235 flash->vendor,
1236 flash->device);
1237 ASSERT(0);
1238 }
1239
1240 dprintf(INFO, "nandid: 0x%x maker=0x%02x device=0x%02x page_size=%d\n",
1241 flash->id,
1242 flash->vendor,
1243 flash->device,
1244 flash->page_size);
1245
1246 dprintf(INFO, "spare_size=%d block_size=%d num_blocks=%d\n",
1247 flash->spare_size,
1248 flash->block_size,
1249 flash->num_blocks);
1250}
1251
1252void
1253qpic_nand_init(struct qpic_nand_init_config *config)
1254{
1255 uint32_t i;
1256 int nand_ret;
1257
1258 nand_base = config->nand_base;
1259
Deepa Dinamanie9ded132012-11-27 15:03:38 -08001260 qpic_bam_init(config);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001261
Deepa Dinamani649a94a2013-03-07 14:37:31 -08001262 qpic_nand_non_onfi_probe(&flash);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001263
1264 /* Save the RAW and read/write configs */
1265 qpic_nand_save_config(&flash);
1266
1267 flash_spare_bytes = (unsigned char *)malloc(flash.spare_size);
1268
1269 if (flash_spare_bytes == NULL)
1270 {
1271 dprintf(CRITICAL, "Failed to allocate memory for spare bytes\n");
1272 return;
1273 }
1274
1275 /* Create a bad block table */
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001276 bbtbl = (uint8_t *) malloc(sizeof(uint8_t) * flash.num_blocks);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001277
1278 if (bbtbl == NULL)
1279 {
1280 dprintf(CRITICAL, "Failed to allocate memory for bad block table\n");
1281 return;
1282 }
1283
1284 for (i = 0; i < flash.num_blocks; i++)
1285 bbtbl[i] = NAND_BAD_BLK_VALUE_NOT_READ;
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001286
1287 /* Set aside contiguous memory for reads/writes.
1288 * This is needed as the BAM transfers only work with
1289 * physically contiguous buffers.
1290 * We will copy any data to be written/ to be read from
1291 * nand to this buffer and this buffer will be submitted to BAM.
1292 */
1293 rdwr_buf = (uint8_t*) malloc(flash.page_size + flash.spare_size);
1294
1295 if (rdwr_buf == NULL)
1296 {
1297 dprintf(CRITICAL, "Failed to allocate memory for page reads or writes\n");
1298 return;
1299 }
1300
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001301}
1302
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -07001303unsigned
1304flash_page_size(void)
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001305{
1306 return flash.page_size;
1307}
1308
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -07001309unsigned
1310flash_block_size(void)
1311{
1312 return flash.block_size;
1313}
1314
Deepa Dinamani8e6b2432012-10-17 17:12:44 -07001315unsigned
1316flash_num_blocks(void)
1317{
1318 return flash.num_blocks;
1319}
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -07001320
1321struct ptable *
1322flash_get_ptable(void)
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001323{
1324 return flash_ptable;
1325}
1326
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -07001327void
Deepa Dinamani87feab82012-10-04 14:28:05 -07001328qpic_nand_uninit()
1329{
1330 bam_pipe_reset(&bam, DATA_PRODUCER_PIPE_INDEX);
1331 bam_pipe_reset(&bam, DATA_CONSUMER_PIPE_INDEX);
1332 bam_pipe_reset(&bam, CMD_PIPE_INDEX);
1333
1334}
1335void
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -07001336flash_set_ptable(struct ptable *new_ptable)
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001337{
1338 ASSERT(flash_ptable == NULL && new_ptable != NULL);
1339 flash_ptable = new_ptable;
1340}
1341
1342/* Note: No support for raw reads. */
1343static int
1344qpic_nand_read_page(uint32_t page, unsigned char* buffer, unsigned char* spareaddr)
1345{
1346 struct cfg_params params;
1347 uint32_t ecc;
Deepa Dinamani16663a62013-02-07 16:25:59 -08001348 uint32_t flash_sts[QPIC_NAND_MAX_CWS_IN_PAGE];
1349 uint32_t buffer_sts[QPIC_NAND_MAX_CWS_IN_PAGE];
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001350 uint32_t addr_loc_0;
1351 uint32_t addr_loc_1;
1352 struct cmd_element *cmd_list_ptr = ce_array;
1353 struct cmd_element *cmd_list_ptr_start = ce_array;
1354 uint32_t num_cmd_desc = 0;
1355 uint32_t num_data_desc = 0;
1356 uint32_t status;
1357 uint32_t i;
1358 int nand_ret = NANDC_RESULT_SUCCESS;
Sundarajan Srinivasan024bda52014-02-27 16:48:48 -08001359 uint8_t flags = 0;
1360 uint32_t *cmd_list_temp = NULL;
1361
1362 uint32_t temp_status = 0;
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001363 /* UD bytes in last CW is 512 - cws_per_page *4.
1364 * Since each of the CW read earlier reads 4 spare bytes.
1365 */
1366 uint16_t ud_bytes_in_last_cw = USER_DATA_BYTES_PER_CW - ((flash.cws_per_page - 1) << 2);
1367 uint16_t oob_bytes = DATA_BYTES_IN_IMG_PER_CW - ud_bytes_in_last_cw;
1368
1369 params.addr0 = page << 16;
1370 params.addr1 = (page >> 16) & 0xff;
1371 params.cfg0 = cfg0;
1372 params.cfg1 = cfg1;
1373 params.cmd = NAND_CMD_PAGE_READ_ALL;
1374 params.exec = 1;
1375 ecc = ecc_bch_cfg;
1376
1377 /* Read all the Data bytes in the first 3 CWs. */
1378 addr_loc_0 = NAND_RD_LOC_OFFSET(0);
1379 addr_loc_0 |= NAND_RD_LOC_SIZE(DATA_BYTES_IN_IMG_PER_CW);
1380 addr_loc_0 |= NAND_RD_LOC_LAST_BIT(1);
1381
1382
1383 addr_loc_1 = NAND_RD_LOC_OFFSET(ud_bytes_in_last_cw);
1384 addr_loc_1 |= NAND_RD_LOC_SIZE(oob_bytes);
1385 addr_loc_1 |= NAND_RD_LOC_LAST_BIT(1);
1386
Deepa Dinamanidc1381e2012-11-15 14:53:24 -08001387 status = qpic_nand_block_isbad(page);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001388
1389 if (status)
1390 return status;
1391
sundarajan srinivasan7ced6482013-03-21 16:01:18 -07001392 /* Reset and Configure erased CW/page detection controller */
1393 qpic_nand_erased_status_reset(ce_array, BAM_DESC_LOCK_FLAG);
1394
Sundarajan Srinivasan024bda52014-02-27 16:48:48 -08001395 /* Queue up the command and data descriptors for all the codewords in a page
1396 * and do a single bam transfer at the end.*/
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001397 for (i = 0; i < flash.cws_per_page; i++)
1398 {
1399 num_cmd_desc = 0;
1400 num_data_desc = 0;
1401
1402 if (i == 0)
1403 {
1404 cmd_list_ptr = qpic_nand_add_addr_n_cfg_ce(&params, cmd_list_ptr);
1405
1406 bam_add_cmd_element(cmd_list_ptr, NAND_DEV0_ECC_CFG,(uint32_t)ecc, CE_WRITE_TYPE);
1407 cmd_list_ptr++;
1408 }
1409 else
1410 cmd_list_ptr_start = cmd_list_ptr;
1411
1412 bam_add_cmd_element(cmd_list_ptr, NAND_FLASH_CMD, (uint32_t)params.cmd, CE_WRITE_TYPE);
1413 cmd_list_ptr++;
1414
1415 if (i == flash.cws_per_page - 1)
1416 {
1417 addr_loc_0 = NAND_RD_LOC_OFFSET(0);
1418 addr_loc_0 |= NAND_RD_LOC_SIZE(ud_bytes_in_last_cw);
1419 addr_loc_0 |= NAND_RD_LOC_LAST_BIT(0);
1420
1421 /* Write addr loc 1 only for the last CW. */
1422 bam_add_cmd_element(cmd_list_ptr, NAND_READ_LOCATION_n(1), (uint32_t)addr_loc_1, CE_WRITE_TYPE);
1423 cmd_list_ptr++;
1424
1425 /* Add Data desc */
1426 bam_add_one_desc(&bam,
1427 DATA_PRODUCER_PIPE_INDEX,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001428 (unsigned char *)PA((addr_t)buffer),
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001429 ud_bytes_in_last_cw,
1430 0);
1431 num_data_desc++;
1432
1433 bam_add_one_desc(&bam,
1434 DATA_PRODUCER_PIPE_INDEX,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001435 (unsigned char *)PA((addr_t)spareaddr),
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001436 oob_bytes,
1437 BAM_DESC_INT_FLAG);
1438 num_data_desc++;
1439
1440 bam_sys_gen_event(&bam, DATA_PRODUCER_PIPE_INDEX, num_data_desc);
1441 }
1442 else
1443 {
1444 /* Add Data desc */
1445 bam_add_one_desc(&bam,
1446 DATA_PRODUCER_PIPE_INDEX,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001447 (unsigned char *)PA((addr_t)buffer),
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001448 DATA_BYTES_IN_IMG_PER_CW,
Sundarajan Srinivasan024bda52014-02-27 16:48:48 -08001449 0);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001450 num_data_desc++;
1451 bam_sys_gen_event(&bam, DATA_PRODUCER_PIPE_INDEX, num_data_desc);
1452 }
1453
1454 /* Write addr loc 0. */
1455 bam_add_cmd_element(cmd_list_ptr,
1456 NAND_READ_LOCATION_n(0),
1457 (uint32_t)addr_loc_0,
1458 CE_WRITE_TYPE);
1459
1460 cmd_list_ptr++;
1461 bam_add_cmd_element(cmd_list_ptr,
1462 NAND_EXEC_CMD,
1463 (uint32_t)params.exec,
1464 CE_WRITE_TYPE);
1465 cmd_list_ptr++;
1466
Sundarajan Srinivasan024bda52014-02-27 16:48:48 -08001467 /* Enqueue the desc for the above commands */
1468 bam_add_one_desc(&bam,
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001469 CMD_PIPE_INDEX,
1470 (unsigned char*)cmd_list_ptr_start,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001471 PA((uint32_t)cmd_list_ptr - (uint32_t)cmd_list_ptr_start),
Sundarajan Srinivasan024bda52014-02-27 16:48:48 -08001472 BAM_DESC_NWD_FLAG | BAM_DESC_CMD_FLAG);
1473 num_cmd_desc++;
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001474
Sundarajan Srinivasan024bda52014-02-27 16:48:48 -08001475 bam_add_cmd_element(cmd_list_ptr, NAND_FLASH_STATUS, (uint32_t)PA((addr_t)&(flash_sts[i])), CE_READ_TYPE);
1476
1477 cmd_list_temp = cmd_list_ptr;
1478
1479 cmd_list_ptr++;
1480
1481 bam_add_cmd_element(cmd_list_ptr, NAND_BUFFER_STATUS, (uint32_t)PA((addr_t)&(buffer_sts[i])), CE_READ_TYPE);
1482 cmd_list_ptr++;
1483
1484 if (i == flash.cws_per_page - 1)
1485 {
1486 flags = BAM_DESC_CMD_FLAG | BAM_DESC_UNLOCK_FLAG;
1487 }
1488 else
1489 flags = BAM_DESC_CMD_FLAG;
1490
1491 /* Enqueue the desc for the above command */
1492 bam_add_one_desc(&bam,
1493 CMD_PIPE_INDEX,
1494 (unsigned char*)PA((addr_t)cmd_list_temp),
1495 PA((uint32_t)cmd_list_ptr - (uint32_t)cmd_list_temp),
1496 flags);
1497 num_cmd_desc++;
1498
1499 buffer += DATA_BYTES_IN_IMG_PER_CW;
1500
1501 /* Notify BAM HW about the newly added descriptors */
1502 bam_sys_gen_event(&bam, CMD_PIPE_INDEX, num_cmd_desc);
1503 }
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001504
1505 qpic_nand_wait_for_data(DATA_PRODUCER_PIPE_INDEX);
1506
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001507 /* Check status */
1508 for (i = 0; i < flash.cws_per_page ; i ++)
Sundarajan Srinivasan024bda52014-02-27 16:48:48 -08001509 {
1510 flash_sts[i] = qpic_nand_check_status(flash_sts[i]);
Deepa Dinamani19530062012-10-03 14:43:05 -07001511 if (flash_sts[i])
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001512 {
1513 nand_ret = NANDC_RESULT_BAD_PAGE;
Sundarajan Srinivasan024bda52014-02-27 16:48:48 -08001514 dprintf(CRITICAL, "NAND page read failed. page: %x status %x\n", page, flash_sts[i]);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001515 goto qpic_nand_read_page_error;
1516 }
Sundarajan Srinivasan024bda52014-02-27 16:48:48 -08001517 }
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001518qpic_nand_read_page_error:
1519return nand_ret;
1520}
1521
1522/* Function to read a flash partition.
1523 * ptn : Partition to read.
1524 * extra_per_page : Spare data to be read.
1525 * offset : Num of bytes offset into the partition.
1526 * data : Buffer to read the data into.
1527 * bytes : Num of bytes to be read.
1528 */
1529 /* TODO: call this func read_partition. */
1530int
1531flash_read_ext(struct ptentry *ptn,
1532 unsigned extra_per_page,
1533 unsigned offset,
1534 void *data,
1535 unsigned bytes)
1536{
1537 uint32_t page =
1538 (ptn->start * flash.num_pages_per_blk) + (offset / flash.page_size);
1539 uint32_t lastpage = (ptn->start + ptn->length) * flash.num_pages_per_blk;
1540 uint32_t count =
1541 (bytes + flash.page_size - 1 + extra_per_page) / (flash.page_size +
1542 extra_per_page);
1543 uint32_t *spare = (unsigned *)flash_spare_bytes;
1544 uint32_t errors = 0;
1545 unsigned char *image = data;
1546 int result = 0;
1547 uint32_t current_block =
1548 (page - (page & flash.num_pages_per_blk_mask)) / flash.num_pages_per_blk;
1549 uint32_t start_block = ptn->start;
1550 uint32_t start_block_count = 0;
1551 uint32_t isbad = 0;
Deepa Dinamani2f7006c2013-08-19 11:59:38 -07001552 uint32_t current_page;
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001553
1554 /* Verify first byte is at page boundary. */
1555 if (offset & (flash.page_size - 1))
1556 {
1557 dprintf(CRITICAL, "Read request start not at page boundary: %d\n",
1558 offset);
1559 return NANDC_RESULT_PARAM_INVALID;
1560 }
1561
Deepa Dinamani2f7006c2013-08-19 11:59:38 -07001562 current_page = start_block * flash.num_pages_per_blk;
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001563 /* Adjust page offset based on number of bad blocks from start to current page */
1564 if (start_block < current_block)
1565 {
1566 start_block_count = (current_block - start_block);
1567 while (start_block_count
1568 && (start_block < (ptn->start + ptn->length)))
1569 {
Deepa Dinamani2f7006c2013-08-19 11:59:38 -07001570 isbad = qpic_nand_block_isbad(current_page);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001571 if (isbad)
1572 page += flash.num_pages_per_blk;
1573 else
1574 start_block_count--;
1575 start_block++;
Deepa Dinamani2f7006c2013-08-19 11:59:38 -07001576 current_page += flash.num_pages_per_blk;
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001577 }
1578 }
1579
1580 while ((page < lastpage) && !start_block_count)
1581 {
1582 if (count == 0)
1583 {
Deepa Dinamani52aca8d2013-02-05 11:41:41 -08001584 dprintf(SPEW, "flash_read_image: success (%d errors)\n",
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001585 errors);
1586 return NANDC_RESULT_SUCCESS;
1587 }
1588
Sundarajan Srinivasan29d927c2014-02-10 14:11:24 -08001589#if CONTIGUOUS_MEMORY
1590 result = qpic_nand_read_page(page, image, (unsigned char *) spare);
1591#else
1592 result = qpic_nand_read_page(page, rdwr_buf, (unsigned char *) spare);
1593#endif
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001594 if (result == NANDC_RESULT_BAD_PAGE)
1595 {
1596 /* bad page, go to next page. */
1597 page++;
1598 errors++;
1599 continue;
1600 }
1601 else if (result == NANDC_RESULT_BAD_BLOCK)
1602 {
1603 /* bad block, go to next block same offset. */
1604 page += flash.num_pages_per_blk;
1605 errors++;
1606 continue;
1607 }
1608
Sundarajan Srinivasan29d927c2014-02-10 14:11:24 -08001609#ifndef CONTIGUOUS_MEMORY
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001610 /* Copy the read page into correct location. */
1611 memcpy(image, rdwr_buf, flash.page_size);
Sundarajan Srinivasan29d927c2014-02-10 14:11:24 -08001612#endif
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001613 page++;
1614 image += flash.page_size;
1615 /* Copy spare bytes to image */
Sundarajan Srinivasan29d927c2014-02-10 14:11:24 -08001616 if(extra_per_page)
1617 {
1618 memcpy(image, spare, extra_per_page);
1619 image += extra_per_page;
1620 }
1621
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001622 count -= 1;
1623 }
1624
1625 /* could not find enough valid pages before we hit the end */
1626 dprintf(CRITICAL, "flash_read_image: failed (%d errors)\n", errors);
1627 return NANDC_RESULT_FAILURE;
1628}
1629
1630int
1631flash_erase(struct ptentry *ptn)
1632{
Deepa Dinamani2467bbb2012-10-02 13:59:58 -07001633 int ret = 0;
1634
1635 ret = qpic_nand_blk_erase(ptn->start * flash.num_pages_per_blk);
1636
1637 if (ret)
1638 dprintf(CRITICAL, "Erase operation failed \n");
1639
1640 return ret;
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001641}
Deepa Dinamani2467bbb2012-10-02 13:59:58 -07001642
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001643int
1644flash_ecc_bch_enabled()
1645{
1646 return (flash.ecc_width == NAND_WITH_4_BIT_ECC)? 0 : 1;
1647}
1648
1649int
1650flash_write(struct ptentry *ptn,
Deepa Dinamanic13d5942013-04-30 15:48:53 -07001651 unsigned write_extra_bytes,
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001652 const void *data,
1653 unsigned bytes)
1654{
1655 uint32_t page = ptn->start * flash.num_pages_per_blk;
1656 uint32_t lastpage = (ptn->start + ptn->length) * flash.num_pages_per_blk;
1657 uint32_t *spare = (unsigned *)flash_spare_bytes;
1658 const unsigned char *image = data;
Deepa Dinamanic13d5942013-04-30 15:48:53 -07001659 uint32_t wsize;
Sundarajan Srinivasan223d7002014-02-11 19:48:11 -08001660 uint32_t spare_byte_count = 0;
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001661 int r;
1662
Sundarajan Srinivasan223d7002014-02-11 19:48:11 -08001663 spare_byte_count = ((flash.cw_size * flash.cws_per_page)- flash.page_size);
1664
Deepa Dinamanic13d5942013-04-30 15:48:53 -07001665 if(write_extra_bytes)
Sundarajan Srinivasan223d7002014-02-11 19:48:11 -08001666 wsize = flash.page_size + spare_byte_count;
Deepa Dinamanic13d5942013-04-30 15:48:53 -07001667 else
1668 wsize = flash.page_size;
1669
Sundarajan Srinivasan223d7002014-02-11 19:48:11 -08001670 memset(spare, 0xff, (spare_byte_count / flash.cws_per_page));
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001671
1672 while (bytes > 0)
1673 {
1674 if (bytes < wsize)
1675 {
1676 dprintf(CRITICAL,
1677 "flash_write_image: image undersized (%d < %d)\n",
1678 bytes,
1679 wsize);
1680 return -1;
1681 }
1682
1683 if (page >= lastpage)
1684 {
1685 dprintf(CRITICAL, "flash_write_image: out of space\n");
1686 return -1;
1687 }
1688
1689 if ((page & flash.num_pages_per_blk_mask) == 0)
1690 {
Deepa Dinamani2467bbb2012-10-02 13:59:58 -07001691 if (qpic_nand_blk_erase(page))
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001692 {
1693 dprintf(INFO,
1694 "flash_write_image: bad block @ %d\n",
1695 page / flash.num_pages_per_blk);
1696
1697 page += flash.num_pages_per_blk;
1698 continue;
1699 }
1700 }
1701
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001702 memcpy(rdwr_buf, image, flash.page_size);
1703
Deepa Dinamanic13d5942013-04-30 15:48:53 -07001704 if (write_extra_bytes)
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001705 {
Sundarajan Srinivasan223d7002014-02-11 19:48:11 -08001706 memcpy(rdwr_buf + flash.page_size, image + flash.page_size, spare_byte_count);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001707 r = qpic_nand_write_page(page,
1708 NAND_CFG,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001709 rdwr_buf,
1710 rdwr_buf + flash.page_size);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001711 }
1712 else
1713 {
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001714 r = qpic_nand_write_page(page, NAND_CFG, rdwr_buf, spare);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001715 }
1716
1717 if (r)
1718 {
1719 dprintf(INFO,
1720 "flash_write_image: write failure @ page %d (src %d)\n",
1721 page,
1722 image - (const unsigned char *)data);
1723
1724 image -= (page & flash.num_pages_per_blk_mask) * wsize;
1725 bytes += (page & flash.num_pages_per_blk_mask) * wsize;
1726 page &= ~flash.num_pages_per_blk_mask;
1727 if (qpic_nand_blk_erase(page))
1728 {
1729 dprintf(INFO,
1730 "flash_write_image: erase failure @ page %d\n",
1731 page);
1732 }
1733
1734 qpic_nand_mark_badblock(page);
1735
1736 dprintf(INFO,
1737 "flash_write_image: restart write @ page %d (src %d)\n",
1738 page, image - (const unsigned char *)data);
1739
1740 page += flash.num_pages_per_blk;
1741 continue;
1742 }
1743 page++;
1744 image += wsize;
1745 bytes -= wsize;
1746 }
1747
1748 /* erase any remaining pages in the partition */
1749 page = (page + flash.num_pages_per_blk_mask) & (~flash.num_pages_per_blk_mask);
1750
1751 while (page < lastpage)
1752 {
1753 if (qpic_nand_blk_erase(page))
1754 {
1755 dprintf(INFO, "flash_write_image: bad block @ %d\n",
1756 page / flash.num_pages_per_blk);
1757 }
1758 page += flash.num_pages_per_blk;
1759 }
1760
1761 dprintf(INFO, "flash_write_image: success\n");
1762 return 0;
1763}
Smita Ghoshf5431c62014-09-18 14:11:14 -07001764
1765uint32_t nand_device_base()
1766{
1767 return nand_base;
1768}