blob: efe41887258917d2ca3ca582673739e2a08a6d73 [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
Sridhar Parasuramf5188d82014-11-17 15:39:55 -080051struct cmd_element ce_array[100] __attribute__ ((aligned(16)));
52struct cmd_element ce_read_array[20] __attribute__ ((aligned(16)));
Deepa Dinamanie4573be2012-08-03 16:32:29 -070053
54#define QPIC_BAM_DATA_FIFO_SIZE 64
55#define QPIC_BAM_CMD_FIFO_SIZE 64
56
57static struct bam_desc cmd_desc_fifo[QPIC_BAM_CMD_FIFO_SIZE] __attribute__ ((aligned(BAM_DESC_SIZE)));
58static struct bam_desc data_desc_fifo[QPIC_BAM_DATA_FIFO_SIZE] __attribute__ ((aligned(BAM_DESC_SIZE)));
59
60static struct bam_instance bam;
61static uint8_t *bbtbl;
62
Deepa Dinamani0bf2f442012-10-19 11:41:06 -070063static uint8_t* rdwr_buf;
64
Deepa Dinamanie4573be2012-08-03 16:32:29 -070065static struct flash_id supported_flash[] = {
Deepa Dinamani649a94a2013-03-07 14:37:31 -080066 /* Flash ID ID Mask Density(MB) Wid Pgsz Blksz oobsz 8-bit ECCf */
67 {0x1590AC2C, 0xFFFFFFFF, 0x20000000, 0, 2048, 0x00020000, 0x40, 0},
Sundarajan Srinivasand4e21952013-08-27 15:59:10 -070068 {0x1590AA2C, 0xFFFFFFFF, 0x10000000, 0, 2048, 0x00020000, 0xE0, 1},
Deepa Dinamani649a94a2013-03-07 14:37:31 -080069 {0x2690AC2C, 0xFFFFFFFF, 0x20000000, 0, 4096, 0x00040000, 0xE0, 1},
Sundarajan Srinivasand69c0d32013-08-09 16:47:33 -070070 {0x1590ACAD, 0xFFFFFFFF, 0x20000000, 0, 2048, 0x00020000, 0x80, 0},
Joonwoo Park342b2362014-08-25 15:41:39 -070071 {0x9590DC2C, 0xFFFFFFFF, 0x10000000, 0, 2048, 0x00020000, 0x40, 0},
Channagoud Kadabi12b96932014-09-23 15:18:11 -070072 {0x1590aa98, 0xFFFFFFFF, 0x10000000, 0, 2048, 0x00020000, 0x80, 1},
Deepa Dinamanie4573be2012-08-03 16:32:29 -070073 /* Note: Width flag is 0 for 8 bit Flash and 1 for 16 bit flash */
Deepa Dinamanie4573be2012-08-03 16:32:29 -070074};
75
Deepa Dinamanie4573be2012-08-03 16:32:29 -070076static void
77qpic_nand_wait_for_cmd_exec(uint32_t num_desc)
78{
79 /* Create a read/write event to notify the periperal of the added desc. */
80 bam_sys_gen_event(&bam, CMD_PIPE_INDEX, num_desc);
81
82 /* Wait for the descriptors to be processed */
83 bam_wait_for_interrupt(&bam, CMD_PIPE_INDEX, P_PRCSD_DESC_EN_MASK);
84
85 /* Read offset update for the circular FIFO */
86 bam_read_offset_update(&bam, CMD_PIPE_INDEX);
87}
88
89static void
90qpic_nand_wait_for_data(uint32_t pipe_num)
91{
92 /* Wait for the descriptors to be processed */
93 bam_wait_for_interrupt(&bam, pipe_num, P_PRCSD_DESC_EN_MASK);
94
95 /* Read offset update for the circular FIFO */
96 bam_read_offset_update(&bam, pipe_num);
97}
98
99static uint32_t
100qpic_nand_read_reg(uint32_t reg_addr,
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800101 uint8_t flags)
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700102{
103 uint32_t val;
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800104 struct cmd_element *cmd_list_read_ptr = ce_read_array;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700105
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800106 bam_add_cmd_element(cmd_list_read_ptr, reg_addr, (uint32_t)PA((addr_t)&val), CE_READ_TYPE);
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700107
108 /* Enqueue the desc for the above command */
109 bam_add_one_desc(&bam,
110 CMD_PIPE_INDEX,
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800111 (unsigned char*)PA((addr_t)cmd_list_read_ptr),
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700112 BAM_CE_SIZE,
113 BAM_DESC_CMD_FLAG| BAM_DESC_INT_FLAG | flags);
114
115 qpic_nand_wait_for_cmd_exec(1);
116
117 return val;
118}
119
Deepa Dinamani19530062012-10-03 14:43:05 -0700120/* Assume the BAM is in a locked state. */
121void
sundarajan srinivasan7ced6482013-03-21 16:01:18 -0700122qpic_nand_erased_status_reset(struct cmd_element *cmd_list_ptr, uint8_t flags)
Deepa Dinamani19530062012-10-03 14:43:05 -0700123{
124 uint32_t val = 0;
125
126 /* Reset the Erased Codeword/Page detection controller. */
127 val = NAND_ERASED_CW_DETECT_CFG_RESET_CTRL;
128
129 bam_add_cmd_element(cmd_list_ptr, NAND_ERASED_CW_DETECT_CFG, val, CE_WRITE_TYPE);
130
131 /* Enqueue the desc for the above command */
132 bam_add_one_desc(&bam,
133 CMD_PIPE_INDEX,
134 (unsigned char*)cmd_list_ptr,
135 BAM_CE_SIZE,
sundarajan srinivasan7ced6482013-03-21 16:01:18 -0700136 BAM_DESC_CMD_FLAG | BAM_DESC_INT_FLAG | flags);
Deepa Dinamani19530062012-10-03 14:43:05 -0700137
138 qpic_nand_wait_for_cmd_exec(1);
139
140 /* Enable the Erased Codeword/Page detection
141 * controller to check the data as it arrives.
142 * Also disable ECC reporting for an erased CW.
143 */
144 val = NAND_ERASED_CW_DETECT_CFG_ACTIVATE_CTRL | NAND_ERASED_CW_DETECT_ERASED_CW_ECC_MASK;
145
146 bam_add_cmd_element(cmd_list_ptr, NAND_ERASED_CW_DETECT_CFG, val, CE_WRITE_TYPE);
147
148 /* Enqueue the desc for the above command */
149 bam_add_one_desc(&bam,
150 CMD_PIPE_INDEX,
151 (unsigned char*)cmd_list_ptr,
152 BAM_CE_SIZE,
153 BAM_DESC_CMD_FLAG | BAM_DESC_INT_FLAG);
154
155 qpic_nand_wait_for_cmd_exec(1);
156}
157
158static nand_result_t
159qpic_nand_check_status(uint32_t status)
160{
161 uint32_t erase_sts;
162
163 /* Check for errors */
164 if (status & NAND_FLASH_ERR)
165 {
166 /* Check if this is an ECC error on an erased page. */
167 if (status & NAND_FLASH_OP_ERR)
168 {
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800169 erase_sts = qpic_nand_read_reg(NAND_ERASED_CW_DETECT_STATUS, 0);
Deepa Dinamani19530062012-10-03 14:43:05 -0700170 if ((erase_sts & (1 << NAND_ERASED_CW_DETECT_STATUS_PAGE_ALL_ERASED)))
171 {
172 /* Mask the OP ERROR. */
173 status &= ~NAND_FLASH_OP_ERR;
sundarajan srinivasan7ced6482013-03-21 16:01:18 -0700174 qpic_nand_erased_status_reset(ce_array, 0);
Deepa Dinamani19530062012-10-03 14:43:05 -0700175 }
176 }
177
178 /* ECC error flagged on an erased page read.
179 * Ignore and return success.
180 */
181 if (!(status & NAND_FLASH_ERR))
182 return NANDC_RESULT_SUCCESS;
183
184 dprintf(CRITICAL, "Nand Flash error. Status = %d\n", status);
185
186 if (status & NAND_FLASH_TIMEOUT_ERR)
187 return NANDC_RESULT_TIMEOUT;
188 else
189 return NANDC_RESULT_FAILURE;
190 }
191
192 return NANDC_RESULT_SUCCESS;
193}
194
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700195static uint32_t
196qpic_nand_fetch_id(struct flash_info *flash)
197{
198 struct cmd_element *cmd_list_ptr = ce_array;
199 struct cmd_element *cmd_list_ptr_start = ce_array;
200 int num_desc = 0;
201 uint32_t status;
202 uint32_t id;
203 uint32_t flash_cmd = NAND_CMD_FETCH_ID;
204 uint32_t exec_cmd = 1;
205 int nand_ret = NANDC_RESULT_SUCCESS;
206
207 /* Issue the Fetch id command to the NANDc */
208 bam_add_cmd_element(cmd_list_ptr, NAND_FLASH_CMD, (uint32_t)flash_cmd, CE_WRITE_TYPE);
209 cmd_list_ptr++;
210
211 /* Execute the cmd */
212 bam_add_cmd_element(cmd_list_ptr, NAND_EXEC_CMD, (uint32_t)exec_cmd, CE_WRITE_TYPE);
213 cmd_list_ptr++;
214
215 /* Prepare the cmd desc for the above commands */
216 bam_add_one_desc(&bam,
217 CMD_PIPE_INDEX,
218 (unsigned char*)cmd_list_ptr_start,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -0700219 PA((uint32_t)cmd_list_ptr - (uint32_t)cmd_list_ptr_start),
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700220 BAM_DESC_LOCK_FLAG | BAM_DESC_INT_FLAG |
221 BAM_DESC_NWD_FLAG | BAM_DESC_CMD_FLAG);
222
223 /* Keep track of the number of desc added. */
224 num_desc++;
225 qpic_nand_wait_for_cmd_exec(num_desc);
226
227 cmd_list_ptr_start = ce_array;
228 cmd_list_ptr = ce_array;
229
230 /* Read the status register */
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800231 status = qpic_nand_read_reg(NAND_FLASH_STATUS, 0);
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700232
233 /* Check for errors */
234 nand_ret = qpic_nand_check_status(status);
235 if (nand_ret)
236 {
237 dprintf( CRITICAL, "Read ID cmd status failed\n");
238 goto qpic_nand_fetch_id_err;
239 }
240
241 /* Read the id */
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800242 id = qpic_nand_read_reg(NAND_READ_ID, BAM_DESC_UNLOCK_FLAG);
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700243
244 flash->id = id;
245 flash->vendor = id & 0xff;
246 flash->device = (id >> 8) & 0xff;
247 flash->dev_cfg = (id >> 24) & 0xFF;
248 flash->widebus = 0;
249 flash->widebus &= (id >> 24) & 0xFF;
250 flash->widebus = flash->widebus? 1: 0;
251
252qpic_nand_fetch_id_err:
253 return nand_ret;
254}
255
256static int
Deepa Dinamanie9ded132012-11-27 15:03:38 -0800257qpic_bam_init(struct qpic_nand_init_config *config)
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700258{
259 uint32_t bam_ret = NANDC_RESULT_SUCCESS;
260
Deepa Dinamanie9ded132012-11-27 15:03:38 -0800261 bam.base = config->bam_base;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700262 /* Set Read pipe params. */
Deepa Dinamanie9ded132012-11-27 15:03:38 -0800263 bam.pipe[DATA_PRODUCER_PIPE_INDEX].pipe_num = config->pipes.read_pipe;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700264 /* System consumer */
265 bam.pipe[DATA_PRODUCER_PIPE_INDEX].trans_type = BAM2SYS;
266 bam.pipe[DATA_PRODUCER_PIPE_INDEX].fifo.size = QPIC_BAM_DATA_FIFO_SIZE;
267 bam.pipe[DATA_PRODUCER_PIPE_INDEX].fifo.head = data_desc_fifo;
Deepa Dinamani536d3f82013-07-09 13:05:56 -0700268 bam.pipe[DATA_PRODUCER_PIPE_INDEX].lock_grp = config->pipes.read_pipe_grp;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700269
270 /* Set Write pipe params. */
Deepa Dinamanie9ded132012-11-27 15:03:38 -0800271 bam.pipe[DATA_CONSUMER_PIPE_INDEX].pipe_num = config->pipes.write_pipe;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700272 /* System producer */
273 bam.pipe[DATA_CONSUMER_PIPE_INDEX].trans_type = SYS2BAM;
274 bam.pipe[DATA_CONSUMER_PIPE_INDEX].fifo.size = QPIC_BAM_DATA_FIFO_SIZE;
275 bam.pipe[DATA_CONSUMER_PIPE_INDEX].fifo.head = data_desc_fifo;
Deepa Dinamani536d3f82013-07-09 13:05:56 -0700276 bam.pipe[DATA_CONSUMER_PIPE_INDEX].lock_grp = config->pipes.write_pipe_grp;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700277
278 /* Set Cmd pipe params. */
Deepa Dinamanie9ded132012-11-27 15:03:38 -0800279 bam.pipe[CMD_PIPE_INDEX].pipe_num = config->pipes.cmd_pipe;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700280 /* System consumer */
Sundarajan Srinivasan357c35a2013-07-23 17:00:54 -0700281 bam.pipe[CMD_PIPE_INDEX].trans_type = SYS2BAM;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700282 bam.pipe[CMD_PIPE_INDEX].fifo.size = QPIC_BAM_CMD_FIFO_SIZE;
283 bam.pipe[CMD_PIPE_INDEX].fifo.head = cmd_desc_fifo;
Deepa Dinamani536d3f82013-07-09 13:05:56 -0700284 bam.pipe[CMD_PIPE_INDEX].lock_grp = config->pipes.cmd_pipe_grp;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700285
286 /* Programs the threshold for BAM transfer
287 * When this threshold is reached, BAM signals the peripheral via the pipe_bytes_available
288 * interface.
289 * The peripheral is signalled with this notification in the following cases:
290 * a. It has accumulated all the descriptors.
291 * b. It has accumulated more than threshold bytes.
292 * c. It has reached EOT (End Of Transfer).
293 * Note: this value needs to be set by the h/w folks and is specific for each peripheral.
294 */
295 bam.threshold = 32;
296
Deepa Dinamanie9ded132012-11-27 15:03:38 -0800297 /* Set the EE. */
298 bam.ee = config->ee;
299
300 /* Set the max desc length for this BAM. */
301 bam.max_desc_len = config->max_desc_len;
302
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700303 /* BAM Init. */
304 bam_init(&bam);
305
306 /* Initialize BAM QPIC read pipe */
307 bam_sys_pipe_init(&bam, DATA_PRODUCER_PIPE_INDEX);
308
309 /* Init read fifo */
310 bam_ret = bam_pipe_fifo_init(&bam, bam.pipe[DATA_PRODUCER_PIPE_INDEX].pipe_num);
311
312 if (bam_ret)
313 {
314 dprintf(CRITICAL, "QPIC:NANDc BAM Read FIFO init error\n");
315 bam_ret = NANDC_RESULT_FAILURE;
316 goto qpic_nand_bam_init_error;
317 }
318
319 /* Initialize BAM QPIC write pipe */
320 bam_sys_pipe_init(&bam, DATA_CONSUMER_PIPE_INDEX);
321
322 /* Init write fifo. Use the same fifo as read fifo. */
323 bam_ret = bam_pipe_fifo_init(&bam, bam.pipe[DATA_CONSUMER_PIPE_INDEX].pipe_num);
324
325 if (bam_ret)
326 {
327 dprintf(CRITICAL, "QPIC: NANDc: BAM Write FIFO init error\n");
328 bam_ret = NANDC_RESULT_FAILURE;
329 goto qpic_nand_bam_init_error;
330 }
331
332 /* Initialize BAM QPIC cmd pipe */
333 bam_sys_pipe_init(&bam, CMD_PIPE_INDEX);
334
335 /* Init cmd fifo */
336 bam_ret = bam_pipe_fifo_init(&bam, bam.pipe[CMD_PIPE_INDEX].pipe_num);
337
338 if (bam_ret)
339 {
340 dprintf(CRITICAL, "QPIC:NANDc BAM CMD FIFO init error\n");
341 bam_ret = NANDC_RESULT_FAILURE;
342 goto qpic_nand_bam_init_error;
343 }
344
345qpic_nand_bam_init_error:
346return bam_ret;
347}
348
349/* Adds command elements for addr and cfg register writes.
350 * cfg: Defines the configuration for the flash cmd.
351 * start: Address where the command elements are added.
352 *
353 * Returns the address where the next cmd element can be added.
354 */
355static struct cmd_element*
356qpic_nand_add_addr_n_cfg_ce(struct cfg_params *cfg,
357 struct cmd_element *start)
358{
359 struct cmd_element *cmd_list_ptr = start;
360
361 bam_add_cmd_element(cmd_list_ptr, NAND_ADDR0, (uint32_t)cfg->addr0, CE_WRITE_TYPE);
362 cmd_list_ptr++;
363 bam_add_cmd_element(cmd_list_ptr, NAND_ADDR1, (uint32_t)cfg->addr1, CE_WRITE_TYPE);
364 cmd_list_ptr++;
365 bam_add_cmd_element(cmd_list_ptr, NAND_DEV0_CFG0, (uint32_t)cfg->cfg0, CE_WRITE_TYPE);
366 cmd_list_ptr++;
367 bam_add_cmd_element(cmd_list_ptr, NAND_DEV0_CFG1, (uint32_t)cfg->cfg1, CE_WRITE_TYPE);
368 cmd_list_ptr++;
369
370 return cmd_list_ptr;
371}
372
373
374static struct cmd_element*
375qpic_nand_add_onfi_probe_ce(struct onfi_probe_params *params,
376 struct cmd_element *start)
377{
378 struct cmd_element *cmd_list_ptr = start;
379
380 cmd_list_ptr = qpic_nand_add_addr_n_cfg_ce(&params->cfg, cmd_list_ptr);
381
382 bam_add_cmd_element(cmd_list_ptr, NAND_DEV_CMD1, (uint32_t)params->dev_cmd1, CE_WRITE_TYPE);
383 cmd_list_ptr++;
384 bam_add_cmd_element(cmd_list_ptr, NAND_DEV_CMD_VLD, (uint32_t)params->vld, CE_WRITE_TYPE);
385 cmd_list_ptr++;
386 bam_add_cmd_element(cmd_list_ptr, NAND_READ_LOCATION_n(0), (uint32_t)params->cfg.addr_loc_0, CE_WRITE_TYPE);
387 cmd_list_ptr++;
388 bam_add_cmd_element(cmd_list_ptr, NAND_FLASH_CMD, (uint32_t)params->cfg.cmd, CE_WRITE_TYPE);
389 cmd_list_ptr++;
390 bam_add_cmd_element(cmd_list_ptr, NAND_EXEC_CMD, (uint32_t)params->cfg.exec, CE_WRITE_TYPE);
391 cmd_list_ptr++;
392
393 return cmd_list_ptr;
394}
395
396static int
397onfi_probe_cmd_exec(struct onfi_probe_params *params,
398 unsigned char* data_ptr,
399 int data_len)
400{
401 struct cmd_element *cmd_list_ptr = ce_array;
402 struct cmd_element *cmd_list_ptr_start = ce_array;
403 int num_desc = 0;
404 uint32_t status = 0;
405 int nand_ret = NANDC_RESULT_SUCCESS;
406 uint8_t desc_flags = BAM_DESC_NWD_FLAG | BAM_DESC_CMD_FLAG
407 | BAM_DESC_LOCK_FLAG | BAM_DESC_INT_FLAG;
408
409 params->cfg.addr_loc_0 = 0;
410 params->cfg.addr_loc_0 |= NAND_RD_LOC_LAST_BIT(1);
411 params->cfg.addr_loc_0 |= NAND_RD_LOC_OFFSET(0);
412 params->cfg.addr_loc_0 |= NAND_RD_LOC_SIZE(data_len);
413
414 cmd_list_ptr = qpic_nand_add_onfi_probe_ce(params, cmd_list_ptr);
415
416 /* Enqueue the desc for the above commands */
417 bam_add_one_desc(&bam,
418 CMD_PIPE_INDEX,
419 (unsigned char*)cmd_list_ptr_start,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -0700420 PA((addr_t)(uint32_t)cmd_list_ptr - (uint32_t)cmd_list_ptr_start),
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700421 desc_flags);
422
423 cmd_list_ptr_start = cmd_list_ptr;
424 num_desc++;
425
426 /* Add Data desc */
427 bam_add_desc(&bam,
428 DATA_PRODUCER_PIPE_INDEX,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -0700429 (unsigned char *)PA((addr_t)data_ptr),
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700430 data_len,
431 BAM_DESC_INT_FLAG);
432
433 /* Wait for the commands to be executed */
434 qpic_nand_wait_for_cmd_exec(num_desc);
435
436 /* Read buffer status and check for errors. */
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800437 status = qpic_nand_read_reg(NAND_FLASH_STATUS, 0);
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700438
439 if (qpic_nand_check_status(status))
440 {
441 nand_ret = NANDC_RESULT_FAILURE;
442 goto onfi_probe_exec_err;
443 }
444
445 /* Wait for data to be available */
446 qpic_nand_wait_for_data(DATA_PRODUCER_PIPE_INDEX);
447
448 /* Check for errors */
449 nand_ret = qpic_nand_check_status(status);
450
451onfi_probe_exec_err:
452 return nand_ret;
453}
454
455/* TODO: check why both vld and cmd need to be written. */
456void
457qpic_nand_onfi_probe_cleanup(uint32_t vld, uint32_t dev_cmd1)
458{
459 struct cmd_element *cmd_list_ptr = ce_array;
460 struct cmd_element *cmd_list_ptr_start = ce_array;
461
462 bam_add_cmd_element(cmd_list_ptr, NAND_DEV_CMD1, dev_cmd1, CE_WRITE_TYPE);
463 cmd_list_ptr++;
464 bam_add_cmd_element(cmd_list_ptr, NAND_DEV_CMD_VLD, vld, CE_WRITE_TYPE);
465 cmd_list_ptr++;
466
467 /* Enqueue the desc for the above commands */
468 bam_add_one_desc(&bam,
469 CMD_PIPE_INDEX,
470 (unsigned char*)cmd_list_ptr_start,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -0700471 PA((uint32_t)cmd_list_ptr - (uint32_t)cmd_list_ptr_start),
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700472 BAM_DESC_UNLOCK_FLAG | BAM_DESC_CMD_FLAG| BAM_DESC_INT_FLAG);
473
474 qpic_nand_wait_for_cmd_exec(1);
475}
476
477static int
478qpic_nand_onfi_save_params(struct onfi_param_page *param_page, struct flash_info *flash)
479{
480 int onfi_ret = NANDC_RESULT_SUCCESS;
481 uint32_t ecc_bits;
482
483 onfi_ret = qpic_nand_fetch_id(flash);
484
485 if (onfi_ret)
486 {
487 dprintf(CRITICAL, "Fetch ID cmd failed\n");
488 goto onfi_save_params_err;
489 }
490
491 flash->page_size = param_page->data_per_pg;
492 flash->block_size = param_page->pgs_per_blk * flash->page_size;
493 flash->num_blocks = param_page->blks_per_LUN;
494 flash->widebus = param_page->feature_supported & 0x1;
495 flash->density = param_page->blks_per_LUN * flash->blksize;
496 flash->spare_size = param_page->spare_per_pg;
497 ecc_bits = param_page->num_bits_ecc_correctability;
498 flash->num_pages_per_blk = param_page->pgs_per_blk;
499 flash->num_pages_per_blk_mask = param_page->pgs_per_blk - 1;
500
501 if (ecc_bits >= 8)
502 flash->ecc_width = NAND_WITH_8_BIT_ECC;
503 else
504 flash->ecc_width = NAND_WITH_4_BIT_ECC;
505
506 onfi_save_params_err:
507 return onfi_ret;
508}
509
510static void
511qpic_nand_save_config(struct flash_info *flash)
512{
513
514 /* Save Configurations */
515 flash->cws_per_page = flash->page_size >> NAND_CW_DIV_RIGHT_SHIFT;
516
Deepa Dinamani16663a62013-02-07 16:25:59 -0800517 /* Verify that we have enough buffer to handle all the cws in a page. */
518 ASSERT(flash->cws_per_page <= QPIC_NAND_MAX_CWS_IN_PAGE);
519
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700520 /* Codeword Size = UD_SIZE_BYTES + ECC_PARITY_SIZE_BYTES
521 * + SPARE_SIZE_BYTES + Bad Block size
522 */
523 if (flash->ecc_width & NAND_WITH_8_BIT_ECC)
524 {
525 flash->cw_size = NAND_CW_SIZE_8_BIT_ECC;
526 ecc_bch_cfg |= (1 << NAND_DEV0_ECC_MODE_SHIFT); /* Use 8-bit ecc */
527
528 if (flash->widebus)
529 {
530 cfg0 |= (0 << NAND_DEV0_CFG0_SPARE_SZ_BYTES_SHIFT); /* spare size bytes in each CW */
531 ecc_bch_cfg |= (14 << NAND_DEV0_ECC_PARITY_SZ_BYTES_SHIFT); /* parity bytes in each CW */
532 }
533 else
534 {
535 cfg0 |= (2 << NAND_DEV0_CFG0_SPARE_SZ_BYTES_SHIFT); /* spare size bytes in each CW */
536 ecc_bch_cfg |= (13 << NAND_DEV0_ECC_PARITY_SZ_BYTES_SHIFT); /* parity bytes in each CW */
537 }
538 }
539 else
540 {
541 flash->cw_size = NAND_CW_SIZE_4_BIT_ECC;
542
543 if (flash->widebus)
544 {
545 cfg0 |= (2 << NAND_DEV0_CFG0_SPARE_SZ_BYTES_SHIFT); /* spare size bytes in each CW */
546 ecc_bch_cfg |= (8 << NAND_DEV0_ECC_PARITY_SZ_BYTES_SHIFT); /* parity bytes in each CW */
547 }
548 else
549 {
550 cfg0 |= (4 << NAND_DEV0_CFG0_SPARE_SZ_BYTES_SHIFT); /* spare size bytes in each CW */
551 ecc_bch_cfg |= (7 << NAND_DEV0_ECC_PARITY_SZ_BYTES_SHIFT); /* parity bytes in each CW */
552 }
553 }
554
555 /* BAD_BLOCK_BYTE_NUM = Page Size -
556 * (CW_PER_PAGE * Codeword Size) + 1
557 * Note: Set CW_PER_PAGE to 1 less than the actual number.
558 */
559 flash->bad_blk_loc = flash->page_size - flash->cw_size * (flash->cws_per_page - 1) + 1;
560
561 cfg0 |= ((flash->cws_per_page - 1) << NAND_DEV0_CFG0_CW_PER_PAGE_SHIFT) /* 4/8 cw/pg for 2/4k */
562 |(DATA_BYTES_IN_IMG_PER_CW << NAND_DEV0_CFG0_UD_SIZE_BYTES_SHIFT) /* 516 user data bytes */
563 |(5 << NAND_DEV0_CFG0_ADDR_CYCLE_SHIFT) /* 5 address cycles */
564 |(0 << NAND_DEV0_CFG0_DIS_STS_AFTER_WR_SHIFT);/* Send read status cmd after each write. */
565
566 cfg1 |= (7 << NAND_DEV0_CFG1_RECOVERY_CYCLES_SHIFT) /* 8 recovery cycles */
567 |(0 << NAND_DEV0_CFG1_CS_ACTIVE_BSY_SHIFT) /* Allow CS deassertion */
568 |(flash->bad_blk_loc << NAND_DEV0_CFG1_BAD_BLK_BYTE_NUM_SHIFT)/* Bad block marker location */
569 |(0 << NAND_DEV0_CFG1_BAD_BLK_IN_SPARE_SHIFT) /* Bad block in user data area */
570 |(2 << NAND_DEV0_CFG1_WR_RD_BSY_GAP_SHIFT) /* 8 cycle tWB/tRB */
571 |(flash->widebus << NAND_DEV0_CFG1_WIDE_BUS_SHIFT); /* preserve wide flash flag */
572
573 cfg0_raw = ((flash->cws_per_page- 1) << NAND_DEV0_CFG0_CW_PER_PAGE_SHIFT)
574 |(5 << NAND_DEV0_CFG0_ADDR_CYCLE_SHIFT)
575 |(516 << NAND_DEV0_CFG0_UD_SIZE_BYTES_SHIFT) //figure out the size of cw
576 | (1 << NAND_DEV0_CFG0_DIS_STS_AFTER_WR_SHIFT);
577
578 cfg1_raw = (7 << NAND_DEV0_CFG1_RECOVERY_CYCLES_SHIFT)
579 | (0 << NAND_DEV0_CFG1_CS_ACTIVE_BSY_SHIFT)
580 | (17 << NAND_DEV0_CFG1_BAD_BLK_BYTE_NUM_SHIFT)
581 | (1 << NAND_DEV0_CFG1_BAD_BLK_IN_SPARE_SHIFT)
582 | (2 << NAND_DEV0_CFG1_WR_RD_BSY_GAP_SHIFT)
583 | (flash->widebus << NAND_DEV0_CFG1_WIDE_BUS_SHIFT)
584 |1 ; /* to disable reed solomon ecc..this feild is now read only. */
585
586 ecc_bch_cfg |= (0 << NAND_DEV0_ECC_DISABLE_SHIFT) /* Enable ECC */
587 | (0 << NAND_DEV0_ECC_SW_RESET_SHIFT) /* Put ECC core in op mode */
588 | (DATA_BYTES_IN_IMG_PER_CW << NAND_DEV0_ECC_NUM_DATA_BYTES)
589 | (1 << NAND_DEV0_ECC_FORCE_CLK_OPEN_SHIFT); /* Enable all clocks */
590}
591
592/* Onfi probe should issue the following commands to the flash device:
593 * 1. Read ID - with addr ONFI_READ_ID_ADDR.
594 * This returns the ONFI ASCII string indicating support for ONFI.
595 * 2. Read Prameter Page - with addr ONFI_READ_PARAM_PAGE_ADDR.
596 * This returns the params for the device.
597 * Each command inturn issues commands- ADDR0, ADDR1, chip_select,
598 * cfg0, cfg1, cmd_vld, dev_cmd1, read_loc0, flash, exec.
599 */
600static int
601qpic_nand_onfi_probe(struct flash_info *flash)
602{
603 struct onfi_probe_params params;
604 uint32_t vld;
605 uint32_t dev_cmd1;
606 unsigned char *buffer;
607 unsigned char onfi_str[4];
608 uint32_t *id;
609 struct onfi_param_page *param_page;
610 int onfi_ret = NANDC_RESULT_SUCCESS;
611
612 /* Allocate memory required to read the onfi param page */
613 buffer = (unsigned char*) malloc(ONFI_READ_PARAM_PAGE_BUFFER_SIZE);
Maria Yu71909742014-07-04 17:30:00 +0800614 ASSERT(buffer != NULL);
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700615
616 /* Read the vld and dev_cmd1 registers before modifying */
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800617 vld = qpic_nand_read_reg(NAND_DEV_CMD_VLD, 0);
618 dev_cmd1 = qpic_nand_read_reg(NAND_DEV_CMD1, 0);
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700619
620 /* Initialize flash cmd */
621 params.cfg.cmd = NAND_CMD_PAGE_READ;
622 params.cfg.exec = 1;
623
624 /* Execute Read ID cmd */
625
626 /* Initialize the config */
627 params.cfg.cfg0 = NAND_CFG0_RAW_ONFI_ID;
628 params.cfg.cfg1 = NAND_CFG1_RAW_ONFI_ID;
629
630 /* Initialize the cmd and vld */
631 params.dev_cmd1 = (dev_cmd1 & 0xFFFFFF00) | ONFI_READ_ID_CMD;
632 params.vld = vld & 0xFFFFFFFE;
633
634 /* Initialize the address
635 * addr1 is not used bcos of the cfg.
636 */
637 params.cfg.addr0 = ONFI_READ_ID_ADDR;
638 params.cfg.addr1 = 0;
639
640 /* Lock the pipe and execute the cmd. */
641 onfi_ret = onfi_probe_cmd_exec(&params, onfi_str, ONFI_READ_ID_BUFFER_SIZE);
642 if (onfi_ret)
643 {
644 dprintf(CRITICAL, "ONFI Read id cmd failed\n");
645 goto qpic_nand_onfi_probe_err;
646 }
647
648 /* Write back vld and cmd and unlock the pipe. */
649 qpic_nand_onfi_probe_cleanup(vld, dev_cmd1);
650
651 /* Check for onfi string */
652 id = (uint32_t*)onfi_str;
653 if (*id != ONFI_SIGNATURE)
654 {
655 dprintf(CRITICAL, "Not an ONFI device\n");
656 /* Not an onfi device. Return error. */
657 onfi_ret = NANDC_RESULT_DEV_NOT_SUPPORTED;
658 goto qpic_nand_onfi_probe_err;
659 }
660
661 dprintf(INFO, "ONFI device found\n");
662 /* Now read the param page */
663 /* Initialize the config */
664 params.cfg.cfg0 = NAND_CFG0_RAW_ONFI_PARAM_PAGE;
665 params.cfg.cfg1 = NAND_CFG1_RAW_ONFI_PARAM_PAGE;
666
667 /* Initialize the cmd and vld */
668 params.dev_cmd1 = (dev_cmd1 & 0xFFFFFF00) | ONFI_READ_PARAM_PAGE_CMD;
669 params.vld = vld & 0xFFFFFFFE;
670
671 /* Initialize the address
672 * addr1 is not used bcos of the cfg.
673 */
674 params.cfg.addr0 = ONFI_READ_PARAM_PAGE_ADDR;
675 params.cfg.addr1 = 0;
676
677 /* Lock the pipe and execute the cmd. */
678 onfi_ret = onfi_probe_cmd_exec(&params, buffer, ONFI_READ_PARAM_PAGE_BUFFER_SIZE);
679 if (onfi_ret)
680 {
681 dprintf(CRITICAL, "ONFI Read param page failed\n");
682 goto qpic_nand_onfi_probe_err;
683 }
684
685 /* Write back vld and cmd and unlock the pipe. */
686 qpic_nand_onfi_probe_cleanup(vld, dev_cmd1);
687
688 /* Verify the integrity of the returned page */
689 param_page = (struct onfi_param_page*)buffer;
690
691 /* TODO: Add CRC check to validate the param page. */
692
693 /* Save the parameter values */
694 onfi_ret = qpic_nand_onfi_save_params(param_page, flash);
695
696qpic_nand_onfi_probe_err:
697 if (onfi_ret)
698 dprintf(CRITICAL, "ONFI probe failed\n");
699
700 free(buffer);
701
702 return onfi_ret;
703}
704
705/* Enquues a desc for a flash cmd with NWD flag set:
706 * cfg: Defines the configuration for the flash cmd.
707 * start: Address where the command elements are added.
708 *
709 * Returns the address where the next cmd element can be added.
710 */
711struct cmd_element*
712qpic_nand_add_cmd_ce(struct cfg_params *cfg,
713 struct cmd_element *start)
714{
715 struct cmd_element *cmd_list_ptr;
716
717 cmd_list_ptr = qpic_nand_add_addr_n_cfg_ce(cfg, start);
718
719 bam_add_cmd_element(cmd_list_ptr, NAND_FLASH_CMD, (uint32_t)cfg->cmd, CE_WRITE_TYPE);
720 cmd_list_ptr++;
721
722 bam_add_cmd_element(cmd_list_ptr, NAND_EXEC_CMD, (uint32_t)cfg->exec, CE_WRITE_TYPE);
723 cmd_list_ptr++;
724
725 return cmd_list_ptr;
726}
727
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800728/* Reads nand_flash_status */
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700729struct cmd_element*
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800730qpic_nand_add_read_ce(struct cmd_element *start, uint32_t *flash_status_read)
731{
732 struct cmd_element *cmd_list_ptr = start;
733
734 bam_add_cmd_element(cmd_list_ptr, NAND_FLASH_STATUS, (uint32_t)PA((addr_t)flash_status_read), CE_READ_TYPE);
735 cmd_list_ptr++;
736
737 return cmd_list_ptr;
738}
739
740/* Resets nand_flash_status and nand_read_status */
741struct cmd_element*
742qpic_nand_reset_status_ce(struct cmd_element *start, uint32_t read_status)
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700743{
744 struct cmd_element *cmd_list_ptr = start;
745 uint32_t flash_status_reset;
746 uint32_t read_status_reset;
747
748 /* Read and reset the status registers. */
749 flash_status_reset = NAND_FLASH_STATUS_RESET;
750 read_status_reset = NAND_READ_STATUS_RESET;
751
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700752 bam_add_cmd_element(cmd_list_ptr, NAND_FLASH_STATUS, (uint32_t)flash_status_reset, CE_WRITE_TYPE);
753 cmd_list_ptr++;
754
755 if (read_status)
756 {
757 bam_add_cmd_element(cmd_list_ptr, NAND_READ_STATUS, (uint32_t)read_status_reset, CE_WRITE_TYPE);
758 cmd_list_ptr++;
759 }
760
761 return cmd_list_ptr;
762}
763
764struct cmd_element*
765qpic_nand_add_isbad_cmd_ce(struct cfg_params *cfg,
766 struct cmd_element *start)
767{
768 struct cmd_element *cmd_list_ptr = start;
769
770 bam_add_cmd_element(cmd_list_ptr, NAND_DEV0_ECC_CFG, (uint32_t)cfg->ecc_cfg, CE_WRITE_TYPE);
771 cmd_list_ptr++;
772
773 bam_add_cmd_element(cmd_list_ptr, NAND_READ_LOCATION_n(0), (uint32_t)cfg->addr_loc_0, CE_WRITE_TYPE);
774 cmd_list_ptr++;
775
776 cmd_list_ptr = qpic_nand_add_cmd_ce(cfg, cmd_list_ptr);
777
778 return cmd_list_ptr;
779}
780
781static int
782qpic_nand_block_isbad_exec(struct cfg_params *params,
783 uint8_t *bad_block)
784{
785
786 struct cmd_element *cmd_list_ptr = ce_array;
787 struct cmd_element *cmd_list_ptr_start = ce_array;
788 uint8_t desc_flags = BAM_DESC_NWD_FLAG | BAM_DESC_CMD_FLAG
789 | BAM_DESC_LOCK_FLAG | BAM_DESC_INT_FLAG;
790 int num_desc = 0;
791 uint32_t status = 0;
792 int nand_ret = NANDC_RESULT_SUCCESS;
793
794 cmd_list_ptr = qpic_nand_add_isbad_cmd_ce(params, cmd_list_ptr);
795
796 /* Enqueue the desc for the above commands */
797 bam_add_one_desc(&bam,
798 CMD_PIPE_INDEX,
799 (unsigned char*)cmd_list_ptr_start,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -0700800 PA((uint32_t)cmd_list_ptr - (uint32_t)cmd_list_ptr_start),
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700801 desc_flags);
802
803 num_desc++;
804
805 /* Add Data desc */
806 bam_add_desc(&bam,
807 DATA_PRODUCER_PIPE_INDEX,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -0700808 (unsigned char *)PA((addr_t)bad_block),
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700809 4,
810 BAM_DESC_INT_FLAG);
811
812 qpic_nand_wait_for_cmd_exec(num_desc);
813
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800814 status = qpic_nand_read_reg(NAND_FLASH_STATUS, 0);
Deepa Dinamani19530062012-10-03 14:43:05 -0700815
816 nand_ret = qpic_nand_check_status(status);
817
818 /* Dummy read to unlock pipe. */
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800819 status = qpic_nand_read_reg(NAND_FLASH_STATUS, BAM_DESC_UNLOCK_FLAG);
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700820
Deepa Dinamani19530062012-10-03 14:43:05 -0700821 if (nand_ret)
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700822 return NANDC_RESULT_FAILURE;
823
824 qpic_nand_wait_for_data(DATA_PRODUCER_PIPE_INDEX);
825
826 return nand_ret;
827}
828
829static int
Deepa Dinamanidc1381e2012-11-15 14:53:24 -0800830qpic_nand_block_isbad(unsigned page)
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700831{
832 unsigned cwperpage;
833 struct cfg_params params;
834 uint8_t bad_block[4];
835 unsigned nand_ret = NANDC_RESULT_SUCCESS;
Deepa Dinamanidc1381e2012-11-15 14:53:24 -0800836 uint32_t blk = page / flash.num_pages_per_blk;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700837
Deepa Dinamanidc1381e2012-11-15 14:53:24 -0800838 if (bbtbl[blk] == NAND_BAD_BLK_VALUE_IS_GOOD)
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700839 return NANDC_RESULT_SUCCESS;
Deepa Dinamanidc1381e2012-11-15 14:53:24 -0800840 else if (bbtbl[blk] == NAND_BAD_BLK_VALUE_IS_BAD)
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700841 return NANDC_RESULT_BAD_BLOCK;
842 else
843 {
844 /* Read the bad block value from the flash.
845 * Bad block value is stored in the first page of the block.
846 */
847 /* Read the first page in the block. */
848 cwperpage = flash.cws_per_page;
849
850 /* Read page cmd */
Deepa Dinamanidc1381e2012-11-15 14:53:24 -0800851 params.cmd = NAND_CMD_PAGE_READ_ECC;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700852 /* Clear the CW per page bits */
853 params.cfg0 = cfg0_raw & ~(7U << NAND_DEV0_CFG0_CW_PER_PAGE_SHIFT);
854 params.cfg1 = cfg1_raw;
Deepa Dinamanidc1381e2012-11-15 14:53:24 -0800855 /* addr0 - Write column addr + few bits in row addr upto 32 bits. */
856 params.addr0 = (page << 16) | (USER_DATA_BYTES_PER_CW * cwperpage);
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700857
858 /* addr1 - Write rest of row addr.
859 * This will be all 0s.
860 */
Deepa Dinamanidc1381e2012-11-15 14:53:24 -0800861 params.addr1 = (page >> 16) & 0xff;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700862 params.addr_loc_0 = NAND_RD_LOC_OFFSET(0);
863 params.addr_loc_0 |= NAND_RD_LOC_LAST_BIT(1);
864 params.addr_loc_0 |= NAND_RD_LOC_SIZE(4); /* Read 4 bytes */
Deepa Dinamanidc1381e2012-11-15 14:53:24 -0800865 params.ecc_cfg = ecc_bch_cfg | 0x1; /* Disable ECC */
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700866 params.exec = 1;
867
868 if (qpic_nand_block_isbad_exec(&params, bad_block))
869 {
870 dprintf(CRITICAL,
871 "Could not read bad block value\n");
872 return NANDC_RESULT_FAILURE;
873 }
874
875 if (flash.widebus)
876 {
877 if (bad_block[0] != 0xFF && bad_block[1] != 0xFF)
878 {
Deepa Dinamanidc1381e2012-11-15 14:53:24 -0800879 bbtbl[blk] = NAND_BAD_BLK_VALUE_IS_BAD;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700880 nand_ret = NANDC_RESULT_BAD_BLOCK;
881 }
882 }
883 else if (bad_block[0] != 0xFF)
884 {
Deepa Dinamanidc1381e2012-11-15 14:53:24 -0800885 bbtbl[blk] = NAND_BAD_BLK_VALUE_IS_BAD;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700886 nand_ret = NANDC_RESULT_BAD_BLOCK;
887 }
888 else
Deepa Dinamanidc1381e2012-11-15 14:53:24 -0800889 bbtbl[blk] = NAND_BAD_BLK_VALUE_IS_GOOD;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700890
891 return nand_ret;
892 }
893}
894
895/* Function to erase a block on the nand.
896 * page: Starting page address for the block.
897 */
898static int
899qpic_nand_blk_erase(uint32_t page)
900{
901 struct cfg_params cfg;
902 struct cmd_element *cmd_list_ptr = ce_array;
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800903 struct cmd_element *cmd_list_read_ptr = ce_read_array;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700904 struct cmd_element *cmd_list_ptr_start = ce_array;
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800905 struct cmd_element *cmd_list_read_ptr_start = ce_read_array;
vijay kumar4f4405f2014-08-08 11:49:53 +0530906 uint32_t status, nand_ret;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700907 int num_desc = 0;
908 uint32_t blk_addr = page / flash.num_pages_per_blk;
909
910 /* Erase only if the block is not bad */
Deepa Dinamanidc1381e2012-11-15 14:53:24 -0800911 if (qpic_nand_block_isbad(page))
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700912 {
913 dprintf(CRITICAL,
914 "NAND Erase error: Block address belongs to bad block: %d\n",
915 blk_addr);
916 return NANDC_RESULT_FAILURE;
917 }
918
919 /* Fill in params for the erase flash cmd */
920 cfg.addr0 = page;
921 cfg.addr1 = 0;
922 /* Clear CW_PER_PAGE in cfg0 */
923 cfg.cfg0 = cfg0 & ~(7U << NAND_DEV0_CFG0_CW_PER_PAGE_SHIFT);
924 cfg.cfg1 = cfg1;
925 cfg.cmd = NAND_CMD_BLOCK_ERASE;
926 cfg.exec = 1;
927
928 cmd_list_ptr = qpic_nand_add_cmd_ce(&cfg, cmd_list_ptr);
929
930 /* Enqueue the desc for the above commands */
931 bam_add_one_desc(&bam,
932 CMD_PIPE_INDEX,
933 (unsigned char*)cmd_list_ptr_start,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -0700934 PA((uint32_t)cmd_list_ptr - (uint32_t)cmd_list_ptr_start),
Deepa Dinamani2467bbb2012-10-02 13:59:58 -0700935 BAM_DESC_NWD_FLAG | BAM_DESC_CMD_FLAG | BAM_DESC_INT_FLAG | BAM_DESC_LOCK_FLAG);
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700936
937 cmd_list_ptr_start = cmd_list_ptr;
938 num_desc++;
939
940 qpic_nand_wait_for_cmd_exec(num_desc);
941
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800942 status = qpic_nand_read_reg(NAND_FLASH_STATUS, 0);
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700943
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700944 cmd_list_ptr_start = cmd_list_ptr;
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800945 cmd_list_read_ptr_start = cmd_list_read_ptr;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700946
947 /* QPIC controller automatically sends
948 * GET_STATUS cmd to the nand card because
949 * of the configuration programmed.
950 * Read the result of GET_STATUS cmd.
951 */
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800952 cmd_list_read_ptr = qpic_nand_add_read_ce(cmd_list_read_ptr, &status);
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700953
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800954 /* Enqueue the desc for the NAND_FLASH_STATUS read command */
955 bam_add_one_desc(&bam,
956 CMD_PIPE_INDEX,
957 (unsigned char*)cmd_list_read_ptr_start,
958 PA((uint32_t)cmd_list_read_ptr - (uint32_t)cmd_list_read_ptr_start),
959 BAM_DESC_CMD_FLAG) ;
960
961 cmd_list_ptr = qpic_nand_reset_status_ce(cmd_list_ptr, 1);
962
963 /* Enqueue the desc for NAND_FLASH_STATUS and NAND_READ_STATUS write commands */
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700964 bam_add_one_desc(&bam,
965 CMD_PIPE_INDEX,
966 (unsigned char*)cmd_list_ptr_start,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -0700967 PA((uint32_t)cmd_list_ptr - (uint32_t)cmd_list_ptr_start),
Deepa Dinamani19530062012-10-03 14:43:05 -0700968 BAM_DESC_INT_FLAG | BAM_DESC_CMD_FLAG) ;
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800969 num_desc = 2;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700970 qpic_nand_wait_for_cmd_exec(num_desc);
971
Deepa Dinamani19530062012-10-03 14:43:05 -0700972 status = qpic_nand_check_status(status);
973
974 /* Dummy read to unlock pipe. */
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800975 nand_ret = qpic_nand_read_reg(NAND_FLASH_STATUS, BAM_DESC_UNLOCK_FLAG);
Deepa Dinamani19530062012-10-03 14:43:05 -0700976
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700977 /* Check for status errors*/
Deepa Dinamani19530062012-10-03 14:43:05 -0700978 if (status)
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700979 {
980 dprintf(CRITICAL,
981 "NAND Erase error: Block address belongs to bad block: %d\n",
982 blk_addr);
983 return NANDC_RESULT_FAILURE;
984 }
985
986 /* Check for PROG_ERASE_OP_RESULT bit for the result of erase operation. */
Deepa Dinamani2467bbb2012-10-02 13:59:58 -0700987 if (!(status & PROG_ERASE_OP_RESULT))
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700988 return NANDC_RESULT_SUCCESS;
989
990 return NANDC_RESULT_FAILURE;
991}
992
993/* Return num of desc added. */
Deepa Dinamani19530062012-10-03 14:43:05 -0700994static void
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700995qpic_nand_add_wr_page_cws_cmd_desc(struct cfg_params *cfg,
996 uint32_t status[],
997 enum nand_cfg_value cfg_mode)
998{
999 struct cmd_element *cmd_list_ptr = ce_array;
Sridhar Parasuramf5188d82014-11-17 15:39:55 -08001000 struct cmd_element *cmd_list_read_ptr = ce_read_array;
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001001 struct cmd_element *cmd_list_ptr_start = ce_array;
Sridhar Parasuramf5188d82014-11-17 15:39:55 -08001002 struct cmd_element *cmd_list_read_ptr_start = ce_read_array;
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001003 uint32_t ecc;
1004 int num_desc = 0;
1005 int int_flag = 0;
1006
1007 if (cfg_mode == NAND_CFG)
1008 ecc = ecc_bch_cfg;
1009 else
Deepa Dinamanidc1381e2012-11-15 14:53:24 -08001010 ecc = ecc_bch_cfg | 0x1; /* Disable ECC */
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001011
1012 /* Add ECC configuration */
1013 bam_add_cmd_element(cmd_list_ptr, NAND_DEV0_ECC_CFG,
1014 (uint32_t)ecc, CE_WRITE_TYPE);
1015 cmd_list_ptr++;
1016 cmd_list_ptr = qpic_nand_add_addr_n_cfg_ce(cfg, cmd_list_ptr);
1017
1018 bam_add_cmd_element(cmd_list_ptr, NAND_FLASH_CMD,
1019 (uint32_t)cfg->cmd, CE_WRITE_TYPE);
1020 cmd_list_ptr++;
1021
1022 /* Enqueue the desc for the above commands */
1023 bam_add_one_desc(&bam,
1024 CMD_PIPE_INDEX,
1025 (unsigned char*)cmd_list_ptr_start,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001026 PA((uint32_t)cmd_list_ptr - (uint32_t)cmd_list_ptr_start),
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001027 BAM_DESC_CMD_FLAG | BAM_DESC_LOCK_FLAG);
1028
1029 num_desc++;
1030
1031 /* Add CE for all the CWs */
1032 for (unsigned i = 0; i < flash.cws_per_page; i++)
1033 {
1034 cmd_list_ptr_start = cmd_list_ptr;
Deepa Dinamani19530062012-10-03 14:43:05 -07001035 int_flag = BAM_DESC_INT_FLAG;
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001036
1037 bam_add_cmd_element(cmd_list_ptr, NAND_EXEC_CMD, (uint32_t)cfg->exec, CE_WRITE_TYPE);
1038 cmd_list_ptr++;
1039
1040 /* Enqueue the desc for the above commands */
1041 bam_add_one_desc(&bam,
1042 CMD_PIPE_INDEX,
1043 (unsigned char*)cmd_list_ptr_start,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001044 PA((uint32_t)cmd_list_ptr - (uint32_t)cmd_list_ptr_start),
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001045 BAM_DESC_NWD_FLAG | BAM_DESC_CMD_FLAG);
1046
1047 num_desc++;
1048 cmd_list_ptr_start = cmd_list_ptr;
Sridhar Parasuramf5188d82014-11-17 15:39:55 -08001049 cmd_list_read_ptr_start = cmd_list_read_ptr;
1050
1051 cmd_list_read_ptr = qpic_nand_add_read_ce(cmd_list_read_ptr_start, &status[i]);
1052 /* Enqueue the desc for the NAND_FLASH_STATUS read command */
1053 bam_add_one_desc(&bam,
1054 CMD_PIPE_INDEX,
1055 (unsigned char*)cmd_list_read_ptr_start,
1056 PA((uint32_t)cmd_list_read_ptr - (uint32_t)cmd_list_read_ptr_start),
1057 BAM_DESC_CMD_FLAG);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001058
1059 /* Set interrupt bit only for the last CW */
1060 if (i == flash.cws_per_page - 1)
Sridhar Parasuramf5188d82014-11-17 15:39:55 -08001061 cmd_list_ptr = qpic_nand_reset_status_ce(cmd_list_ptr, 1);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001062 else
Sridhar Parasuramf5188d82014-11-17 15:39:55 -08001063 cmd_list_ptr = qpic_nand_reset_status_ce(cmd_list_ptr, 0);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001064
Sridhar Parasuramf5188d82014-11-17 15:39:55 -08001065 /* Enqueue the desc for NAND_FLASH_STATUS and NAND_READ_STATUS write commands */
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001066 bam_add_one_desc(&bam,
1067 CMD_PIPE_INDEX,
1068 (unsigned char*)cmd_list_ptr_start,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001069 PA((uint32_t)cmd_list_ptr - (uint32_t)cmd_list_ptr_start),
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001070 int_flag | BAM_DESC_CMD_FLAG);
Sridhar Parasuramf5188d82014-11-17 15:39:55 -08001071 num_desc += 2;
Deepa Dinamani19530062012-10-03 14:43:05 -07001072
1073 qpic_nand_wait_for_cmd_exec(num_desc);
1074
1075 status[i] = qpic_nand_check_status(status[i]);
1076
1077 num_desc = 0;
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001078 }
Deepa Dinamani19530062012-10-03 14:43:05 -07001079 return;
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001080}
1081
1082void
1083qpic_add_wr_page_cws_data_desc(const void *buffer,
1084 enum nand_cfg_value cfg_mode,
1085 const void *spareaddr)
1086{
1087 int len;
1088 int flags;
1089 uint32_t start;
1090 unsigned num_desc = 0;
1091
1092 for( unsigned i = 0; i < flash.cws_per_page; i++)
1093 {
1094 flags = 0;
1095
1096 /* Set the interrupt flag on the last CW write for the page. */
1097 if( i == flash.cws_per_page - 1)
1098 flags |= BAM_DESC_INT_FLAG;
1099
1100 if (cfg_mode != NAND_CFG_RAW)
1101 {
1102 start = (uint32_t)buffer + i * DATA_BYTES_IN_IMG_PER_CW;
1103
1104 if (i < (flash.cws_per_page - 1))
1105 {
1106 len = DATA_BYTES_IN_IMG_PER_CW;
1107 flags |= BAM_DESC_EOT_FLAG;
1108 }
1109 else
1110 {
1111 /* Allow space for spare bytes in the last page */
1112 len = USER_DATA_BYTES_PER_CW - ((flash.cws_per_page - 1) << 2);
1113 flags = 0;
1114 }
1115 }
1116 else
1117 {
1118 start = (uint32_t)buffer;
1119 len = flash.cw_size;
1120 flags |= BAM_DESC_EOT_FLAG;
1121 }
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001122 bam_add_one_desc(&bam, DATA_CONSUMER_PIPE_INDEX, (unsigned char*)PA(start), len, flags);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001123 num_desc++;
1124
1125 if ((i == (flash.cws_per_page - 1)) && (cfg_mode == NAND_CFG))
1126 {
1127 /* write extra data */
1128 start = (uint32_t)spareaddr;
1129 len = (flash.cws_per_page << 2);
1130 flags = BAM_DESC_EOT_FLAG | BAM_DESC_INT_FLAG;
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001131 bam_add_one_desc(&bam, DATA_CONSUMER_PIPE_INDEX, (unsigned char*)PA(start), len, flags);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001132 num_desc++;
1133 }
1134 }
1135
1136 bam_sys_gen_event(&bam, DATA_CONSUMER_PIPE_INDEX, num_desc);
1137}
1138
1139static nand_result_t
1140qpic_nand_write_page(uint32_t pg_addr,
1141 enum nand_cfg_value cfg_mode,
1142 const void* buffer,
1143 const void* spareaddr)
1144{
1145 struct cfg_params cfg;
Deepa Dinamani16663a62013-02-07 16:25:59 -08001146 uint32_t status[QPIC_NAND_MAX_CWS_IN_PAGE];
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001147 int nand_ret = NANDC_RESULT_SUCCESS;
1148
1149 if (cfg_mode == NAND_CFG_RAW)
1150 {
1151 cfg.cfg0 = cfg0_raw;
1152 cfg.cfg1 = cfg1_raw;
1153 }
1154 else
1155 {
1156 cfg.cfg0 = cfg0;
1157 cfg.cfg1 = cfg1;
1158 }
1159
1160 cfg.cmd = NAND_CMD_PRG_PAGE;
1161 cfg.exec = 1;
1162
1163 cfg.addr0 = pg_addr << 16;
1164 cfg.addr1 = (pg_addr >> 16) & 0xff;
1165
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001166 qpic_add_wr_page_cws_data_desc(buffer, cfg_mode, spareaddr);
1167
Deepa Dinamani19530062012-10-03 14:43:05 -07001168 qpic_nand_add_wr_page_cws_cmd_desc(&cfg, status, cfg_mode);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001169
1170 /* Check for errors */
1171 for(unsigned i = 0; i < flash.cws_per_page; i++)
1172 {
1173 nand_ret = qpic_nand_check_status(status[i]);
1174 if (nand_ret)
1175 {
1176 dprintf(CRITICAL,
1177 "Failed to write CW %d for page: %d\n",
1178 i, pg_addr);
1179 break;
1180 }
1181 }
1182
1183 /* Wait for data to be available */
1184 qpic_nand_wait_for_data(DATA_CONSUMER_PIPE_INDEX);
1185
1186 return nand_ret;
1187}
1188
1189static int
1190qpic_nand_mark_badblock(uint32_t page)
1191{
1192 char empty_buf[NAND_CW_SIZE_8_BIT_ECC];
1193
1194 memset(empty_buf, 0, NAND_CW_SIZE_8_BIT_ECC);
1195
1196 /* Going to first page of the block */
1197 if (page & flash.num_pages_per_blk_mask)
1198 page = page - (page & flash.num_pages_per_blk_mask);
1199
1200 return qpic_nand_write_page(page, NAND_CFG_RAW, empty_buf, 0);
1201}
1202
1203static void
1204qpic_nand_non_onfi_probe(struct flash_info *flash)
1205{
1206 int dev_found = 0;
1207 unsigned index;
1208 uint32_t ecc_bits;
1209
1210 /* Read the nand id. */
1211 qpic_nand_fetch_id(flash);
1212
1213 /* Check if we support the device */
Deepa Dinamani649a94a2013-03-07 14:37:31 -08001214 for (index = 0; index < (ARRAY_SIZE(supported_flash)); index++)
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001215 {
1216 if ((flash->id & supported_flash[index].mask) ==
1217 (supported_flash[index].flash_id & (supported_flash[index].mask)))
1218 {
1219 dev_found = 1;
1220 break;
1221 }
1222 }
1223
1224 if (dev_found)
1225 {
1226 flash->page_size = supported_flash[index].pagesize;
1227 flash->block_size = supported_flash[index].blksize;
1228 flash->spare_size = supported_flash[index].oobsize;
1229 ecc_bits = supported_flash[index].ecc_8_bits;
1230
1231 /* Make sure that the block size and page size are defined. */
1232 ASSERT(flash->block_size);
1233 ASSERT(flash->page_size);
1234
1235 flash->num_blocks = supported_flash[index].density;
1236 flash->num_blocks /= (flash->block_size);
1237 flash->num_pages_per_blk = flash->block_size / flash->page_size;
1238 flash->num_pages_per_blk_mask = flash->num_pages_per_blk - 1;
1239
1240 /* Look for 8bit BCH ECC Nand, TODO: ECC Correctability >= 8 */
1241 if (ecc_bits)
1242 flash->ecc_width = NAND_WITH_8_BIT_ECC;
1243 else
1244 flash->ecc_width = NAND_WITH_4_BIT_ECC;
1245
1246 flash->density = supported_flash[index].density;
1247 flash->widebus = supported_flash[index].widebus;
1248
1249 return;
1250 }
1251
1252 /* Flash device is not supported, print flash device info and halt */
1253 if (dev_found == 0)
1254 {
1255 dprintf(CRITICAL, "NAND device is not supported: nandid: 0x%x"
1256 "maker=0x%02x device=0x%02x\n",
1257 flash->id,
1258 flash->vendor,
1259 flash->device);
1260 ASSERT(0);
1261 }
1262
1263 dprintf(INFO, "nandid: 0x%x maker=0x%02x device=0x%02x page_size=%d\n",
1264 flash->id,
1265 flash->vendor,
1266 flash->device,
1267 flash->page_size);
1268
1269 dprintf(INFO, "spare_size=%d block_size=%d num_blocks=%d\n",
1270 flash->spare_size,
1271 flash->block_size,
1272 flash->num_blocks);
1273}
1274
1275void
1276qpic_nand_init(struct qpic_nand_init_config *config)
1277{
1278 uint32_t i;
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001279
1280 nand_base = config->nand_base;
1281
Deepa Dinamanie9ded132012-11-27 15:03:38 -08001282 qpic_bam_init(config);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001283
Deepa Dinamani649a94a2013-03-07 14:37:31 -08001284 qpic_nand_non_onfi_probe(&flash);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001285
1286 /* Save the RAW and read/write configs */
1287 qpic_nand_save_config(&flash);
1288
1289 flash_spare_bytes = (unsigned char *)malloc(flash.spare_size);
1290
1291 if (flash_spare_bytes == NULL)
1292 {
1293 dprintf(CRITICAL, "Failed to allocate memory for spare bytes\n");
1294 return;
1295 }
1296
1297 /* Create a bad block table */
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001298 bbtbl = (uint8_t *) malloc(sizeof(uint8_t) * flash.num_blocks);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001299
1300 if (bbtbl == NULL)
1301 {
1302 dprintf(CRITICAL, "Failed to allocate memory for bad block table\n");
1303 return;
1304 }
1305
1306 for (i = 0; i < flash.num_blocks; i++)
1307 bbtbl[i] = NAND_BAD_BLK_VALUE_NOT_READ;
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001308
1309 /* Set aside contiguous memory for reads/writes.
1310 * This is needed as the BAM transfers only work with
1311 * physically contiguous buffers.
1312 * We will copy any data to be written/ to be read from
1313 * nand to this buffer and this buffer will be submitted to BAM.
1314 */
1315 rdwr_buf = (uint8_t*) malloc(flash.page_size + flash.spare_size);
1316
1317 if (rdwr_buf == NULL)
1318 {
1319 dprintf(CRITICAL, "Failed to allocate memory for page reads or writes\n");
1320 return;
1321 }
1322
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001323}
1324
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -07001325unsigned
1326flash_page_size(void)
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001327{
1328 return flash.page_size;
1329}
1330
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -07001331unsigned
1332flash_block_size(void)
1333{
1334 return flash.block_size;
1335}
1336
Deepa Dinamani8e6b2432012-10-17 17:12:44 -07001337unsigned
1338flash_num_blocks(void)
1339{
1340 return flash.num_blocks;
1341}
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -07001342
1343struct ptable *
1344flash_get_ptable(void)
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001345{
1346 return flash_ptable;
1347}
1348
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -07001349void
Deepa Dinamani87feab82012-10-04 14:28:05 -07001350qpic_nand_uninit()
1351{
1352 bam_pipe_reset(&bam, DATA_PRODUCER_PIPE_INDEX);
1353 bam_pipe_reset(&bam, DATA_CONSUMER_PIPE_INDEX);
1354 bam_pipe_reset(&bam, CMD_PIPE_INDEX);
1355
1356}
1357void
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -07001358flash_set_ptable(struct ptable *new_ptable)
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001359{
1360 ASSERT(flash_ptable == NULL && new_ptable != NULL);
1361 flash_ptable = new_ptable;
1362}
1363
1364/* Note: No support for raw reads. */
1365static int
1366qpic_nand_read_page(uint32_t page, unsigned char* buffer, unsigned char* spareaddr)
1367{
1368 struct cfg_params params;
1369 uint32_t ecc;
Deepa Dinamani16663a62013-02-07 16:25:59 -08001370 uint32_t flash_sts[QPIC_NAND_MAX_CWS_IN_PAGE];
1371 uint32_t buffer_sts[QPIC_NAND_MAX_CWS_IN_PAGE];
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001372 uint32_t addr_loc_0;
1373 uint32_t addr_loc_1;
1374 struct cmd_element *cmd_list_ptr = ce_array;
1375 struct cmd_element *cmd_list_ptr_start = ce_array;
1376 uint32_t num_cmd_desc = 0;
1377 uint32_t num_data_desc = 0;
1378 uint32_t status;
1379 uint32_t i;
1380 int nand_ret = NANDC_RESULT_SUCCESS;
Sundarajan Srinivasan024bda52014-02-27 16:48:48 -08001381 uint8_t flags = 0;
1382 uint32_t *cmd_list_temp = NULL;
1383
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001384 /* UD bytes in last CW is 512 - cws_per_page *4.
1385 * Since each of the CW read earlier reads 4 spare bytes.
1386 */
1387 uint16_t ud_bytes_in_last_cw = USER_DATA_BYTES_PER_CW - ((flash.cws_per_page - 1) << 2);
1388 uint16_t oob_bytes = DATA_BYTES_IN_IMG_PER_CW - ud_bytes_in_last_cw;
1389
1390 params.addr0 = page << 16;
1391 params.addr1 = (page >> 16) & 0xff;
1392 params.cfg0 = cfg0;
1393 params.cfg1 = cfg1;
1394 params.cmd = NAND_CMD_PAGE_READ_ALL;
1395 params.exec = 1;
1396 ecc = ecc_bch_cfg;
1397
1398 /* Read all the Data bytes in the first 3 CWs. */
1399 addr_loc_0 = NAND_RD_LOC_OFFSET(0);
1400 addr_loc_0 |= NAND_RD_LOC_SIZE(DATA_BYTES_IN_IMG_PER_CW);
1401 addr_loc_0 |= NAND_RD_LOC_LAST_BIT(1);
1402
1403
1404 addr_loc_1 = NAND_RD_LOC_OFFSET(ud_bytes_in_last_cw);
1405 addr_loc_1 |= NAND_RD_LOC_SIZE(oob_bytes);
1406 addr_loc_1 |= NAND_RD_LOC_LAST_BIT(1);
1407
Deepa Dinamanidc1381e2012-11-15 14:53:24 -08001408 status = qpic_nand_block_isbad(page);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001409
1410 if (status)
1411 return status;
1412
sundarajan srinivasan7ced6482013-03-21 16:01:18 -07001413 /* Reset and Configure erased CW/page detection controller */
1414 qpic_nand_erased_status_reset(ce_array, BAM_DESC_LOCK_FLAG);
1415
Sundarajan Srinivasan024bda52014-02-27 16:48:48 -08001416 /* Queue up the command and data descriptors for all the codewords in a page
1417 * and do a single bam transfer at the end.*/
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001418 for (i = 0; i < flash.cws_per_page; i++)
1419 {
1420 num_cmd_desc = 0;
1421 num_data_desc = 0;
1422
1423 if (i == 0)
1424 {
1425 cmd_list_ptr = qpic_nand_add_addr_n_cfg_ce(&params, cmd_list_ptr);
1426
1427 bam_add_cmd_element(cmd_list_ptr, NAND_DEV0_ECC_CFG,(uint32_t)ecc, CE_WRITE_TYPE);
1428 cmd_list_ptr++;
1429 }
1430 else
1431 cmd_list_ptr_start = cmd_list_ptr;
1432
1433 bam_add_cmd_element(cmd_list_ptr, NAND_FLASH_CMD, (uint32_t)params.cmd, CE_WRITE_TYPE);
1434 cmd_list_ptr++;
1435
1436 if (i == flash.cws_per_page - 1)
1437 {
1438 addr_loc_0 = NAND_RD_LOC_OFFSET(0);
1439 addr_loc_0 |= NAND_RD_LOC_SIZE(ud_bytes_in_last_cw);
1440 addr_loc_0 |= NAND_RD_LOC_LAST_BIT(0);
1441
1442 /* Write addr loc 1 only for the last CW. */
1443 bam_add_cmd_element(cmd_list_ptr, NAND_READ_LOCATION_n(1), (uint32_t)addr_loc_1, CE_WRITE_TYPE);
1444 cmd_list_ptr++;
1445
1446 /* Add Data desc */
1447 bam_add_one_desc(&bam,
1448 DATA_PRODUCER_PIPE_INDEX,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001449 (unsigned char *)PA((addr_t)buffer),
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001450 ud_bytes_in_last_cw,
1451 0);
1452 num_data_desc++;
1453
1454 bam_add_one_desc(&bam,
1455 DATA_PRODUCER_PIPE_INDEX,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001456 (unsigned char *)PA((addr_t)spareaddr),
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001457 oob_bytes,
1458 BAM_DESC_INT_FLAG);
1459 num_data_desc++;
1460
1461 bam_sys_gen_event(&bam, DATA_PRODUCER_PIPE_INDEX, num_data_desc);
1462 }
1463 else
1464 {
1465 /* Add Data desc */
1466 bam_add_one_desc(&bam,
1467 DATA_PRODUCER_PIPE_INDEX,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001468 (unsigned char *)PA((addr_t)buffer),
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001469 DATA_BYTES_IN_IMG_PER_CW,
Sundarajan Srinivasan024bda52014-02-27 16:48:48 -08001470 0);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001471 num_data_desc++;
1472 bam_sys_gen_event(&bam, DATA_PRODUCER_PIPE_INDEX, num_data_desc);
1473 }
1474
1475 /* Write addr loc 0. */
1476 bam_add_cmd_element(cmd_list_ptr,
1477 NAND_READ_LOCATION_n(0),
1478 (uint32_t)addr_loc_0,
1479 CE_WRITE_TYPE);
1480
1481 cmd_list_ptr++;
1482 bam_add_cmd_element(cmd_list_ptr,
1483 NAND_EXEC_CMD,
1484 (uint32_t)params.exec,
1485 CE_WRITE_TYPE);
1486 cmd_list_ptr++;
1487
Sundarajan Srinivasan024bda52014-02-27 16:48:48 -08001488 /* Enqueue the desc for the above commands */
1489 bam_add_one_desc(&bam,
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001490 CMD_PIPE_INDEX,
1491 (unsigned char*)cmd_list_ptr_start,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001492 PA((uint32_t)cmd_list_ptr - (uint32_t)cmd_list_ptr_start),
Sundarajan Srinivasan024bda52014-02-27 16:48:48 -08001493 BAM_DESC_NWD_FLAG | BAM_DESC_CMD_FLAG);
1494 num_cmd_desc++;
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001495
Sundarajan Srinivasan024bda52014-02-27 16:48:48 -08001496 bam_add_cmd_element(cmd_list_ptr, NAND_FLASH_STATUS, (uint32_t)PA((addr_t)&(flash_sts[i])), CE_READ_TYPE);
1497
vijay kumar4f4405f2014-08-08 11:49:53 +05301498 cmd_list_temp = (uint32_t *)cmd_list_ptr;
Sundarajan Srinivasan024bda52014-02-27 16:48:48 -08001499
1500 cmd_list_ptr++;
1501
1502 bam_add_cmd_element(cmd_list_ptr, NAND_BUFFER_STATUS, (uint32_t)PA((addr_t)&(buffer_sts[i])), CE_READ_TYPE);
1503 cmd_list_ptr++;
1504
1505 if (i == flash.cws_per_page - 1)
1506 {
1507 flags = BAM_DESC_CMD_FLAG | BAM_DESC_UNLOCK_FLAG;
1508 }
1509 else
1510 flags = BAM_DESC_CMD_FLAG;
1511
1512 /* Enqueue the desc for the above command */
1513 bam_add_one_desc(&bam,
1514 CMD_PIPE_INDEX,
1515 (unsigned char*)PA((addr_t)cmd_list_temp),
1516 PA((uint32_t)cmd_list_ptr - (uint32_t)cmd_list_temp),
1517 flags);
1518 num_cmd_desc++;
1519
1520 buffer += DATA_BYTES_IN_IMG_PER_CW;
1521
1522 /* Notify BAM HW about the newly added descriptors */
1523 bam_sys_gen_event(&bam, CMD_PIPE_INDEX, num_cmd_desc);
1524 }
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001525
1526 qpic_nand_wait_for_data(DATA_PRODUCER_PIPE_INDEX);
1527
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001528 /* Check status */
1529 for (i = 0; i < flash.cws_per_page ; i ++)
Sundarajan Srinivasan024bda52014-02-27 16:48:48 -08001530 {
1531 flash_sts[i] = qpic_nand_check_status(flash_sts[i]);
Deepa Dinamani19530062012-10-03 14:43:05 -07001532 if (flash_sts[i])
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001533 {
1534 nand_ret = NANDC_RESULT_BAD_PAGE;
Sundarajan Srinivasan024bda52014-02-27 16:48:48 -08001535 dprintf(CRITICAL, "NAND page read failed. page: %x status %x\n", page, flash_sts[i]);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001536 goto qpic_nand_read_page_error;
1537 }
Sundarajan Srinivasan024bda52014-02-27 16:48:48 -08001538 }
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001539qpic_nand_read_page_error:
1540return nand_ret;
1541}
1542
1543/* Function to read a flash partition.
1544 * ptn : Partition to read.
1545 * extra_per_page : Spare data to be read.
1546 * offset : Num of bytes offset into the partition.
1547 * data : Buffer to read the data into.
1548 * bytes : Num of bytes to be read.
1549 */
1550 /* TODO: call this func read_partition. */
1551int
1552flash_read_ext(struct ptentry *ptn,
1553 unsigned extra_per_page,
1554 unsigned offset,
1555 void *data,
1556 unsigned bytes)
1557{
1558 uint32_t page =
1559 (ptn->start * flash.num_pages_per_blk) + (offset / flash.page_size);
1560 uint32_t lastpage = (ptn->start + ptn->length) * flash.num_pages_per_blk;
1561 uint32_t count =
1562 (bytes + flash.page_size - 1 + extra_per_page) / (flash.page_size +
1563 extra_per_page);
1564 uint32_t *spare = (unsigned *)flash_spare_bytes;
1565 uint32_t errors = 0;
1566 unsigned char *image = data;
1567 int result = 0;
1568 uint32_t current_block =
1569 (page - (page & flash.num_pages_per_blk_mask)) / flash.num_pages_per_blk;
1570 uint32_t start_block = ptn->start;
1571 uint32_t start_block_count = 0;
1572 uint32_t isbad = 0;
Deepa Dinamani2f7006c2013-08-19 11:59:38 -07001573 uint32_t current_page;
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001574
1575 /* Verify first byte is at page boundary. */
1576 if (offset & (flash.page_size - 1))
1577 {
1578 dprintf(CRITICAL, "Read request start not at page boundary: %d\n",
1579 offset);
1580 return NANDC_RESULT_PARAM_INVALID;
1581 }
1582
Deepa Dinamani2f7006c2013-08-19 11:59:38 -07001583 current_page = start_block * flash.num_pages_per_blk;
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001584 /* Adjust page offset based on number of bad blocks from start to current page */
1585 if (start_block < current_block)
1586 {
1587 start_block_count = (current_block - start_block);
1588 while (start_block_count
1589 && (start_block < (ptn->start + ptn->length)))
1590 {
Deepa Dinamani2f7006c2013-08-19 11:59:38 -07001591 isbad = qpic_nand_block_isbad(current_page);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001592 if (isbad)
1593 page += flash.num_pages_per_blk;
1594 else
1595 start_block_count--;
1596 start_block++;
Deepa Dinamani2f7006c2013-08-19 11:59:38 -07001597 current_page += flash.num_pages_per_blk;
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001598 }
1599 }
1600
1601 while ((page < lastpage) && !start_block_count)
1602 {
1603 if (count == 0)
1604 {
Deepa Dinamani52aca8d2013-02-05 11:41:41 -08001605 dprintf(SPEW, "flash_read_image: success (%d errors)\n",
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001606 errors);
1607 return NANDC_RESULT_SUCCESS;
1608 }
1609
Sundarajan Srinivasan29d927c2014-02-10 14:11:24 -08001610#if CONTIGUOUS_MEMORY
1611 result = qpic_nand_read_page(page, image, (unsigned char *) spare);
1612#else
1613 result = qpic_nand_read_page(page, rdwr_buf, (unsigned char *) spare);
1614#endif
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001615 if (result == NANDC_RESULT_BAD_PAGE)
1616 {
1617 /* bad page, go to next page. */
1618 page++;
1619 errors++;
1620 continue;
1621 }
1622 else if (result == NANDC_RESULT_BAD_BLOCK)
1623 {
1624 /* bad block, go to next block same offset. */
1625 page += flash.num_pages_per_blk;
1626 errors++;
1627 continue;
1628 }
1629
Sundarajan Srinivasan29d927c2014-02-10 14:11:24 -08001630#ifndef CONTIGUOUS_MEMORY
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001631 /* Copy the read page into correct location. */
1632 memcpy(image, rdwr_buf, flash.page_size);
Sundarajan Srinivasan29d927c2014-02-10 14:11:24 -08001633#endif
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001634 page++;
1635 image += flash.page_size;
1636 /* Copy spare bytes to image */
Sundarajan Srinivasan29d927c2014-02-10 14:11:24 -08001637 if(extra_per_page)
1638 {
1639 memcpy(image, spare, extra_per_page);
1640 image += extra_per_page;
1641 }
1642
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001643 count -= 1;
1644 }
1645
1646 /* could not find enough valid pages before we hit the end */
1647 dprintf(CRITICAL, "flash_read_image: failed (%d errors)\n", errors);
1648 return NANDC_RESULT_FAILURE;
1649}
1650
1651int
1652flash_erase(struct ptentry *ptn)
1653{
Deepa Dinamani2467bbb2012-10-02 13:59:58 -07001654 int ret = 0;
1655
1656 ret = qpic_nand_blk_erase(ptn->start * flash.num_pages_per_blk);
1657
1658 if (ret)
1659 dprintf(CRITICAL, "Erase operation failed \n");
1660
1661 return ret;
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001662}
Deepa Dinamani2467bbb2012-10-02 13:59:58 -07001663
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001664int
1665flash_ecc_bch_enabled()
1666{
1667 return (flash.ecc_width == NAND_WITH_4_BIT_ECC)? 0 : 1;
1668}
1669
1670int
1671flash_write(struct ptentry *ptn,
Deepa Dinamanic13d5942013-04-30 15:48:53 -07001672 unsigned write_extra_bytes,
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001673 const void *data,
1674 unsigned bytes)
1675{
1676 uint32_t page = ptn->start * flash.num_pages_per_blk;
1677 uint32_t lastpage = (ptn->start + ptn->length) * flash.num_pages_per_blk;
1678 uint32_t *spare = (unsigned *)flash_spare_bytes;
1679 const unsigned char *image = data;
Deepa Dinamanic13d5942013-04-30 15:48:53 -07001680 uint32_t wsize;
Sundarajan Srinivasan223d7002014-02-11 19:48:11 -08001681 uint32_t spare_byte_count = 0;
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001682 int r;
1683
Sundarajan Srinivasan223d7002014-02-11 19:48:11 -08001684 spare_byte_count = ((flash.cw_size * flash.cws_per_page)- flash.page_size);
1685
Deepa Dinamanic13d5942013-04-30 15:48:53 -07001686 if(write_extra_bytes)
Sundarajan Srinivasan223d7002014-02-11 19:48:11 -08001687 wsize = flash.page_size + spare_byte_count;
Deepa Dinamanic13d5942013-04-30 15:48:53 -07001688 else
1689 wsize = flash.page_size;
1690
Sundarajan Srinivasan223d7002014-02-11 19:48:11 -08001691 memset(spare, 0xff, (spare_byte_count / flash.cws_per_page));
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001692
1693 while (bytes > 0)
1694 {
1695 if (bytes < wsize)
1696 {
1697 dprintf(CRITICAL,
1698 "flash_write_image: image undersized (%d < %d)\n",
1699 bytes,
1700 wsize);
1701 return -1;
1702 }
1703
1704 if (page >= lastpage)
1705 {
1706 dprintf(CRITICAL, "flash_write_image: out of space\n");
1707 return -1;
1708 }
1709
1710 if ((page & flash.num_pages_per_blk_mask) == 0)
1711 {
Deepa Dinamani2467bbb2012-10-02 13:59:58 -07001712 if (qpic_nand_blk_erase(page))
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001713 {
1714 dprintf(INFO,
1715 "flash_write_image: bad block @ %d\n",
1716 page / flash.num_pages_per_blk);
1717
1718 page += flash.num_pages_per_blk;
1719 continue;
1720 }
1721 }
1722
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001723 memcpy(rdwr_buf, image, flash.page_size);
1724
Deepa Dinamanic13d5942013-04-30 15:48:53 -07001725 if (write_extra_bytes)
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001726 {
Sundarajan Srinivasan223d7002014-02-11 19:48:11 -08001727 memcpy(rdwr_buf + flash.page_size, image + flash.page_size, spare_byte_count);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001728 r = qpic_nand_write_page(page,
1729 NAND_CFG,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001730 rdwr_buf,
1731 rdwr_buf + flash.page_size);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001732 }
1733 else
1734 {
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001735 r = qpic_nand_write_page(page, NAND_CFG, rdwr_buf, spare);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001736 }
1737
1738 if (r)
1739 {
1740 dprintf(INFO,
1741 "flash_write_image: write failure @ page %d (src %d)\n",
1742 page,
1743 image - (const unsigned char *)data);
1744
1745 image -= (page & flash.num_pages_per_blk_mask) * wsize;
1746 bytes += (page & flash.num_pages_per_blk_mask) * wsize;
1747 page &= ~flash.num_pages_per_blk_mask;
1748 if (qpic_nand_blk_erase(page))
1749 {
1750 dprintf(INFO,
1751 "flash_write_image: erase failure @ page %d\n",
1752 page);
1753 }
1754
1755 qpic_nand_mark_badblock(page);
1756
1757 dprintf(INFO,
1758 "flash_write_image: restart write @ page %d (src %d)\n",
1759 page, image - (const unsigned char *)data);
1760
1761 page += flash.num_pages_per_blk;
1762 continue;
1763 }
1764 page++;
1765 image += wsize;
1766 bytes -= wsize;
1767 }
1768
1769 /* erase any remaining pages in the partition */
1770 page = (page + flash.num_pages_per_blk_mask) & (~flash.num_pages_per_blk_mask);
1771
1772 while (page < lastpage)
1773 {
1774 if (qpic_nand_blk_erase(page))
1775 {
1776 dprintf(INFO, "flash_write_image: bad block @ %d\n",
1777 page / flash.num_pages_per_blk);
1778 }
1779 page += flash.num_pages_per_blk;
1780 }
1781
1782 dprintf(INFO, "flash_write_image: success\n");
1783 return 0;
1784}
Smita Ghoshf5431c62014-09-18 14:11:14 -07001785
1786uint32_t nand_device_base()
1787{
1788 return nand_base;
1789}