blob: d2b604493cd03647c54ffb05870bbd9eb0e9e9c7 [file] [log] [blame]
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001/*
2 * Copyright (c) 2008, Google Inc.
3 * All rights reserved.
Tanya Brokhman646eedb2015-01-06 23:09:54 +02004 * Copyright (c) 2009-2015, 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>
Sridhar Parasuramfb0d9c82015-02-02 15:23:13 -080036#include <bits.h>
Deepa Dinamanie4573be2012-08-03 16:32:29 -070037#include <sys/types.h>
Deepa Dinamani0bf2f442012-10-19 11:41:06 -070038#include <platform.h>
Amol Jadib726c3b2012-09-13 13:51:23 -070039#include <platform/clock.h>
Smita Ghoshf5431c62014-09-18 14:11:14 -070040#include <platform/iomap.h>
Deepa Dinamanie4573be2012-08-03 16:32:29 -070041
42static uint32_t nand_base;
43static struct ptable *flash_ptable;
44static struct flash_info flash;
45static unsigned char *flash_spare_bytes;
46static uint32_t cfg0;
47static uint32_t cfg1;
48static uint32_t cfg0_raw;
49static uint32_t cfg1_raw;
50static uint32_t ecc_bch_cfg;
Channagoud Kadabib1dc47c2015-05-21 17:02:44 -070051static uint32_t ecc_cfg_raw;
52static uint32_t ecc_parity_bytes;
Deepa Dinamanie4573be2012-08-03 16:32:29 -070053
Sridhar Parasuramf5188d82014-11-17 15:39:55 -080054struct cmd_element ce_array[100] __attribute__ ((aligned(16)));
55struct cmd_element ce_read_array[20] __attribute__ ((aligned(16)));
Deepa Dinamanie4573be2012-08-03 16:32:29 -070056
57#define QPIC_BAM_DATA_FIFO_SIZE 64
58#define QPIC_BAM_CMD_FIFO_SIZE 64
59
Channagoud Kadabib1dc47c2015-05-21 17:02:44 -070060#define THRESHOLD_BIT_FLIPS 4
61
Deepa Dinamanie4573be2012-08-03 16:32:29 -070062static struct bam_desc cmd_desc_fifo[QPIC_BAM_CMD_FIFO_SIZE] __attribute__ ((aligned(BAM_DESC_SIZE)));
63static struct bam_desc data_desc_fifo[QPIC_BAM_DATA_FIFO_SIZE] __attribute__ ((aligned(BAM_DESC_SIZE)));
64
65static struct bam_instance bam;
66static uint8_t *bbtbl;
67
Deepa Dinamani0bf2f442012-10-19 11:41:06 -070068static uint8_t* rdwr_buf;
69
Deepa Dinamanie4573be2012-08-03 16:32:29 -070070static struct flash_id supported_flash[] = {
Sridhar Parasuramfb0d9c82015-02-02 15:23:13 -080071 /* Flash ID Flash ID2 ID Mask ID Mask2 Density(MB) Wid Pgsz Blksz oobsz 8-bit ECCf */
72 {0x1590AC2C, 0x56, 0xFFFFFFFF, 0xFF, 0x20000000, 0, 2048, 0x00020000, 0x40, 0},
73 {0x1590AC2C, 0x57, 0xFFFFFFFF, 0xFF, 0x20000000, 0, 2048, 0x00020000, 0x40, 1},
74 {0x1590AA2C, 0x06, 0xFFFFFFFF, 0x0, 0x10000000, 0, 2048, 0x00020000, 0xE0, 1},
75 {0x2690AC2C, 0x54, 0xFFFFFFFF, 0x0, 0x20000000, 0, 4096, 0x00040000, 0xE0, 1},
76 {0x1590ACAD, 0, 0xFFFFFFFF, 0x0, 0x20000000, 0, 2048, 0x00020000, 0x80, 0},
77 {0x9590DC2C, 0x56, 0xFFFFFFFF, 0x0, 0x10000000, 0, 2048, 0x00020000, 0x40, 0},
78 {0x1590aa98, 0x76, 0xFFFFFFFF, 0x0, 0x10000000, 0, 2048, 0x00020000, 0x80, 1},
vijay kumar94451f82015-07-23 12:41:24 +053079 {0x2690A32C, 0x64, 0xFFFFFFFF, 0x0, 0x20000000, 0, 4096, 0x00040000, 0xE0, 1},
vijay kumarc395fb52015-09-30 19:16:33 +053080 {0x2690AC98, 0x81676, 0xFFFFFFFF, 0x0, 0x20000000, 0, 4096, 0x00040000, 0xE0, 1},
Deepa Dinamanie4573be2012-08-03 16:32:29 -070081 /* Note: Width flag is 0 for 8 bit Flash and 1 for 16 bit flash */
Deepa Dinamanie4573be2012-08-03 16:32:29 -070082};
83
Tanya Brokhman72b44dc2015-01-07 10:20:05 +020084static int qpic_nand_mark_badblock(uint32_t page);
85
Deepa Dinamanie4573be2012-08-03 16:32:29 -070086static void
87qpic_nand_wait_for_cmd_exec(uint32_t num_desc)
88{
89 /* Create a read/write event to notify the periperal of the added desc. */
90 bam_sys_gen_event(&bam, CMD_PIPE_INDEX, num_desc);
91
92 /* Wait for the descriptors to be processed */
93 bam_wait_for_interrupt(&bam, CMD_PIPE_INDEX, P_PRCSD_DESC_EN_MASK);
94
95 /* Read offset update for the circular FIFO */
96 bam_read_offset_update(&bam, CMD_PIPE_INDEX);
97}
98
99static void
100qpic_nand_wait_for_data(uint32_t pipe_num)
101{
102 /* Wait for the descriptors to be processed */
103 bam_wait_for_interrupt(&bam, pipe_num, P_PRCSD_DESC_EN_MASK);
104
105 /* Read offset update for the circular FIFO */
106 bam_read_offset_update(&bam, pipe_num);
107}
108
109static uint32_t
110qpic_nand_read_reg(uint32_t reg_addr,
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800111 uint8_t flags)
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700112{
113 uint32_t val;
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800114 struct cmd_element *cmd_list_read_ptr = ce_read_array;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700115
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800116 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 -0700117
118 /* Enqueue the desc for the above command */
119 bam_add_one_desc(&bam,
120 CMD_PIPE_INDEX,
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800121 (unsigned char*)PA((addr_t)cmd_list_read_ptr),
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700122 BAM_CE_SIZE,
123 BAM_DESC_CMD_FLAG| BAM_DESC_INT_FLAG | flags);
124
125 qpic_nand_wait_for_cmd_exec(1);
126
127 return val;
128}
129
Deepa Dinamani19530062012-10-03 14:43:05 -0700130/* Assume the BAM is in a locked state. */
131void
sundarajan srinivasan7ced6482013-03-21 16:01:18 -0700132qpic_nand_erased_status_reset(struct cmd_element *cmd_list_ptr, uint8_t flags)
Deepa Dinamani19530062012-10-03 14:43:05 -0700133{
134 uint32_t val = 0;
135
136 /* Reset the Erased Codeword/Page detection controller. */
137 val = NAND_ERASED_CW_DETECT_CFG_RESET_CTRL;
138
139 bam_add_cmd_element(cmd_list_ptr, NAND_ERASED_CW_DETECT_CFG, val, CE_WRITE_TYPE);
140
141 /* Enqueue the desc for the above command */
142 bam_add_one_desc(&bam,
143 CMD_PIPE_INDEX,
144 (unsigned char*)cmd_list_ptr,
145 BAM_CE_SIZE,
sundarajan srinivasan7ced6482013-03-21 16:01:18 -0700146 BAM_DESC_CMD_FLAG | BAM_DESC_INT_FLAG | flags);
Deepa Dinamani19530062012-10-03 14:43:05 -0700147
148 qpic_nand_wait_for_cmd_exec(1);
149
150 /* Enable the Erased Codeword/Page detection
151 * controller to check the data as it arrives.
152 * Also disable ECC reporting for an erased CW.
153 */
154 val = NAND_ERASED_CW_DETECT_CFG_ACTIVATE_CTRL | NAND_ERASED_CW_DETECT_ERASED_CW_ECC_MASK;
155
156 bam_add_cmd_element(cmd_list_ptr, NAND_ERASED_CW_DETECT_CFG, val, CE_WRITE_TYPE);
157
158 /* Enqueue the desc for the above command */
159 bam_add_one_desc(&bam,
160 CMD_PIPE_INDEX,
161 (unsigned char*)cmd_list_ptr,
162 BAM_CE_SIZE,
163 BAM_DESC_CMD_FLAG | BAM_DESC_INT_FLAG);
164
165 qpic_nand_wait_for_cmd_exec(1);
166}
167
168static nand_result_t
169qpic_nand_check_status(uint32_t status)
170{
171 uint32_t erase_sts;
172
173 /* Check for errors */
174 if (status & NAND_FLASH_ERR)
175 {
176 /* Check if this is an ECC error on an erased page. */
177 if (status & NAND_FLASH_OP_ERR)
178 {
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800179 erase_sts = qpic_nand_read_reg(NAND_ERASED_CW_DETECT_STATUS, 0);
Deepa Dinamani19530062012-10-03 14:43:05 -0700180 if ((erase_sts & (1 << NAND_ERASED_CW_DETECT_STATUS_PAGE_ALL_ERASED)))
181 {
182 /* Mask the OP ERROR. */
183 status &= ~NAND_FLASH_OP_ERR;
sundarajan srinivasan7ced6482013-03-21 16:01:18 -0700184 qpic_nand_erased_status_reset(ce_array, 0);
Deepa Dinamani19530062012-10-03 14:43:05 -0700185 }
186 }
187
188 /* ECC error flagged on an erased page read.
189 * Ignore and return success.
190 */
191 if (!(status & NAND_FLASH_ERR))
192 return NANDC_RESULT_SUCCESS;
193
194 dprintf(CRITICAL, "Nand Flash error. Status = %d\n", status);
195
196 if (status & NAND_FLASH_TIMEOUT_ERR)
197 return NANDC_RESULT_TIMEOUT;
198 else
199 return NANDC_RESULT_FAILURE;
200 }
201
202 return NANDC_RESULT_SUCCESS;
203}
204
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700205static uint32_t
206qpic_nand_fetch_id(struct flash_info *flash)
207{
208 struct cmd_element *cmd_list_ptr = ce_array;
209 struct cmd_element *cmd_list_ptr_start = ce_array;
210 int num_desc = 0;
211 uint32_t status;
Sridhar Parasuramfb0d9c82015-02-02 15:23:13 -0800212 uint32_t id, id2;
213 uint32_t flash_cmd = NAND_CMD_FETCH_ID | BIT(19); //bit 19 needs to be set to get extended NAND ID
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700214 uint32_t exec_cmd = 1;
215 int nand_ret = NANDC_RESULT_SUCCESS;
216
217 /* Issue the Fetch id command to the NANDc */
218 bam_add_cmd_element(cmd_list_ptr, NAND_FLASH_CMD, (uint32_t)flash_cmd, CE_WRITE_TYPE);
219 cmd_list_ptr++;
220
221 /* Execute the cmd */
222 bam_add_cmd_element(cmd_list_ptr, NAND_EXEC_CMD, (uint32_t)exec_cmd, CE_WRITE_TYPE);
223 cmd_list_ptr++;
224
225 /* Prepare the cmd desc for the above commands */
226 bam_add_one_desc(&bam,
227 CMD_PIPE_INDEX,
228 (unsigned char*)cmd_list_ptr_start,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -0700229 PA((uint32_t)cmd_list_ptr - (uint32_t)cmd_list_ptr_start),
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700230 BAM_DESC_LOCK_FLAG | BAM_DESC_INT_FLAG |
231 BAM_DESC_NWD_FLAG | BAM_DESC_CMD_FLAG);
232
233 /* Keep track of the number of desc added. */
234 num_desc++;
235 qpic_nand_wait_for_cmd_exec(num_desc);
236
237 cmd_list_ptr_start = ce_array;
238 cmd_list_ptr = ce_array;
239
240 /* Read the status register */
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800241 status = qpic_nand_read_reg(NAND_FLASH_STATUS, 0);
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700242
243 /* Check for errors */
244 nand_ret = qpic_nand_check_status(status);
245 if (nand_ret)
246 {
247 dprintf( CRITICAL, "Read ID cmd status failed\n");
248 goto qpic_nand_fetch_id_err;
249 }
250
251 /* Read the id */
Sridhar Parasuramfb0d9c82015-02-02 15:23:13 -0800252 id = qpic_nand_read_reg(NAND_READ_ID, 0);
253 id2 = qpic_nand_read_reg(NAND_READ_ID2, BAM_DESC_UNLOCK_FLAG);
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700254
255 flash->id = id;
Sridhar Parasuramfb0d9c82015-02-02 15:23:13 -0800256 flash->id2 = id2;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700257 flash->vendor = id & 0xff;
258 flash->device = (id >> 8) & 0xff;
259 flash->dev_cfg = (id >> 24) & 0xFF;
260 flash->widebus = 0;
261 flash->widebus &= (id >> 24) & 0xFF;
262 flash->widebus = flash->widebus? 1: 0;
263
264qpic_nand_fetch_id_err:
265 return nand_ret;
266}
267
268static int
Deepa Dinamanie9ded132012-11-27 15:03:38 -0800269qpic_bam_init(struct qpic_nand_init_config *config)
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700270{
271 uint32_t bam_ret = NANDC_RESULT_SUCCESS;
272
Deepa Dinamanie9ded132012-11-27 15:03:38 -0800273 bam.base = config->bam_base;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700274 /* Set Read pipe params. */
Deepa Dinamanie9ded132012-11-27 15:03:38 -0800275 bam.pipe[DATA_PRODUCER_PIPE_INDEX].pipe_num = config->pipes.read_pipe;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700276 /* System consumer */
277 bam.pipe[DATA_PRODUCER_PIPE_INDEX].trans_type = BAM2SYS;
278 bam.pipe[DATA_PRODUCER_PIPE_INDEX].fifo.size = QPIC_BAM_DATA_FIFO_SIZE;
279 bam.pipe[DATA_PRODUCER_PIPE_INDEX].fifo.head = data_desc_fifo;
Deepa Dinamani536d3f82013-07-09 13:05:56 -0700280 bam.pipe[DATA_PRODUCER_PIPE_INDEX].lock_grp = config->pipes.read_pipe_grp;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700281
282 /* Set Write pipe params. */
Deepa Dinamanie9ded132012-11-27 15:03:38 -0800283 bam.pipe[DATA_CONSUMER_PIPE_INDEX].pipe_num = config->pipes.write_pipe;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700284 /* System producer */
285 bam.pipe[DATA_CONSUMER_PIPE_INDEX].trans_type = SYS2BAM;
286 bam.pipe[DATA_CONSUMER_PIPE_INDEX].fifo.size = QPIC_BAM_DATA_FIFO_SIZE;
287 bam.pipe[DATA_CONSUMER_PIPE_INDEX].fifo.head = data_desc_fifo;
Deepa Dinamani536d3f82013-07-09 13:05:56 -0700288 bam.pipe[DATA_CONSUMER_PIPE_INDEX].lock_grp = config->pipes.write_pipe_grp;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700289
290 /* Set Cmd pipe params. */
Deepa Dinamanie9ded132012-11-27 15:03:38 -0800291 bam.pipe[CMD_PIPE_INDEX].pipe_num = config->pipes.cmd_pipe;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700292 /* System consumer */
Sundarajan Srinivasan357c35a2013-07-23 17:00:54 -0700293 bam.pipe[CMD_PIPE_INDEX].trans_type = SYS2BAM;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700294 bam.pipe[CMD_PIPE_INDEX].fifo.size = QPIC_BAM_CMD_FIFO_SIZE;
295 bam.pipe[CMD_PIPE_INDEX].fifo.head = cmd_desc_fifo;
Deepa Dinamani536d3f82013-07-09 13:05:56 -0700296 bam.pipe[CMD_PIPE_INDEX].lock_grp = config->pipes.cmd_pipe_grp;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700297
298 /* Programs the threshold for BAM transfer
299 * When this threshold is reached, BAM signals the peripheral via the pipe_bytes_available
300 * interface.
301 * The peripheral is signalled with this notification in the following cases:
302 * a. It has accumulated all the descriptors.
303 * b. It has accumulated more than threshold bytes.
304 * c. It has reached EOT (End Of Transfer).
305 * Note: this value needs to be set by the h/w folks and is specific for each peripheral.
306 */
307 bam.threshold = 32;
308
Deepa Dinamanie9ded132012-11-27 15:03:38 -0800309 /* Set the EE. */
310 bam.ee = config->ee;
311
312 /* Set the max desc length for this BAM. */
313 bam.max_desc_len = config->max_desc_len;
314
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700315 /* BAM Init. */
316 bam_init(&bam);
317
318 /* Initialize BAM QPIC read pipe */
319 bam_sys_pipe_init(&bam, DATA_PRODUCER_PIPE_INDEX);
320
321 /* Init read fifo */
322 bam_ret = bam_pipe_fifo_init(&bam, bam.pipe[DATA_PRODUCER_PIPE_INDEX].pipe_num);
323
324 if (bam_ret)
325 {
326 dprintf(CRITICAL, "QPIC:NANDc BAM Read FIFO init error\n");
327 bam_ret = NANDC_RESULT_FAILURE;
328 goto qpic_nand_bam_init_error;
329 }
330
331 /* Initialize BAM QPIC write pipe */
332 bam_sys_pipe_init(&bam, DATA_CONSUMER_PIPE_INDEX);
333
334 /* Init write fifo. Use the same fifo as read fifo. */
335 bam_ret = bam_pipe_fifo_init(&bam, bam.pipe[DATA_CONSUMER_PIPE_INDEX].pipe_num);
336
337 if (bam_ret)
338 {
339 dprintf(CRITICAL, "QPIC: NANDc: BAM Write FIFO init error\n");
340 bam_ret = NANDC_RESULT_FAILURE;
341 goto qpic_nand_bam_init_error;
342 }
343
344 /* Initialize BAM QPIC cmd pipe */
345 bam_sys_pipe_init(&bam, CMD_PIPE_INDEX);
346
347 /* Init cmd fifo */
348 bam_ret = bam_pipe_fifo_init(&bam, bam.pipe[CMD_PIPE_INDEX].pipe_num);
349
350 if (bam_ret)
351 {
352 dprintf(CRITICAL, "QPIC:NANDc BAM CMD FIFO init error\n");
353 bam_ret = NANDC_RESULT_FAILURE;
354 goto qpic_nand_bam_init_error;
355 }
356
357qpic_nand_bam_init_error:
358return bam_ret;
359}
360
361/* Adds command elements for addr and cfg register writes.
362 * cfg: Defines the configuration for the flash cmd.
363 * start: Address where the command elements are added.
364 *
365 * Returns the address where the next cmd element can be added.
366 */
367static struct cmd_element*
368qpic_nand_add_addr_n_cfg_ce(struct cfg_params *cfg,
369 struct cmd_element *start)
370{
371 struct cmd_element *cmd_list_ptr = start;
372
373 bam_add_cmd_element(cmd_list_ptr, NAND_ADDR0, (uint32_t)cfg->addr0, CE_WRITE_TYPE);
374 cmd_list_ptr++;
375 bam_add_cmd_element(cmd_list_ptr, NAND_ADDR1, (uint32_t)cfg->addr1, CE_WRITE_TYPE);
376 cmd_list_ptr++;
377 bam_add_cmd_element(cmd_list_ptr, NAND_DEV0_CFG0, (uint32_t)cfg->cfg0, CE_WRITE_TYPE);
378 cmd_list_ptr++;
379 bam_add_cmd_element(cmd_list_ptr, NAND_DEV0_CFG1, (uint32_t)cfg->cfg1, CE_WRITE_TYPE);
380 cmd_list_ptr++;
381
382 return cmd_list_ptr;
383}
384
385
386static struct cmd_element*
387qpic_nand_add_onfi_probe_ce(struct onfi_probe_params *params,
388 struct cmd_element *start)
389{
390 struct cmd_element *cmd_list_ptr = start;
391
392 cmd_list_ptr = qpic_nand_add_addr_n_cfg_ce(&params->cfg, cmd_list_ptr);
393
394 bam_add_cmd_element(cmd_list_ptr, NAND_DEV_CMD1, (uint32_t)params->dev_cmd1, CE_WRITE_TYPE);
395 cmd_list_ptr++;
396 bam_add_cmd_element(cmd_list_ptr, NAND_DEV_CMD_VLD, (uint32_t)params->vld, CE_WRITE_TYPE);
397 cmd_list_ptr++;
398 bam_add_cmd_element(cmd_list_ptr, NAND_READ_LOCATION_n(0), (uint32_t)params->cfg.addr_loc_0, CE_WRITE_TYPE);
399 cmd_list_ptr++;
400 bam_add_cmd_element(cmd_list_ptr, NAND_FLASH_CMD, (uint32_t)params->cfg.cmd, CE_WRITE_TYPE);
401 cmd_list_ptr++;
402 bam_add_cmd_element(cmd_list_ptr, NAND_EXEC_CMD, (uint32_t)params->cfg.exec, CE_WRITE_TYPE);
403 cmd_list_ptr++;
404
405 return cmd_list_ptr;
406}
407
408static int
409onfi_probe_cmd_exec(struct onfi_probe_params *params,
410 unsigned char* data_ptr,
411 int data_len)
412{
413 struct cmd_element *cmd_list_ptr = ce_array;
414 struct cmd_element *cmd_list_ptr_start = ce_array;
415 int num_desc = 0;
416 uint32_t status = 0;
417 int nand_ret = NANDC_RESULT_SUCCESS;
418 uint8_t desc_flags = BAM_DESC_NWD_FLAG | BAM_DESC_CMD_FLAG
419 | BAM_DESC_LOCK_FLAG | BAM_DESC_INT_FLAG;
420
421 params->cfg.addr_loc_0 = 0;
422 params->cfg.addr_loc_0 |= NAND_RD_LOC_LAST_BIT(1);
423 params->cfg.addr_loc_0 |= NAND_RD_LOC_OFFSET(0);
424 params->cfg.addr_loc_0 |= NAND_RD_LOC_SIZE(data_len);
425
426 cmd_list_ptr = qpic_nand_add_onfi_probe_ce(params, cmd_list_ptr);
427
428 /* Enqueue the desc for the above commands */
429 bam_add_one_desc(&bam,
430 CMD_PIPE_INDEX,
431 (unsigned char*)cmd_list_ptr_start,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -0700432 PA((addr_t)(uint32_t)cmd_list_ptr - (uint32_t)cmd_list_ptr_start),
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700433 desc_flags);
434
435 cmd_list_ptr_start = cmd_list_ptr;
436 num_desc++;
437
438 /* Add Data desc */
439 bam_add_desc(&bam,
440 DATA_PRODUCER_PIPE_INDEX,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -0700441 (unsigned char *)PA((addr_t)data_ptr),
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700442 data_len,
443 BAM_DESC_INT_FLAG);
444
445 /* Wait for the commands to be executed */
446 qpic_nand_wait_for_cmd_exec(num_desc);
447
448 /* Read buffer status and check for errors. */
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800449 status = qpic_nand_read_reg(NAND_FLASH_STATUS, 0);
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700450
451 if (qpic_nand_check_status(status))
452 {
453 nand_ret = NANDC_RESULT_FAILURE;
454 goto onfi_probe_exec_err;
455 }
456
457 /* Wait for data to be available */
458 qpic_nand_wait_for_data(DATA_PRODUCER_PIPE_INDEX);
459
460 /* Check for errors */
461 nand_ret = qpic_nand_check_status(status);
462
463onfi_probe_exec_err:
464 return nand_ret;
465}
466
467/* TODO: check why both vld and cmd need to be written. */
468void
469qpic_nand_onfi_probe_cleanup(uint32_t vld, uint32_t dev_cmd1)
470{
471 struct cmd_element *cmd_list_ptr = ce_array;
472 struct cmd_element *cmd_list_ptr_start = ce_array;
473
474 bam_add_cmd_element(cmd_list_ptr, NAND_DEV_CMD1, dev_cmd1, CE_WRITE_TYPE);
475 cmd_list_ptr++;
476 bam_add_cmd_element(cmd_list_ptr, NAND_DEV_CMD_VLD, vld, CE_WRITE_TYPE);
477 cmd_list_ptr++;
478
479 /* Enqueue the desc for the above commands */
480 bam_add_one_desc(&bam,
481 CMD_PIPE_INDEX,
482 (unsigned char*)cmd_list_ptr_start,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -0700483 PA((uint32_t)cmd_list_ptr - (uint32_t)cmd_list_ptr_start),
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700484 BAM_DESC_UNLOCK_FLAG | BAM_DESC_CMD_FLAG| BAM_DESC_INT_FLAG);
485
486 qpic_nand_wait_for_cmd_exec(1);
487}
488
489static int
490qpic_nand_onfi_save_params(struct onfi_param_page *param_page, struct flash_info *flash)
491{
492 int onfi_ret = NANDC_RESULT_SUCCESS;
493 uint32_t ecc_bits;
494
495 onfi_ret = qpic_nand_fetch_id(flash);
496
497 if (onfi_ret)
498 {
499 dprintf(CRITICAL, "Fetch ID cmd failed\n");
500 goto onfi_save_params_err;
501 }
502
503 flash->page_size = param_page->data_per_pg;
504 flash->block_size = param_page->pgs_per_blk * flash->page_size;
505 flash->num_blocks = param_page->blks_per_LUN;
506 flash->widebus = param_page->feature_supported & 0x1;
507 flash->density = param_page->blks_per_LUN * flash->blksize;
508 flash->spare_size = param_page->spare_per_pg;
509 ecc_bits = param_page->num_bits_ecc_correctability;
510 flash->num_pages_per_blk = param_page->pgs_per_blk;
511 flash->num_pages_per_blk_mask = param_page->pgs_per_blk - 1;
512
513 if (ecc_bits >= 8)
514 flash->ecc_width = NAND_WITH_8_BIT_ECC;
515 else
516 flash->ecc_width = NAND_WITH_4_BIT_ECC;
517
518 onfi_save_params_err:
519 return onfi_ret;
520}
521
522static void
523qpic_nand_save_config(struct flash_info *flash)
524{
Channagoud Kadabib1dc47c2015-05-21 17:02:44 -0700525 uint32_t spare_bytes = 0;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700526
527 /* Save Configurations */
528 flash->cws_per_page = flash->page_size >> NAND_CW_DIV_RIGHT_SHIFT;
529
Deepa Dinamani16663a62013-02-07 16:25:59 -0800530 /* Verify that we have enough buffer to handle all the cws in a page. */
531 ASSERT(flash->cws_per_page <= QPIC_NAND_MAX_CWS_IN_PAGE);
532
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700533 /* Codeword Size = UD_SIZE_BYTES + ECC_PARITY_SIZE_BYTES
534 * + SPARE_SIZE_BYTES + Bad Block size
535 */
536 if (flash->ecc_width & NAND_WITH_8_BIT_ECC)
537 {
538 flash->cw_size = NAND_CW_SIZE_8_BIT_ECC;
539 ecc_bch_cfg |= (1 << NAND_DEV0_ECC_MODE_SHIFT); /* Use 8-bit ecc */
540
541 if (flash->widebus)
542 {
543 cfg0 |= (0 << NAND_DEV0_CFG0_SPARE_SZ_BYTES_SHIFT); /* spare size bytes in each CW */
544 ecc_bch_cfg |= (14 << NAND_DEV0_ECC_PARITY_SZ_BYTES_SHIFT); /* parity bytes in each CW */
545 }
546 else
547 {
548 cfg0 |= (2 << NAND_DEV0_CFG0_SPARE_SZ_BYTES_SHIFT); /* spare size bytes in each CW */
549 ecc_bch_cfg |= (13 << NAND_DEV0_ECC_PARITY_SZ_BYTES_SHIFT); /* parity bytes in each CW */
550 }
551 }
552 else
553 {
554 flash->cw_size = NAND_CW_SIZE_4_BIT_ECC;
555
556 if (flash->widebus)
557 {
558 cfg0 |= (2 << NAND_DEV0_CFG0_SPARE_SZ_BYTES_SHIFT); /* spare size bytes in each CW */
559 ecc_bch_cfg |= (8 << NAND_DEV0_ECC_PARITY_SZ_BYTES_SHIFT); /* parity bytes in each CW */
560 }
561 else
562 {
563 cfg0 |= (4 << NAND_DEV0_CFG0_SPARE_SZ_BYTES_SHIFT); /* spare size bytes in each CW */
564 ecc_bch_cfg |= (7 << NAND_DEV0_ECC_PARITY_SZ_BYTES_SHIFT); /* parity bytes in each CW */
565 }
566 }
567
568 /* BAD_BLOCK_BYTE_NUM = Page Size -
569 * (CW_PER_PAGE * Codeword Size) + 1
570 * Note: Set CW_PER_PAGE to 1 less than the actual number.
571 */
572 flash->bad_blk_loc = flash->page_size - flash->cw_size * (flash->cws_per_page - 1) + 1;
573
Channagoud Kadabib1dc47c2015-05-21 17:02:44 -0700574 /* Calculate the parity and spare bytes */
575 ecc_parity_bytes = (flash->ecc_width & NAND_WITH_8_BIT_ECC) ? (flash->widebus ? 14 : 13) : (flash->widebus ? 8 : 7) ;
576 spare_bytes = flash->cw_size - (USER_DATA_BYTES_PER_CW + ecc_parity_bytes);
577
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700578 cfg0 |= ((flash->cws_per_page - 1) << NAND_DEV0_CFG0_CW_PER_PAGE_SHIFT) /* 4/8 cw/pg for 2/4k */
579 |(DATA_BYTES_IN_IMG_PER_CW << NAND_DEV0_CFG0_UD_SIZE_BYTES_SHIFT) /* 516 user data bytes */
580 |(5 << NAND_DEV0_CFG0_ADDR_CYCLE_SHIFT) /* 5 address cycles */
581 |(0 << NAND_DEV0_CFG0_DIS_STS_AFTER_WR_SHIFT);/* Send read status cmd after each write. */
582
583 cfg1 |= (7 << NAND_DEV0_CFG1_RECOVERY_CYCLES_SHIFT) /* 8 recovery cycles */
584 |(0 << NAND_DEV0_CFG1_CS_ACTIVE_BSY_SHIFT) /* Allow CS deassertion */
585 |(flash->bad_blk_loc << NAND_DEV0_CFG1_BAD_BLK_BYTE_NUM_SHIFT)/* Bad block marker location */
586 |(0 << NAND_DEV0_CFG1_BAD_BLK_IN_SPARE_SHIFT) /* Bad block in user data area */
587 |(2 << NAND_DEV0_CFG1_WR_RD_BSY_GAP_SHIFT) /* 8 cycle tWB/tRB */
588 |(flash->widebus << NAND_DEV0_CFG1_WIDE_BUS_SHIFT); /* preserve wide flash flag */
589
Channagoud Kadabib1dc47c2015-05-21 17:02:44 -0700590 cfg0_raw = ((flash->cws_per_page - 1) << NAND_DEV0_CFG0_CW_PER_PAGE_SHIFT)
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700591 |(5 << NAND_DEV0_CFG0_ADDR_CYCLE_SHIFT)
Channagoud Kadabib1dc47c2015-05-21 17:02:44 -0700592 |(512 << NAND_DEV0_CFG0_UD_SIZE_BYTES_SHIFT)
593 | (spare_bytes << NAND_DEV0_CFG0_SPARE_SZ_BYTES_SHIFT);
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700594
Channagoud Kadabib1dc47c2015-05-21 17:02:44 -0700595 cfg1_raw = (2 << NAND_DEV0_CFG1_WR_RD_BSY_GAP_SHIFT)
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700596 | (1 << NAND_DEV0_CFG1_BAD_BLK_IN_SPARE_SHIFT)
Channagoud Kadabib1dc47c2015-05-21 17:02:44 -0700597 | (21 << NAND_DEV0_CFG1_BAD_BLK_BYTE_NUM_SHIFT)
598 | (0 << NAND_DEV0_CFG1_CS_ACTIVE_BSY_SHIFT)
599 | (7 << NAND_DEV0_CFG1_RECOVERY_CYCLES_SHIFT)
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700600 | (flash->widebus << NAND_DEV0_CFG1_WIDE_BUS_SHIFT)
601 |1 ; /* to disable reed solomon ecc..this feild is now read only. */
602
603 ecc_bch_cfg |= (0 << NAND_DEV0_ECC_DISABLE_SHIFT) /* Enable ECC */
604 | (0 << NAND_DEV0_ECC_SW_RESET_SHIFT) /* Put ECC core in op mode */
605 | (DATA_BYTES_IN_IMG_PER_CW << NAND_DEV0_ECC_NUM_DATA_BYTES)
606 | (1 << NAND_DEV0_ECC_FORCE_CLK_OPEN_SHIFT); /* Enable all clocks */
Channagoud Kadabib1dc47c2015-05-21 17:02:44 -0700607
608 ecc_cfg_raw = (1 << NAND_DEV0_ECC_FORCE_CLK_OPEN_SHIFT)
609 | (DATA_BYTES_IN_IMG_PER_CW << NAND_DEV0_ECC_NUM_DATA_BYTES)
610 | (ecc_parity_bytes << NAND_DEV0_ECC_PARITY_SZ_BYTES_SHIFT)
611 | (0 << NAND_DEV0_ECC_SW_RESET_SHIFT)
612 | (1 << NAND_DEV0_ECC_DISABLE_SHIFT);
613
614#if DEBUG_QPIC_NAND
615 dprintf(INFO, "CFG0: 0x%08x CFG1: 0x%08x\n", cfg0, cfg1);
616 dprintf(INFO, "CFG0_RAW: 0x%08x CFG1_RAW: 0x%08x\n", cfg0_raw, cfg1_raw);
617 dprintf(INFO, "ECC_BCH_CFG: 0x%08x ECC_CFG_RAW: 0x%08x\n", ecc_bch_cfg, ecc_cfg_raw);
618#endif
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700619}
620
621/* Onfi probe should issue the following commands to the flash device:
622 * 1. Read ID - with addr ONFI_READ_ID_ADDR.
623 * This returns the ONFI ASCII string indicating support for ONFI.
624 * 2. Read Prameter Page - with addr ONFI_READ_PARAM_PAGE_ADDR.
625 * This returns the params for the device.
626 * Each command inturn issues commands- ADDR0, ADDR1, chip_select,
627 * cfg0, cfg1, cmd_vld, dev_cmd1, read_loc0, flash, exec.
628 */
629static int
630qpic_nand_onfi_probe(struct flash_info *flash)
631{
632 struct onfi_probe_params params;
633 uint32_t vld;
634 uint32_t dev_cmd1;
635 unsigned char *buffer;
636 unsigned char onfi_str[4];
637 uint32_t *id;
638 struct onfi_param_page *param_page;
639 int onfi_ret = NANDC_RESULT_SUCCESS;
640
641 /* Allocate memory required to read the onfi param page */
642 buffer = (unsigned char*) malloc(ONFI_READ_PARAM_PAGE_BUFFER_SIZE);
Maria Yu71909742014-07-04 17:30:00 +0800643 ASSERT(buffer != NULL);
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700644
645 /* Read the vld and dev_cmd1 registers before modifying */
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800646 vld = qpic_nand_read_reg(NAND_DEV_CMD_VLD, 0);
647 dev_cmd1 = qpic_nand_read_reg(NAND_DEV_CMD1, 0);
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700648
649 /* Initialize flash cmd */
650 params.cfg.cmd = NAND_CMD_PAGE_READ;
651 params.cfg.exec = 1;
652
653 /* Execute Read ID cmd */
654
655 /* Initialize the config */
656 params.cfg.cfg0 = NAND_CFG0_RAW_ONFI_ID;
657 params.cfg.cfg1 = NAND_CFG1_RAW_ONFI_ID;
658
659 /* Initialize the cmd and vld */
660 params.dev_cmd1 = (dev_cmd1 & 0xFFFFFF00) | ONFI_READ_ID_CMD;
661 params.vld = vld & 0xFFFFFFFE;
662
663 /* Initialize the address
664 * addr1 is not used bcos of the cfg.
665 */
666 params.cfg.addr0 = ONFI_READ_ID_ADDR;
667 params.cfg.addr1 = 0;
668
669 /* Lock the pipe and execute the cmd. */
670 onfi_ret = onfi_probe_cmd_exec(&params, onfi_str, ONFI_READ_ID_BUFFER_SIZE);
671 if (onfi_ret)
672 {
673 dprintf(CRITICAL, "ONFI Read id cmd failed\n");
674 goto qpic_nand_onfi_probe_err;
675 }
676
677 /* Write back vld and cmd and unlock the pipe. */
678 qpic_nand_onfi_probe_cleanup(vld, dev_cmd1);
679
680 /* Check for onfi string */
681 id = (uint32_t*)onfi_str;
682 if (*id != ONFI_SIGNATURE)
683 {
684 dprintf(CRITICAL, "Not an ONFI device\n");
685 /* Not an onfi device. Return error. */
686 onfi_ret = NANDC_RESULT_DEV_NOT_SUPPORTED;
687 goto qpic_nand_onfi_probe_err;
688 }
689
690 dprintf(INFO, "ONFI device found\n");
691 /* Now read the param page */
692 /* Initialize the config */
693 params.cfg.cfg0 = NAND_CFG0_RAW_ONFI_PARAM_PAGE;
694 params.cfg.cfg1 = NAND_CFG1_RAW_ONFI_PARAM_PAGE;
695
696 /* Initialize the cmd and vld */
697 params.dev_cmd1 = (dev_cmd1 & 0xFFFFFF00) | ONFI_READ_PARAM_PAGE_CMD;
698 params.vld = vld & 0xFFFFFFFE;
699
700 /* Initialize the address
701 * addr1 is not used bcos of the cfg.
702 */
703 params.cfg.addr0 = ONFI_READ_PARAM_PAGE_ADDR;
704 params.cfg.addr1 = 0;
705
706 /* Lock the pipe and execute the cmd. */
707 onfi_ret = onfi_probe_cmd_exec(&params, buffer, ONFI_READ_PARAM_PAGE_BUFFER_SIZE);
708 if (onfi_ret)
709 {
710 dprintf(CRITICAL, "ONFI Read param page failed\n");
711 goto qpic_nand_onfi_probe_err;
712 }
713
714 /* Write back vld and cmd and unlock the pipe. */
715 qpic_nand_onfi_probe_cleanup(vld, dev_cmd1);
716
717 /* Verify the integrity of the returned page */
718 param_page = (struct onfi_param_page*)buffer;
719
720 /* TODO: Add CRC check to validate the param page. */
721
722 /* Save the parameter values */
723 onfi_ret = qpic_nand_onfi_save_params(param_page, flash);
724
725qpic_nand_onfi_probe_err:
726 if (onfi_ret)
727 dprintf(CRITICAL, "ONFI probe failed\n");
728
729 free(buffer);
730
731 return onfi_ret;
732}
733
734/* Enquues a desc for a flash cmd with NWD flag set:
735 * cfg: Defines the configuration for the flash cmd.
736 * start: Address where the command elements are added.
737 *
738 * Returns the address where the next cmd element can be added.
739 */
740struct cmd_element*
741qpic_nand_add_cmd_ce(struct cfg_params *cfg,
742 struct cmd_element *start)
743{
744 struct cmd_element *cmd_list_ptr;
745
746 cmd_list_ptr = qpic_nand_add_addr_n_cfg_ce(cfg, start);
747
748 bam_add_cmd_element(cmd_list_ptr, NAND_FLASH_CMD, (uint32_t)cfg->cmd, CE_WRITE_TYPE);
749 cmd_list_ptr++;
750
751 bam_add_cmd_element(cmd_list_ptr, NAND_EXEC_CMD, (uint32_t)cfg->exec, CE_WRITE_TYPE);
752 cmd_list_ptr++;
753
754 return cmd_list_ptr;
755}
756
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800757/* Reads nand_flash_status */
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700758struct cmd_element*
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800759qpic_nand_add_read_ce(struct cmd_element *start, uint32_t *flash_status_read)
760{
761 struct cmd_element *cmd_list_ptr = start;
762
763 bam_add_cmd_element(cmd_list_ptr, NAND_FLASH_STATUS, (uint32_t)PA((addr_t)flash_status_read), CE_READ_TYPE);
764 cmd_list_ptr++;
765
766 return cmd_list_ptr;
767}
768
769/* Resets nand_flash_status and nand_read_status */
770struct cmd_element*
771qpic_nand_reset_status_ce(struct cmd_element *start, uint32_t read_status)
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700772{
773 struct cmd_element *cmd_list_ptr = start;
774 uint32_t flash_status_reset;
775 uint32_t read_status_reset;
776
777 /* Read and reset the status registers. */
778 flash_status_reset = NAND_FLASH_STATUS_RESET;
779 read_status_reset = NAND_READ_STATUS_RESET;
780
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700781 bam_add_cmd_element(cmd_list_ptr, NAND_FLASH_STATUS, (uint32_t)flash_status_reset, CE_WRITE_TYPE);
782 cmd_list_ptr++;
783
784 if (read_status)
785 {
786 bam_add_cmd_element(cmd_list_ptr, NAND_READ_STATUS, (uint32_t)read_status_reset, CE_WRITE_TYPE);
787 cmd_list_ptr++;
788 }
789
790 return cmd_list_ptr;
791}
792
793struct cmd_element*
794qpic_nand_add_isbad_cmd_ce(struct cfg_params *cfg,
795 struct cmd_element *start)
796{
797 struct cmd_element *cmd_list_ptr = start;
798
799 bam_add_cmd_element(cmd_list_ptr, NAND_DEV0_ECC_CFG, (uint32_t)cfg->ecc_cfg, CE_WRITE_TYPE);
800 cmd_list_ptr++;
801
802 bam_add_cmd_element(cmd_list_ptr, NAND_READ_LOCATION_n(0), (uint32_t)cfg->addr_loc_0, CE_WRITE_TYPE);
803 cmd_list_ptr++;
804
805 cmd_list_ptr = qpic_nand_add_cmd_ce(cfg, cmd_list_ptr);
806
807 return cmd_list_ptr;
808}
809
810static int
811qpic_nand_block_isbad_exec(struct cfg_params *params,
812 uint8_t *bad_block)
813{
814
815 struct cmd_element *cmd_list_ptr = ce_array;
816 struct cmd_element *cmd_list_ptr_start = ce_array;
817 uint8_t desc_flags = BAM_DESC_NWD_FLAG | BAM_DESC_CMD_FLAG
818 | BAM_DESC_LOCK_FLAG | BAM_DESC_INT_FLAG;
819 int num_desc = 0;
820 uint32_t status = 0;
821 int nand_ret = NANDC_RESULT_SUCCESS;
822
823 cmd_list_ptr = qpic_nand_add_isbad_cmd_ce(params, cmd_list_ptr);
824
825 /* Enqueue the desc for the above commands */
826 bam_add_one_desc(&bam,
827 CMD_PIPE_INDEX,
828 (unsigned char*)cmd_list_ptr_start,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -0700829 PA((uint32_t)cmd_list_ptr - (uint32_t)cmd_list_ptr_start),
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700830 desc_flags);
831
832 num_desc++;
833
834 /* Add Data desc */
835 bam_add_desc(&bam,
836 DATA_PRODUCER_PIPE_INDEX,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -0700837 (unsigned char *)PA((addr_t)bad_block),
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700838 4,
839 BAM_DESC_INT_FLAG);
840
841 qpic_nand_wait_for_cmd_exec(num_desc);
842
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800843 status = qpic_nand_read_reg(NAND_FLASH_STATUS, 0);
Deepa Dinamani19530062012-10-03 14:43:05 -0700844
845 nand_ret = qpic_nand_check_status(status);
846
847 /* Dummy read to unlock pipe. */
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800848 status = qpic_nand_read_reg(NAND_FLASH_STATUS, BAM_DESC_UNLOCK_FLAG);
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700849
Deepa Dinamani19530062012-10-03 14:43:05 -0700850 if (nand_ret)
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700851 return NANDC_RESULT_FAILURE;
852
853 qpic_nand_wait_for_data(DATA_PRODUCER_PIPE_INDEX);
854
855 return nand_ret;
856}
857
Tanya Brokhman72b44dc2015-01-07 10:20:05 +0200858/**
859 * qpic_nand_block_isbad() - Checks is given block is bad
860 * @page - number of page the block starts at
861 *
862 * Returns nand_result_t
863 */
864nand_result_t qpic_nand_block_isbad(unsigned page)
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700865{
866 unsigned cwperpage;
867 struct cfg_params params;
868 uint8_t bad_block[4];
869 unsigned nand_ret = NANDC_RESULT_SUCCESS;
Deepa Dinamanidc1381e2012-11-15 14:53:24 -0800870 uint32_t blk = page / flash.num_pages_per_blk;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700871
Deepa Dinamanidc1381e2012-11-15 14:53:24 -0800872 if (bbtbl[blk] == NAND_BAD_BLK_VALUE_IS_GOOD)
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700873 return NANDC_RESULT_SUCCESS;
Deepa Dinamanidc1381e2012-11-15 14:53:24 -0800874 else if (bbtbl[blk] == NAND_BAD_BLK_VALUE_IS_BAD)
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700875 return NANDC_RESULT_BAD_BLOCK;
876 else
877 {
878 /* Read the bad block value from the flash.
879 * Bad block value is stored in the first page of the block.
880 */
881 /* Read the first page in the block. */
882 cwperpage = flash.cws_per_page;
883
884 /* Read page cmd */
Deepa Dinamanidc1381e2012-11-15 14:53:24 -0800885 params.cmd = NAND_CMD_PAGE_READ_ECC;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700886 /* Clear the CW per page bits */
887 params.cfg0 = cfg0_raw & ~(7U << NAND_DEV0_CFG0_CW_PER_PAGE_SHIFT);
888 params.cfg1 = cfg1_raw;
Deepa Dinamanidc1381e2012-11-15 14:53:24 -0800889 /* addr0 - Write column addr + few bits in row addr upto 32 bits. */
890 params.addr0 = (page << 16) | (USER_DATA_BYTES_PER_CW * cwperpage);
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700891
892 /* addr1 - Write rest of row addr.
893 * This will be all 0s.
894 */
Deepa Dinamanidc1381e2012-11-15 14:53:24 -0800895 params.addr1 = (page >> 16) & 0xff;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700896 params.addr_loc_0 = NAND_RD_LOC_OFFSET(0);
897 params.addr_loc_0 |= NAND_RD_LOC_LAST_BIT(1);
898 params.addr_loc_0 |= NAND_RD_LOC_SIZE(4); /* Read 4 bytes */
Deepa Dinamanidc1381e2012-11-15 14:53:24 -0800899 params.ecc_cfg = ecc_bch_cfg | 0x1; /* Disable ECC */
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700900 params.exec = 1;
901
902 if (qpic_nand_block_isbad_exec(&params, bad_block))
903 {
904 dprintf(CRITICAL,
905 "Could not read bad block value\n");
906 return NANDC_RESULT_FAILURE;
907 }
908
909 if (flash.widebus)
910 {
911 if (bad_block[0] != 0xFF && bad_block[1] != 0xFF)
912 {
Deepa Dinamanidc1381e2012-11-15 14:53:24 -0800913 bbtbl[blk] = NAND_BAD_BLK_VALUE_IS_BAD;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700914 nand_ret = NANDC_RESULT_BAD_BLOCK;
915 }
916 }
917 else if (bad_block[0] != 0xFF)
918 {
Deepa Dinamanidc1381e2012-11-15 14:53:24 -0800919 bbtbl[blk] = NAND_BAD_BLK_VALUE_IS_BAD;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700920 nand_ret = NANDC_RESULT_BAD_BLOCK;
921 }
922 else
Deepa Dinamanidc1381e2012-11-15 14:53:24 -0800923 bbtbl[blk] = NAND_BAD_BLK_VALUE_IS_GOOD;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700924
925 return nand_ret;
926 }
927}
928
929/* Function to erase a block on the nand.
930 * page: Starting page address for the block.
931 */
Tanya Brokhman72b44dc2015-01-07 10:20:05 +0200932nand_result_t qpic_nand_blk_erase(uint32_t page)
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700933{
934 struct cfg_params cfg;
935 struct cmd_element *cmd_list_ptr = ce_array;
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800936 struct cmd_element *cmd_list_read_ptr = ce_read_array;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700937 struct cmd_element *cmd_list_ptr_start = ce_array;
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800938 struct cmd_element *cmd_list_read_ptr_start = ce_read_array;
Veera Sundaram Sankaran00181512014-12-09 11:23:39 -0800939 uint32_t status;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700940 int num_desc = 0;
941 uint32_t blk_addr = page / flash.num_pages_per_blk;
942
943 /* Erase only if the block is not bad */
Deepa Dinamanidc1381e2012-11-15 14:53:24 -0800944 if (qpic_nand_block_isbad(page))
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700945 {
946 dprintf(CRITICAL,
947 "NAND Erase error: Block address belongs to bad block: %d\n",
948 blk_addr);
949 return NANDC_RESULT_FAILURE;
950 }
951
952 /* Fill in params for the erase flash cmd */
953 cfg.addr0 = page;
954 cfg.addr1 = 0;
955 /* Clear CW_PER_PAGE in cfg0 */
956 cfg.cfg0 = cfg0 & ~(7U << NAND_DEV0_CFG0_CW_PER_PAGE_SHIFT);
957 cfg.cfg1 = cfg1;
958 cfg.cmd = NAND_CMD_BLOCK_ERASE;
959 cfg.exec = 1;
960
961 cmd_list_ptr = qpic_nand_add_cmd_ce(&cfg, cmd_list_ptr);
962
963 /* Enqueue the desc for the above commands */
964 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 Dinamani2467bbb2012-10-02 13:59:58 -0700968 BAM_DESC_NWD_FLAG | BAM_DESC_CMD_FLAG | BAM_DESC_INT_FLAG | BAM_DESC_LOCK_FLAG);
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700969
970 cmd_list_ptr_start = cmd_list_ptr;
971 num_desc++;
972
973 qpic_nand_wait_for_cmd_exec(num_desc);
974
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800975 status = qpic_nand_read_reg(NAND_FLASH_STATUS, 0);
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700976
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700977 cmd_list_ptr_start = cmd_list_ptr;
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800978 cmd_list_read_ptr_start = cmd_list_read_ptr;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700979
980 /* QPIC controller automatically sends
981 * GET_STATUS cmd to the nand card because
982 * of the configuration programmed.
983 * Read the result of GET_STATUS cmd.
984 */
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800985 cmd_list_read_ptr = qpic_nand_add_read_ce(cmd_list_read_ptr, &status);
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700986
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800987 /* Enqueue the desc for the NAND_FLASH_STATUS read command */
988 bam_add_one_desc(&bam,
989 CMD_PIPE_INDEX,
990 (unsigned char*)cmd_list_read_ptr_start,
991 PA((uint32_t)cmd_list_read_ptr - (uint32_t)cmd_list_read_ptr_start),
992 BAM_DESC_CMD_FLAG) ;
993
994 cmd_list_ptr = qpic_nand_reset_status_ce(cmd_list_ptr, 1);
995
996 /* Enqueue the desc for NAND_FLASH_STATUS and NAND_READ_STATUS write commands */
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700997 bam_add_one_desc(&bam,
998 CMD_PIPE_INDEX,
999 (unsigned char*)cmd_list_ptr_start,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001000 PA((uint32_t)cmd_list_ptr - (uint32_t)cmd_list_ptr_start),
Deepa Dinamani19530062012-10-03 14:43:05 -07001001 BAM_DESC_INT_FLAG | BAM_DESC_CMD_FLAG) ;
Sridhar Parasuramf5188d82014-11-17 15:39:55 -08001002 num_desc = 2;
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001003 qpic_nand_wait_for_cmd_exec(num_desc);
1004
Deepa Dinamani19530062012-10-03 14:43:05 -07001005 status = qpic_nand_check_status(status);
1006
1007 /* Dummy read to unlock pipe. */
Veera Sundaram Sankaran00181512014-12-09 11:23:39 -08001008 qpic_nand_read_reg(NAND_FLASH_STATUS, BAM_DESC_UNLOCK_FLAG);
Deepa Dinamani19530062012-10-03 14:43:05 -07001009
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001010 /* Check for status errors*/
Deepa Dinamani19530062012-10-03 14:43:05 -07001011 if (status)
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001012 {
1013 dprintf(CRITICAL,
1014 "NAND Erase error: Block address belongs to bad block: %d\n",
1015 blk_addr);
Tanya Brokhman72b44dc2015-01-07 10:20:05 +02001016 qpic_nand_mark_badblock(page);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001017 return NANDC_RESULT_FAILURE;
1018 }
1019
1020 /* Check for PROG_ERASE_OP_RESULT bit for the result of erase operation. */
Deepa Dinamani2467bbb2012-10-02 13:59:58 -07001021 if (!(status & PROG_ERASE_OP_RESULT))
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001022 return NANDC_RESULT_SUCCESS;
1023
Tanya Brokhman72b44dc2015-01-07 10:20:05 +02001024 qpic_nand_mark_badblock(page);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001025 return NANDC_RESULT_FAILURE;
1026}
1027
1028/* Return num of desc added. */
Deepa Dinamani19530062012-10-03 14:43:05 -07001029static void
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001030qpic_nand_add_wr_page_cws_cmd_desc(struct cfg_params *cfg,
1031 uint32_t status[],
1032 enum nand_cfg_value cfg_mode)
1033{
1034 struct cmd_element *cmd_list_ptr = ce_array;
Sridhar Parasuramf5188d82014-11-17 15:39:55 -08001035 struct cmd_element *cmd_list_read_ptr = ce_read_array;
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001036 struct cmd_element *cmd_list_ptr_start = ce_array;
Sridhar Parasuramf5188d82014-11-17 15:39:55 -08001037 struct cmd_element *cmd_list_read_ptr_start = ce_read_array;
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001038 uint32_t ecc;
1039 int num_desc = 0;
1040 int int_flag = 0;
1041
1042 if (cfg_mode == NAND_CFG)
1043 ecc = ecc_bch_cfg;
1044 else
Deepa Dinamanidc1381e2012-11-15 14:53:24 -08001045 ecc = ecc_bch_cfg | 0x1; /* Disable ECC */
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001046
1047 /* Add ECC configuration */
1048 bam_add_cmd_element(cmd_list_ptr, NAND_DEV0_ECC_CFG,
1049 (uint32_t)ecc, CE_WRITE_TYPE);
1050 cmd_list_ptr++;
1051 cmd_list_ptr = qpic_nand_add_addr_n_cfg_ce(cfg, cmd_list_ptr);
1052
1053 bam_add_cmd_element(cmd_list_ptr, NAND_FLASH_CMD,
1054 (uint32_t)cfg->cmd, CE_WRITE_TYPE);
1055 cmd_list_ptr++;
1056
1057 /* Enqueue the desc for the above commands */
1058 bam_add_one_desc(&bam,
1059 CMD_PIPE_INDEX,
1060 (unsigned char*)cmd_list_ptr_start,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001061 PA((uint32_t)cmd_list_ptr - (uint32_t)cmd_list_ptr_start),
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001062 BAM_DESC_CMD_FLAG | BAM_DESC_LOCK_FLAG);
1063
1064 num_desc++;
1065
1066 /* Add CE for all the CWs */
1067 for (unsigned i = 0; i < flash.cws_per_page; i++)
1068 {
1069 cmd_list_ptr_start = cmd_list_ptr;
Deepa Dinamani19530062012-10-03 14:43:05 -07001070 int_flag = BAM_DESC_INT_FLAG;
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001071
1072 bam_add_cmd_element(cmd_list_ptr, NAND_EXEC_CMD, (uint32_t)cfg->exec, CE_WRITE_TYPE);
1073 cmd_list_ptr++;
1074
1075 /* Enqueue the desc for the above commands */
1076 bam_add_one_desc(&bam,
1077 CMD_PIPE_INDEX,
1078 (unsigned char*)cmd_list_ptr_start,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001079 PA((uint32_t)cmd_list_ptr - (uint32_t)cmd_list_ptr_start),
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001080 BAM_DESC_NWD_FLAG | BAM_DESC_CMD_FLAG);
1081
1082 num_desc++;
1083 cmd_list_ptr_start = cmd_list_ptr;
Sridhar Parasuramf5188d82014-11-17 15:39:55 -08001084 cmd_list_read_ptr_start = cmd_list_read_ptr;
1085
1086 cmd_list_read_ptr = qpic_nand_add_read_ce(cmd_list_read_ptr_start, &status[i]);
1087 /* Enqueue the desc for the NAND_FLASH_STATUS read command */
1088 bam_add_one_desc(&bam,
1089 CMD_PIPE_INDEX,
1090 (unsigned char*)cmd_list_read_ptr_start,
1091 PA((uint32_t)cmd_list_read_ptr - (uint32_t)cmd_list_read_ptr_start),
1092 BAM_DESC_CMD_FLAG);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001093
1094 /* Set interrupt bit only for the last CW */
1095 if (i == flash.cws_per_page - 1)
Sridhar Parasuramf5188d82014-11-17 15:39:55 -08001096 cmd_list_ptr = qpic_nand_reset_status_ce(cmd_list_ptr, 1);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001097 else
Sridhar Parasuramf5188d82014-11-17 15:39:55 -08001098 cmd_list_ptr = qpic_nand_reset_status_ce(cmd_list_ptr, 0);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001099
Sridhar Parasuramf5188d82014-11-17 15:39:55 -08001100 /* Enqueue the desc for NAND_FLASH_STATUS and NAND_READ_STATUS write commands */
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001101 bam_add_one_desc(&bam,
1102 CMD_PIPE_INDEX,
1103 (unsigned char*)cmd_list_ptr_start,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001104 PA((uint32_t)cmd_list_ptr - (uint32_t)cmd_list_ptr_start),
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001105 int_flag | BAM_DESC_CMD_FLAG);
Sridhar Parasuramf5188d82014-11-17 15:39:55 -08001106 num_desc += 2;
Deepa Dinamani19530062012-10-03 14:43:05 -07001107
1108 qpic_nand_wait_for_cmd_exec(num_desc);
1109
1110 status[i] = qpic_nand_check_status(status[i]);
1111
1112 num_desc = 0;
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001113 }
Deepa Dinamani19530062012-10-03 14:43:05 -07001114 return;
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001115}
1116
1117void
1118qpic_add_wr_page_cws_data_desc(const void *buffer,
1119 enum nand_cfg_value cfg_mode,
1120 const void *spareaddr)
1121{
1122 int len;
1123 int flags;
1124 uint32_t start;
1125 unsigned num_desc = 0;
1126
1127 for( unsigned i = 0; i < flash.cws_per_page; i++)
1128 {
1129 flags = 0;
1130
1131 /* Set the interrupt flag on the last CW write for the page. */
1132 if( i == flash.cws_per_page - 1)
1133 flags |= BAM_DESC_INT_FLAG;
1134
1135 if (cfg_mode != NAND_CFG_RAW)
1136 {
1137 start = (uint32_t)buffer + i * DATA_BYTES_IN_IMG_PER_CW;
1138
1139 if (i < (flash.cws_per_page - 1))
1140 {
1141 len = DATA_BYTES_IN_IMG_PER_CW;
1142 flags |= BAM_DESC_EOT_FLAG;
1143 }
1144 else
1145 {
1146 /* Allow space for spare bytes in the last page */
1147 len = USER_DATA_BYTES_PER_CW - ((flash.cws_per_page - 1) << 2);
1148 flags = 0;
1149 }
1150 }
1151 else
1152 {
1153 start = (uint32_t)buffer;
1154 len = flash.cw_size;
1155 flags |= BAM_DESC_EOT_FLAG;
1156 }
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001157 bam_add_one_desc(&bam, DATA_CONSUMER_PIPE_INDEX, (unsigned char*)PA(start), len, flags);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001158 num_desc++;
1159
1160 if ((i == (flash.cws_per_page - 1)) && (cfg_mode == NAND_CFG))
1161 {
1162 /* write extra data */
1163 start = (uint32_t)spareaddr;
1164 len = (flash.cws_per_page << 2);
1165 flags = BAM_DESC_EOT_FLAG | BAM_DESC_INT_FLAG;
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001166 bam_add_one_desc(&bam, DATA_CONSUMER_PIPE_INDEX, (unsigned char*)PA(start), len, flags);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001167 num_desc++;
1168 }
1169 }
1170
1171 bam_sys_gen_event(&bam, DATA_CONSUMER_PIPE_INDEX, num_desc);
1172}
1173
1174static nand_result_t
1175qpic_nand_write_page(uint32_t pg_addr,
1176 enum nand_cfg_value cfg_mode,
1177 const void* buffer,
1178 const void* spareaddr)
1179{
1180 struct cfg_params cfg;
Deepa Dinamani16663a62013-02-07 16:25:59 -08001181 uint32_t status[QPIC_NAND_MAX_CWS_IN_PAGE];
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001182 int nand_ret = NANDC_RESULT_SUCCESS;
1183
1184 if (cfg_mode == NAND_CFG_RAW)
1185 {
1186 cfg.cfg0 = cfg0_raw;
1187 cfg.cfg1 = cfg1_raw;
1188 }
1189 else
1190 {
1191 cfg.cfg0 = cfg0;
1192 cfg.cfg1 = cfg1;
1193 }
1194
1195 cfg.cmd = NAND_CMD_PRG_PAGE;
1196 cfg.exec = 1;
1197
1198 cfg.addr0 = pg_addr << 16;
1199 cfg.addr1 = (pg_addr >> 16) & 0xff;
1200
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001201 qpic_add_wr_page_cws_data_desc(buffer, cfg_mode, spareaddr);
1202
Deepa Dinamani19530062012-10-03 14:43:05 -07001203 qpic_nand_add_wr_page_cws_cmd_desc(&cfg, status, cfg_mode);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001204
1205 /* Check for errors */
1206 for(unsigned i = 0; i < flash.cws_per_page; i++)
1207 {
1208 nand_ret = qpic_nand_check_status(status[i]);
1209 if (nand_ret)
1210 {
1211 dprintf(CRITICAL,
1212 "Failed to write CW %d for page: %d\n",
1213 i, pg_addr);
1214 break;
1215 }
1216 }
1217
1218 /* Wait for data to be available */
1219 qpic_nand_wait_for_data(DATA_CONSUMER_PIPE_INDEX);
1220
1221 return nand_ret;
1222}
1223
1224static int
1225qpic_nand_mark_badblock(uint32_t page)
1226{
1227 char empty_buf[NAND_CW_SIZE_8_BIT_ECC];
1228
1229 memset(empty_buf, 0, NAND_CW_SIZE_8_BIT_ECC);
1230
1231 /* Going to first page of the block */
1232 if (page & flash.num_pages_per_blk_mask)
1233 page = page - (page & flash.num_pages_per_blk_mask);
1234
1235 return qpic_nand_write_page(page, NAND_CFG_RAW, empty_buf, 0);
1236}
1237
1238static void
1239qpic_nand_non_onfi_probe(struct flash_info *flash)
1240{
1241 int dev_found = 0;
1242 unsigned index;
1243 uint32_t ecc_bits;
1244
1245 /* Read the nand id. */
1246 qpic_nand_fetch_id(flash);
1247
1248 /* Check if we support the device */
Deepa Dinamani649a94a2013-03-07 14:37:31 -08001249 for (index = 0; index < (ARRAY_SIZE(supported_flash)); index++)
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001250 {
Sridhar Parasuramfb0d9c82015-02-02 15:23:13 -08001251 if (((flash->id & supported_flash[index].mask) ==
1252 (supported_flash[index].flash_id & (supported_flash[index].mask))) &&
1253 ((flash->id2 & supported_flash[index].mask2) ==
1254 (supported_flash[index].flash_id2 & (supported_flash[index].mask2))))
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001255 {
1256 dev_found = 1;
1257 break;
1258 }
1259 }
1260
1261 if (dev_found)
1262 {
1263 flash->page_size = supported_flash[index].pagesize;
1264 flash->block_size = supported_flash[index].blksize;
1265 flash->spare_size = supported_flash[index].oobsize;
1266 ecc_bits = supported_flash[index].ecc_8_bits;
1267
1268 /* Make sure that the block size and page size are defined. */
1269 ASSERT(flash->block_size);
1270 ASSERT(flash->page_size);
1271
1272 flash->num_blocks = supported_flash[index].density;
1273 flash->num_blocks /= (flash->block_size);
1274 flash->num_pages_per_blk = flash->block_size / flash->page_size;
1275 flash->num_pages_per_blk_mask = flash->num_pages_per_blk - 1;
1276
1277 /* Look for 8bit BCH ECC Nand, TODO: ECC Correctability >= 8 */
1278 if (ecc_bits)
1279 flash->ecc_width = NAND_WITH_8_BIT_ECC;
1280 else
1281 flash->ecc_width = NAND_WITH_4_BIT_ECC;
1282
1283 flash->density = supported_flash[index].density;
1284 flash->widebus = supported_flash[index].widebus;
1285
1286 return;
1287 }
1288
1289 /* Flash device is not supported, print flash device info and halt */
1290 if (dev_found == 0)
1291 {
1292 dprintf(CRITICAL, "NAND device is not supported: nandid: 0x%x"
1293 "maker=0x%02x device=0x%02x\n",
1294 flash->id,
1295 flash->vendor,
1296 flash->device);
1297 ASSERT(0);
1298 }
1299
1300 dprintf(INFO, "nandid: 0x%x maker=0x%02x device=0x%02x page_size=%d\n",
1301 flash->id,
1302 flash->vendor,
1303 flash->device,
1304 flash->page_size);
1305
1306 dprintf(INFO, "spare_size=%d block_size=%d num_blocks=%d\n",
1307 flash->spare_size,
1308 flash->block_size,
1309 flash->num_blocks);
1310}
1311
1312void
1313qpic_nand_init(struct qpic_nand_init_config *config)
1314{
1315 uint32_t i;
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001316
1317 nand_base = config->nand_base;
1318
Deepa Dinamanie9ded132012-11-27 15:03:38 -08001319 qpic_bam_init(config);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001320
Deepa Dinamani649a94a2013-03-07 14:37:31 -08001321 qpic_nand_non_onfi_probe(&flash);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001322
1323 /* Save the RAW and read/write configs */
1324 qpic_nand_save_config(&flash);
1325
1326 flash_spare_bytes = (unsigned char *)malloc(flash.spare_size);
1327
1328 if (flash_spare_bytes == NULL)
1329 {
1330 dprintf(CRITICAL, "Failed to allocate memory for spare bytes\n");
1331 return;
1332 }
1333
1334 /* Create a bad block table */
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001335 bbtbl = (uint8_t *) malloc(sizeof(uint8_t) * flash.num_blocks);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001336
1337 if (bbtbl == NULL)
1338 {
1339 dprintf(CRITICAL, "Failed to allocate memory for bad block table\n");
1340 return;
1341 }
1342
1343 for (i = 0; i < flash.num_blocks; i++)
1344 bbtbl[i] = NAND_BAD_BLK_VALUE_NOT_READ;
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001345
1346 /* Set aside contiguous memory for reads/writes.
1347 * This is needed as the BAM transfers only work with
1348 * physically contiguous buffers.
1349 * We will copy any data to be written/ to be read from
1350 * nand to this buffer and this buffer will be submitted to BAM.
1351 */
1352 rdwr_buf = (uint8_t*) malloc(flash.page_size + flash.spare_size);
1353
1354 if (rdwr_buf == NULL)
1355 {
1356 dprintf(CRITICAL, "Failed to allocate memory for page reads or writes\n");
1357 return;
1358 }
1359
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001360}
1361
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -07001362unsigned
1363flash_page_size(void)
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001364{
1365 return flash.page_size;
1366}
1367
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -07001368unsigned
1369flash_block_size(void)
1370{
1371 return flash.block_size;
1372}
1373
Deepa Dinamani8e6b2432012-10-17 17:12:44 -07001374unsigned
1375flash_num_blocks(void)
1376{
1377 return flash.num_blocks;
1378}
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -07001379
Tanya Brokhman72b44dc2015-01-07 10:20:05 +02001380unsigned
1381flash_spare_size(void)
1382{
1383 return flash.spare_size;
1384}
1385
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -07001386struct ptable *
1387flash_get_ptable(void)
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001388{
1389 return flash_ptable;
1390}
1391
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -07001392void
Deepa Dinamani87feab82012-10-04 14:28:05 -07001393qpic_nand_uninit()
1394{
1395 bam_pipe_reset(&bam, DATA_PRODUCER_PIPE_INDEX);
1396 bam_pipe_reset(&bam, DATA_CONSUMER_PIPE_INDEX);
1397 bam_pipe_reset(&bam, CMD_PIPE_INDEX);
1398
1399}
1400void
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -07001401flash_set_ptable(struct ptable *new_ptable)
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001402{
1403 ASSERT(flash_ptable == NULL && new_ptable != NULL);
1404 flash_ptable = new_ptable;
1405}
1406
Channagoud Kadabib1dc47c2015-05-21 17:02:44 -07001407static int find_num_zeros_per_cw(uint8_t *ecc_buf, uint32_t ecc_bytes)
1408{
1409 uint8_t val;
1410 uint32_t i;
1411 int num_zeros = 0;
1412
1413 for (i = 0; i < ecc_bytes; i++)
1414 {
1415 val = ecc_buf[i];
1416 while (val)
1417 {
1418 if ((val & 1) == 0)
1419 num_zeros++;
1420 if (num_zeros > THRESHOLD_BIT_FLIPS)
1421 goto out;
1422 val >>= 1;
1423 }
1424 }
1425
1426out:
1427 return num_zeros;
1428}
1429
1430static int qpic_nand_read_erased_page(uint32_t page)
1431{
1432 struct cfg_params params;
1433 uint32_t ecc;
1434 uint32_t flash_sts[QPIC_NAND_MAX_CWS_IN_PAGE];
1435 uint32_t buffer_sts[QPIC_NAND_MAX_CWS_IN_PAGE];
1436 uint32_t addr_loc_0;
1437 uint32_t total_ecc_bytes = 0;
1438 struct cmd_element *cmd_list_ptr = ce_array;
1439 struct cmd_element *cmd_list_ptr_start = ce_array;
1440 uint32_t num_cmd_desc = 0;
1441 uint32_t num_data_desc = 0;
1442 uint32_t i;
1443 int nand_ret = NANDC_RESULT_SUCCESS;
1444 uint8_t flags = 0;
1445 uint32_t *cmd_list_temp = NULL;
1446 uint8_t *ecc_buf = NULL;
1447 uint8_t *ecc_temp = NULL;
1448 int num_zeros = 0;
1449#if DEBUG_QPIC_NAND
1450 uint32_t *buffer_temp = NULL;
1451#endif
1452
1453 total_ecc_bytes = (ecc_parity_bytes * flash.cws_per_page);
1454 ecc_buf = memalign(16, total_ecc_bytes);
1455 ASSERT(ecc_buf);
1456
1457 memset(ecc_buf, 0, total_ecc_bytes);
1458
1459 ecc_temp = ecc_buf;
1460#if DEBUG_QPIC_NAND
1461 buffer_temp = (uint32_t*)ecc_buf;
1462#endif
1463 params.addr0 = page << 16;
1464 params.addr1 = (page >> 16) & 0xff;
1465 params.cfg0 = cfg0_raw;
1466 params.cfg1 = cfg1_raw;
1467 params.cmd = NAND_CMD_PAGE_READ;
1468 params.exec = 1;
1469 ecc = ecc_cfg_raw;
1470
1471 /* Read all the Data bytes in the first 3 CWs. */
1472 addr_loc_0 = NAND_RD_LOC_OFFSET(517);
1473 addr_loc_0 |= NAND_RD_LOC_SIZE(ecc_parity_bytes);
1474 addr_loc_0 |= NAND_RD_LOC_LAST_BIT(1);
1475
1476 /* Queue up the command and data descriptors for all the codewords in a page
1477 * and do a single bam transfer at the end.*/
1478 for (i = 0; i < flash.cws_per_page; i++)
1479 {
1480 num_cmd_desc = 0;
1481 num_data_desc = 0;
1482 flags = 0;
1483
1484 if (i == 0)
1485 {
1486 /* Set the lock flag for the first CW */
1487 flags = BAM_DESC_LOCK_FLAG;
1488
1489 cmd_list_ptr = qpic_nand_add_addr_n_cfg_ce(&params, cmd_list_ptr);
1490
1491 bam_add_cmd_element(cmd_list_ptr, NAND_DEV0_ECC_CFG,(uint32_t)ecc, CE_WRITE_TYPE);
1492 cmd_list_ptr++;
1493
1494 bam_add_cmd_element(cmd_list_ptr, NAND_FLASH_CMD, (uint32_t)params.cmd, CE_WRITE_TYPE);
1495 cmd_list_ptr++;
1496
1497 /* Write addr loc 0. */
1498 bam_add_cmd_element(cmd_list_ptr,
1499 NAND_READ_LOCATION_n(0),
1500 (uint32_t)addr_loc_0,
1501 CE_WRITE_TYPE);
1502
1503 cmd_list_ptr++;
1504 }
1505 else
1506 cmd_list_ptr_start = cmd_list_ptr;
1507
1508 if (i == flash.cws_per_page - 1)
1509 flags = BAM_DESC_INT_FLAG;
1510
1511 /* Add Data desc */
1512 bam_add_one_desc(&bam,
1513 DATA_PRODUCER_PIPE_INDEX,
1514 (unsigned char *)PA((addr_t)ecc_temp),
1515 ecc_parity_bytes,
1516 flags);
1517 num_data_desc++;
1518 bam_sys_gen_event(&bam, DATA_PRODUCER_PIPE_INDEX, num_data_desc);
1519
1520 bam_add_cmd_element(cmd_list_ptr,
1521 NAND_EXEC_CMD,
1522 (uint32_t)params.exec,
1523 CE_WRITE_TYPE);
1524 cmd_list_ptr++;
1525
1526 /* Enqueue the desc for the above commands */
1527 bam_add_one_desc(&bam,
1528 CMD_PIPE_INDEX,
1529 (unsigned char*)cmd_list_ptr_start,
1530 PA((uint32_t)cmd_list_ptr - (uint32_t)cmd_list_ptr_start),
1531 BAM_DESC_NWD_FLAG | BAM_DESC_CMD_FLAG | flags);
1532 num_cmd_desc++;
1533
1534 bam_add_cmd_element(cmd_list_ptr, NAND_FLASH_STATUS, (uint32_t)PA((addr_t)&(flash_sts[i])), CE_READ_TYPE);
1535
1536 cmd_list_temp = (uint32_t *)cmd_list_ptr;
1537
1538 cmd_list_ptr++;
1539
1540 bam_add_cmd_element(cmd_list_ptr, NAND_BUFFER_STATUS, (uint32_t)PA((addr_t)&(buffer_sts[i])), CE_READ_TYPE);
1541 cmd_list_ptr++;
1542
1543 if (i == flash.cws_per_page - 1)
1544 {
1545 /* Unlock flag for the last CW */
1546 flags = BAM_DESC_CMD_FLAG | BAM_DESC_UNLOCK_FLAG;
1547 }
1548 else
1549 flags = BAM_DESC_CMD_FLAG;
1550
1551 /* Enqueue the desc for the above command */
1552 bam_add_one_desc(&bam,
1553 CMD_PIPE_INDEX,
1554 (unsigned char*)PA((addr_t)cmd_list_temp),
1555 PA((uint32_t)cmd_list_ptr - (uint32_t)cmd_list_temp),
1556 flags);
1557 num_cmd_desc++;
1558
1559 ecc_temp += ecc_parity_bytes;
1560
1561 /* Notify BAM HW about the newly added descriptors */
1562 bam_sys_gen_event(&bam, CMD_PIPE_INDEX, num_cmd_desc);
1563 }
1564
1565 qpic_nand_wait_for_data(DATA_PRODUCER_PIPE_INDEX);
1566
1567 /* Find number of bit flips in the ecc & if there are more than "threshold" bit flips then
1568 * the page is bad otherwise the page is erased page
1569 */
1570 ecc_temp = ecc_buf;
1571
1572 for (i = 0; i < flash.cws_per_page; i++)
1573 {
1574 num_zeros = find_num_zeros_per_cw(ecc_temp, ecc_parity_bytes);
1575
1576 if (num_zeros > THRESHOLD_BIT_FLIPS)
1577 {
1578 nand_ret = NANDC_RESULT_BAD_PAGE;
1579 goto qpic_nand_read_page_error;
1580 }
1581
1582 ecc_temp += ecc_parity_bytes;
1583 }
1584
1585qpic_nand_read_page_error:
1586
1587#if DEBUG_QPIC_NAND
1588 for(i = 0; i < 24; i += 8)
1589 {
1590 printf("ECC: %08x %08x %08x %08x %08x %08x %08x %08x\n",
1591 buffer_temp[i], buffer_temp[i+1], buffer_temp[i+2], buffer_temp[i+3],
1592 buffer_temp[i+4], buffer_temp[i+5], buffer_temp[i+6], buffer_temp[i+7]);
1593 }
1594 printf("ECC: %08x %08x\n", buffer_temp[24], buffer_temp[25]);
1595#endif
1596
1597 free(ecc_buf);
1598 return nand_ret;
1599}
1600
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001601/* Note: No support for raw reads. */
1602static int
1603qpic_nand_read_page(uint32_t page, unsigned char* buffer, unsigned char* spareaddr)
1604{
1605 struct cfg_params params;
1606 uint32_t ecc;
Channagoud Kadabib1dc47c2015-05-21 17:02:44 -07001607 uint32_t flash_sts[QPIC_NAND_MAX_CWS_IN_PAGE] = {0};
1608 uint32_t buffer_sts[QPIC_NAND_MAX_CWS_IN_PAGE] = {0};
1609 uint32_t erased_cw_sts[QPIC_NAND_MAX_CWS_IN_PAGE] = {0};
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001610 uint32_t addr_loc_0;
1611 uint32_t addr_loc_1;
1612 struct cmd_element *cmd_list_ptr = ce_array;
1613 struct cmd_element *cmd_list_ptr_start = ce_array;
1614 uint32_t num_cmd_desc = 0;
1615 uint32_t num_data_desc = 0;
1616 uint32_t status;
1617 uint32_t i;
1618 int nand_ret = NANDC_RESULT_SUCCESS;
Sundarajan Srinivasan024bda52014-02-27 16:48:48 -08001619 uint8_t flags = 0;
1620 uint32_t *cmd_list_temp = NULL;
Channagoud Kadabib1dc47c2015-05-21 17:02:44 -07001621#if DEBUG_QPIC_NAND
1622 uint8_t *buffer_temp = buffer;
1623#endif
Sundarajan Srinivasan024bda52014-02-27 16:48:48 -08001624
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001625 /* UD bytes in last CW is 512 - cws_per_page *4.
1626 * Since each of the CW read earlier reads 4 spare bytes.
1627 */
1628 uint16_t ud_bytes_in_last_cw = USER_DATA_BYTES_PER_CW - ((flash.cws_per_page - 1) << 2);
1629 uint16_t oob_bytes = DATA_BYTES_IN_IMG_PER_CW - ud_bytes_in_last_cw;
1630
1631 params.addr0 = page << 16;
1632 params.addr1 = (page >> 16) & 0xff;
1633 params.cfg0 = cfg0;
1634 params.cfg1 = cfg1;
Channagoud Kadabib1dc47c2015-05-21 17:02:44 -07001635 params.cmd = NAND_CMD_PAGE_READ_ECC;
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001636 params.exec = 1;
1637 ecc = ecc_bch_cfg;
1638
1639 /* Read all the Data bytes in the first 3 CWs. */
1640 addr_loc_0 = NAND_RD_LOC_OFFSET(0);
1641 addr_loc_0 |= NAND_RD_LOC_SIZE(DATA_BYTES_IN_IMG_PER_CW);
1642 addr_loc_0 |= NAND_RD_LOC_LAST_BIT(1);
1643
1644
1645 addr_loc_1 = NAND_RD_LOC_OFFSET(ud_bytes_in_last_cw);
1646 addr_loc_1 |= NAND_RD_LOC_SIZE(oob_bytes);
1647 addr_loc_1 |= NAND_RD_LOC_LAST_BIT(1);
1648
Deepa Dinamanidc1381e2012-11-15 14:53:24 -08001649 status = qpic_nand_block_isbad(page);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001650
1651 if (status)
1652 return status;
1653
sundarajan srinivasan7ced6482013-03-21 16:01:18 -07001654 /* Reset and Configure erased CW/page detection controller */
1655 qpic_nand_erased_status_reset(ce_array, BAM_DESC_LOCK_FLAG);
1656
Sundarajan Srinivasan024bda52014-02-27 16:48:48 -08001657 /* Queue up the command and data descriptors for all the codewords in a page
1658 * and do a single bam transfer at the end.*/
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001659 for (i = 0; i < flash.cws_per_page; i++)
1660 {
1661 num_cmd_desc = 0;
1662 num_data_desc = 0;
1663
1664 if (i == 0)
1665 {
1666 cmd_list_ptr = qpic_nand_add_addr_n_cfg_ce(&params, cmd_list_ptr);
1667
1668 bam_add_cmd_element(cmd_list_ptr, NAND_DEV0_ECC_CFG,(uint32_t)ecc, CE_WRITE_TYPE);
1669 cmd_list_ptr++;
1670 }
1671 else
1672 cmd_list_ptr_start = cmd_list_ptr;
1673
1674 bam_add_cmd_element(cmd_list_ptr, NAND_FLASH_CMD, (uint32_t)params.cmd, CE_WRITE_TYPE);
1675 cmd_list_ptr++;
1676
1677 if (i == flash.cws_per_page - 1)
1678 {
1679 addr_loc_0 = NAND_RD_LOC_OFFSET(0);
1680 addr_loc_0 |= NAND_RD_LOC_SIZE(ud_bytes_in_last_cw);
1681 addr_loc_0 |= NAND_RD_LOC_LAST_BIT(0);
1682
1683 /* Write addr loc 1 only for the last CW. */
1684 bam_add_cmd_element(cmd_list_ptr, NAND_READ_LOCATION_n(1), (uint32_t)addr_loc_1, CE_WRITE_TYPE);
1685 cmd_list_ptr++;
1686
1687 /* Add Data desc */
1688 bam_add_one_desc(&bam,
1689 DATA_PRODUCER_PIPE_INDEX,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001690 (unsigned char *)PA((addr_t)buffer),
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001691 ud_bytes_in_last_cw,
1692 0);
1693 num_data_desc++;
1694
1695 bam_add_one_desc(&bam,
1696 DATA_PRODUCER_PIPE_INDEX,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001697 (unsigned char *)PA((addr_t)spareaddr),
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001698 oob_bytes,
1699 BAM_DESC_INT_FLAG);
1700 num_data_desc++;
1701
1702 bam_sys_gen_event(&bam, DATA_PRODUCER_PIPE_INDEX, num_data_desc);
1703 }
1704 else
1705 {
1706 /* Add Data desc */
1707 bam_add_one_desc(&bam,
1708 DATA_PRODUCER_PIPE_INDEX,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001709 (unsigned char *)PA((addr_t)buffer),
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001710 DATA_BYTES_IN_IMG_PER_CW,
Sundarajan Srinivasan024bda52014-02-27 16:48:48 -08001711 0);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001712 num_data_desc++;
1713 bam_sys_gen_event(&bam, DATA_PRODUCER_PIPE_INDEX, num_data_desc);
1714 }
1715
1716 /* Write addr loc 0. */
1717 bam_add_cmd_element(cmd_list_ptr,
1718 NAND_READ_LOCATION_n(0),
1719 (uint32_t)addr_loc_0,
1720 CE_WRITE_TYPE);
1721
1722 cmd_list_ptr++;
1723 bam_add_cmd_element(cmd_list_ptr,
1724 NAND_EXEC_CMD,
1725 (uint32_t)params.exec,
1726 CE_WRITE_TYPE);
1727 cmd_list_ptr++;
1728
Sundarajan Srinivasan024bda52014-02-27 16:48:48 -08001729 /* Enqueue the desc for the above commands */
1730 bam_add_one_desc(&bam,
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001731 CMD_PIPE_INDEX,
1732 (unsigned char*)cmd_list_ptr_start,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001733 PA((uint32_t)cmd_list_ptr - (uint32_t)cmd_list_ptr_start),
Sundarajan Srinivasan024bda52014-02-27 16:48:48 -08001734 BAM_DESC_NWD_FLAG | BAM_DESC_CMD_FLAG);
1735 num_cmd_desc++;
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001736
Sundarajan Srinivasan024bda52014-02-27 16:48:48 -08001737 bam_add_cmd_element(cmd_list_ptr, NAND_FLASH_STATUS, (uint32_t)PA((addr_t)&(flash_sts[i])), CE_READ_TYPE);
1738
vijay kumar4f4405f2014-08-08 11:49:53 +05301739 cmd_list_temp = (uint32_t *)cmd_list_ptr;
Sundarajan Srinivasan024bda52014-02-27 16:48:48 -08001740
1741 cmd_list_ptr++;
1742
1743 bam_add_cmd_element(cmd_list_ptr, NAND_BUFFER_STATUS, (uint32_t)PA((addr_t)&(buffer_sts[i])), CE_READ_TYPE);
1744 cmd_list_ptr++;
1745
Channagoud Kadabib1dc47c2015-05-21 17:02:44 -07001746 /* Read erased CW status */
1747 bam_add_cmd_element(cmd_list_ptr, NAND_ERASED_CW_DETECT_STATUS, (uint32_t)PA((addr_t)&erased_cw_sts[i]), CE_READ_TYPE);
1748 cmd_list_ptr++;
1749
Sundarajan Srinivasan024bda52014-02-27 16:48:48 -08001750 if (i == flash.cws_per_page - 1)
1751 {
1752 flags = BAM_DESC_CMD_FLAG | BAM_DESC_UNLOCK_FLAG;
1753 }
1754 else
1755 flags = BAM_DESC_CMD_FLAG;
1756
1757 /* Enqueue the desc for the above command */
1758 bam_add_one_desc(&bam,
1759 CMD_PIPE_INDEX,
1760 (unsigned char*)PA((addr_t)cmd_list_temp),
1761 PA((uint32_t)cmd_list_ptr - (uint32_t)cmd_list_temp),
1762 flags);
1763 num_cmd_desc++;
1764
1765 buffer += DATA_BYTES_IN_IMG_PER_CW;
1766
1767 /* Notify BAM HW about the newly added descriptors */
1768 bam_sys_gen_event(&bam, CMD_PIPE_INDEX, num_cmd_desc);
1769 }
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001770
1771 qpic_nand_wait_for_data(DATA_PRODUCER_PIPE_INDEX);
1772
Channagoud Kadabib1dc47c2015-05-21 17:02:44 -07001773 /* Check flash read status & errors */
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001774 for (i = 0; i < flash.cws_per_page ; i ++)
Sundarajan Srinivasan024bda52014-02-27 16:48:48 -08001775 {
Channagoud Kadabib1dc47c2015-05-21 17:02:44 -07001776#if DEBUG_QPIC_NAND
1777 dprintf(INFO, "FLASH STATUS: 0x%08x, BUFFER STATUS: 0x%08x, ERASED CW STATUS: 0x%08x\n",
1778 flash_sts[i], buffer_sts[i], erased_cw_sts[i]);
1779#endif
1780
1781 /* If MPU or flash op erros are set, look for erased cw status.
1782 * If erased CW status is not set then look for bit flips to confirm
1783 * if the page is and erased page or a bad page
1784 */
1785 if (flash_sts[i] & (NAND_FLASH_OP_ERR | NAND_FLASH_MPU_ERR))
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001786 {
Channagoud Kadabib1dc47c2015-05-21 17:02:44 -07001787 if ((erased_cw_sts[i] & NAND_ERASED_CW) != NAND_ERASED_CW)
1788 {
1789#if DEBUG_QPIC_NAND
1790 dprintf(CRITICAL, "Page: 0x%08x, addr0: 0x%08x, addr1: 0x%08x\n", page, params.addr0, params.addr1);
1791#endif
1792 /*
1793 * Depending on the process technology used there could be bit flips on
1794 * pages on the NAND card
1795 * When any page is erased the controller fills the page with all 1's.
1796 * When we try to read from an erased page and there are bit flips the
1797 * controller would not detect the page as erased page instead throws
1798 * an uncorrectable ecc error.
1799 * The NAND data sheet for that card would specify the number of bit flips
1800 * expected per code word. If the number of bit flips is less than expected
1801 * bit flips then we should ignore the uncorrectable ECC error and consider
1802 * the page as an erased page.
1803 */
1804#if DEBUG_QPIC_NAND
1805 for(i = 0; i < 4096; i += 8)
1806 {
1807 printf("DATA: %x %x %x %x %x %x %x %x",
1808 buffer_temp[i], buffer_temp[i+1], buffer_temp[i+2], buffer_temp[i+3],
1809 buffer_temp[i+4], buffer_temp[i+5], buffer_temp[i+6], buffer_temp[i+7]);
1810 i += 8;
1811 printf("DATA: %x %x %x %x %x %x %x %x\n",
1812 buffer_temp[i], buffer_temp[i+1], buffer_temp[i+2], buffer_temp[i+3],
1813 buffer_temp[i+4], buffer_temp[i+5], buffer_temp[i+6], buffer_temp[i+7]);
1814 }
1815#endif
1816 nand_ret = qpic_nand_read_erased_page(page);
1817 goto qpic_nand_read_page_error;
1818 }
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001819 }
Sundarajan Srinivasan024bda52014-02-27 16:48:48 -08001820 }
Channagoud Kadabib1dc47c2015-05-21 17:02:44 -07001821
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001822qpic_nand_read_page_error:
Channagoud Kadabib1dc47c2015-05-21 17:02:44 -07001823 return nand_ret;
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001824}
1825
Tanya Brokhman72b44dc2015-01-07 10:20:05 +02001826/**
1827 * qpic_nand_read() - read data
1828 * @start_page: number of page to begin reading from
1829 * @num_pages: number of pages to read
1830 * @buffer: buffer where to store the read data
1831 * @spareaddr: buffer where to store spare data.
1832 * If null, spare data wont be read
1833 *
1834 * This function reads @num_pages starting from @start_page and stores the
1835 * read data in buffer. Note that it's in the caller responsibility to make
1836 * sure the read pages are all from same partition.
1837 *
1838 * Returns nand_result_t
1839 */
1840nand_result_t qpic_nand_read(uint32_t start_page, uint32_t num_pages,
1841 unsigned char* buffer, unsigned char* spareaddr)
1842{
1843 unsigned i = 0, ret = 0;
1844
1845 if (!buffer) {
1846 dprintf(CRITICAL, "qpic_nand_read: buffer = null\n");
1847 return NANDC_RESULT_PARAM_INVALID;
1848 }
1849 while (i < num_pages) {
1850 ret = qpic_nand_read_page(start_page + i, buffer + flash.page_size * i,
1851 spareaddr);
1852 i++;
1853 if (ret == NANDC_RESULT_BAD_PAGE)
1854 qpic_nand_mark_badblock(start_page + i);
1855 if (ret) {
1856 dprintf(CRITICAL,
1857 "qpic_nand_read: reading page %d failed with %d err\n",
1858 start_page + i, ret);
1859 return ret;
1860 }
1861 }
1862 return NANDC_RESULT_SUCCESS;
1863}
1864
1865/**
1866 * qpic_nand_write() - read data
1867 * @start_page: number of page to begin writing to
1868 * @num_pages: number of pages to write
1869 * @buffer: buffer to be written
1870 * @write_extra_bytes: true if spare data (ox 0xff) to be written
1871 *
1872 * This function writes @num_pages starting from @start_page. Note that it's
1873 * in the caller responsibility to make sure the written pages are all from
1874 * same partition.
1875 *
1876 * Returns nand_result_t
1877 */
1878nand_result_t qpic_nand_write(uint32_t start_page, uint32_t num_pages,
1879 unsigned char* buffer, unsigned write_extra_bytes)
1880{
1881 int i = 0, ret = NANDC_RESULT_SUCCESS;
1882 uint32_t *spare = (unsigned *)flash_spare_bytes;
1883 uint32_t wsize;
1884 uint32_t spare_byte_count = 0;
1885
1886 if (!buffer) {
1887 dprintf(CRITICAL, "qpic_nand_write: buffer = null\n");
1888 return NANDC_RESULT_PARAM_INVALID;
1889 }
1890 spare_byte_count = ((flash.cw_size * flash.cws_per_page)- flash.page_size);
1891
1892 if (write_extra_bytes)
1893 wsize = flash.page_size + spare_byte_count;
1894 else
1895 wsize = flash.page_size;
1896
1897 memset(spare, 0xff, (spare_byte_count / flash.cws_per_page));
1898
1899 for (i = 0; i < (int)num_pages; i++) {
1900 memcpy(rdwr_buf, buffer, flash.page_size);
1901 if (write_extra_bytes) {
1902 memcpy(rdwr_buf + flash.page_size,
1903 buffer + flash.page_size, spare_byte_count);
1904 ret = qpic_nand_write_page(start_page + i,
1905 NAND_CFG, rdwr_buf, rdwr_buf + flash.page_size);
1906 } else {
1907 ret = qpic_nand_write_page(start_page + i,
1908 NAND_CFG, rdwr_buf, spare);
1909 }
1910 if (ret) {
1911 dprintf(CRITICAL,
1912 "flash_write: write failure @ page %d, block %d\n",
1913 start_page + i,
1914 (start_page + i) / flash.num_pages_per_blk);
1915 if (ret == NANDC_RESULT_BAD_PAGE)
1916 qpic_nand_mark_badblock(start_page + i);
1917 goto out;
1918 }
1919 buffer += wsize;
1920 }
1921out:
1922 return ret;
1923}
1924
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001925/* Function to read a flash partition.
1926 * ptn : Partition to read.
1927 * extra_per_page : Spare data to be read.
1928 * offset : Num of bytes offset into the partition.
1929 * data : Buffer to read the data into.
1930 * bytes : Num of bytes to be read.
1931 */
1932 /* TODO: call this func read_partition. */
1933int
1934flash_read_ext(struct ptentry *ptn,
1935 unsigned extra_per_page,
1936 unsigned offset,
1937 void *data,
1938 unsigned bytes)
1939{
1940 uint32_t page =
1941 (ptn->start * flash.num_pages_per_blk) + (offset / flash.page_size);
1942 uint32_t lastpage = (ptn->start + ptn->length) * flash.num_pages_per_blk;
1943 uint32_t count =
1944 (bytes + flash.page_size - 1 + extra_per_page) / (flash.page_size +
1945 extra_per_page);
1946 uint32_t *spare = (unsigned *)flash_spare_bytes;
1947 uint32_t errors = 0;
1948 unsigned char *image = data;
1949 int result = 0;
1950 uint32_t current_block =
1951 (page - (page & flash.num_pages_per_blk_mask)) / flash.num_pages_per_blk;
1952 uint32_t start_block = ptn->start;
1953 uint32_t start_block_count = 0;
1954 uint32_t isbad = 0;
Deepa Dinamani2f7006c2013-08-19 11:59:38 -07001955 uint32_t current_page;
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001956
1957 /* Verify first byte is at page boundary. */
1958 if (offset & (flash.page_size - 1))
1959 {
1960 dprintf(CRITICAL, "Read request start not at page boundary: %d\n",
1961 offset);
1962 return NANDC_RESULT_PARAM_INVALID;
1963 }
1964
Deepa Dinamani2f7006c2013-08-19 11:59:38 -07001965 current_page = start_block * flash.num_pages_per_blk;
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001966 /* Adjust page offset based on number of bad blocks from start to current page */
1967 if (start_block < current_block)
1968 {
1969 start_block_count = (current_block - start_block);
1970 while (start_block_count
1971 && (start_block < (ptn->start + ptn->length)))
1972 {
Deepa Dinamani2f7006c2013-08-19 11:59:38 -07001973 isbad = qpic_nand_block_isbad(current_page);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001974 if (isbad)
1975 page += flash.num_pages_per_blk;
1976 else
1977 start_block_count--;
1978 start_block++;
Deepa Dinamani2f7006c2013-08-19 11:59:38 -07001979 current_page += flash.num_pages_per_blk;
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001980 }
1981 }
1982
1983 while ((page < lastpage) && !start_block_count)
1984 {
1985 if (count == 0)
1986 {
Deepa Dinamani52aca8d2013-02-05 11:41:41 -08001987 dprintf(SPEW, "flash_read_image: success (%d errors)\n",
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001988 errors);
1989 return NANDC_RESULT_SUCCESS;
1990 }
1991
Sundarajan Srinivasan29d927c2014-02-10 14:11:24 -08001992#if CONTIGUOUS_MEMORY
1993 result = qpic_nand_read_page(page, image, (unsigned char *) spare);
1994#else
1995 result = qpic_nand_read_page(page, rdwr_buf, (unsigned char *) spare);
1996#endif
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001997 if (result == NANDC_RESULT_BAD_PAGE)
1998 {
1999 /* bad page, go to next page. */
2000 page++;
2001 errors++;
2002 continue;
2003 }
2004 else if (result == NANDC_RESULT_BAD_BLOCK)
2005 {
2006 /* bad block, go to next block same offset. */
2007 page += flash.num_pages_per_blk;
2008 errors++;
2009 continue;
2010 }
2011
Sundarajan Srinivasan29d927c2014-02-10 14:11:24 -08002012#ifndef CONTIGUOUS_MEMORY
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07002013 /* Copy the read page into correct location. */
2014 memcpy(image, rdwr_buf, flash.page_size);
Sundarajan Srinivasan29d927c2014-02-10 14:11:24 -08002015#endif
Deepa Dinamanie4573be2012-08-03 16:32:29 -07002016 page++;
2017 image += flash.page_size;
2018 /* Copy spare bytes to image */
Sundarajan Srinivasan29d927c2014-02-10 14:11:24 -08002019 if(extra_per_page)
2020 {
2021 memcpy(image, spare, extra_per_page);
2022 image += extra_per_page;
2023 }
2024
Deepa Dinamanie4573be2012-08-03 16:32:29 -07002025 count -= 1;
2026 }
2027
2028 /* could not find enough valid pages before we hit the end */
2029 dprintf(CRITICAL, "flash_read_image: failed (%d errors)\n", errors);
2030 return NANDC_RESULT_FAILURE;
2031}
2032
2033int
2034flash_erase(struct ptentry *ptn)
2035{
Tanya Brokhman646eedb2015-01-06 23:09:54 +02002036 int ret = 0, i;
Deepa Dinamani2467bbb2012-10-02 13:59:58 -07002037
Tanya Brokhman646eedb2015-01-06 23:09:54 +02002038 for (i = 0; i < (int)ptn->length; i++) {
2039 ret = qpic_nand_blk_erase((ptn->start + i) * flash.num_pages_per_blk);
2040 if (ret)
2041 dprintf(CRITICAL, "Erase operation failed @ page #%d\n",
2042 ptn->start + i);
2043 }
Deepa Dinamani2467bbb2012-10-02 13:59:58 -07002044 return ret;
Deepa Dinamanie4573be2012-08-03 16:32:29 -07002045}
Deepa Dinamani2467bbb2012-10-02 13:59:58 -07002046
Deepa Dinamanie4573be2012-08-03 16:32:29 -07002047int
2048flash_ecc_bch_enabled()
2049{
2050 return (flash.ecc_width == NAND_WITH_4_BIT_ECC)? 0 : 1;
2051}
2052
2053int
2054flash_write(struct ptentry *ptn,
Deepa Dinamanic13d5942013-04-30 15:48:53 -07002055 unsigned write_extra_bytes,
Deepa Dinamanie4573be2012-08-03 16:32:29 -07002056 const void *data,
2057 unsigned bytes)
2058{
2059 uint32_t page = ptn->start * flash.num_pages_per_blk;
2060 uint32_t lastpage = (ptn->start + ptn->length) * flash.num_pages_per_blk;
2061 uint32_t *spare = (unsigned *)flash_spare_bytes;
2062 const unsigned char *image = data;
Deepa Dinamanic13d5942013-04-30 15:48:53 -07002063 uint32_t wsize;
Sundarajan Srinivasan223d7002014-02-11 19:48:11 -08002064 uint32_t spare_byte_count = 0;
Deepa Dinamanie4573be2012-08-03 16:32:29 -07002065 int r;
2066
Sundarajan Srinivasan223d7002014-02-11 19:48:11 -08002067 spare_byte_count = ((flash.cw_size * flash.cws_per_page)- flash.page_size);
2068
Deepa Dinamanic13d5942013-04-30 15:48:53 -07002069 if(write_extra_bytes)
Sundarajan Srinivasan223d7002014-02-11 19:48:11 -08002070 wsize = flash.page_size + spare_byte_count;
Deepa Dinamanic13d5942013-04-30 15:48:53 -07002071 else
2072 wsize = flash.page_size;
2073
Sundarajan Srinivasan223d7002014-02-11 19:48:11 -08002074 memset(spare, 0xff, (spare_byte_count / flash.cws_per_page));
Deepa Dinamanie4573be2012-08-03 16:32:29 -07002075
2076 while (bytes > 0)
2077 {
2078 if (bytes < wsize)
2079 {
2080 dprintf(CRITICAL,
2081 "flash_write_image: image undersized (%d < %d)\n",
2082 bytes,
2083 wsize);
2084 return -1;
2085 }
2086
2087 if (page >= lastpage)
2088 {
2089 dprintf(CRITICAL, "flash_write_image: out of space\n");
2090 return -1;
2091 }
2092
2093 if ((page & flash.num_pages_per_blk_mask) == 0)
2094 {
Deepa Dinamani2467bbb2012-10-02 13:59:58 -07002095 if (qpic_nand_blk_erase(page))
Deepa Dinamanie4573be2012-08-03 16:32:29 -07002096 {
2097 dprintf(INFO,
2098 "flash_write_image: bad block @ %d\n",
2099 page / flash.num_pages_per_blk);
2100
2101 page += flash.num_pages_per_blk;
2102 continue;
2103 }
2104 }
2105
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07002106 memcpy(rdwr_buf, image, flash.page_size);
2107
Deepa Dinamanic13d5942013-04-30 15:48:53 -07002108 if (write_extra_bytes)
Deepa Dinamanie4573be2012-08-03 16:32:29 -07002109 {
Sundarajan Srinivasan223d7002014-02-11 19:48:11 -08002110 memcpy(rdwr_buf + flash.page_size, image + flash.page_size, spare_byte_count);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07002111 r = qpic_nand_write_page(page,
2112 NAND_CFG,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07002113 rdwr_buf,
2114 rdwr_buf + flash.page_size);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07002115 }
2116 else
2117 {
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07002118 r = qpic_nand_write_page(page, NAND_CFG, rdwr_buf, spare);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07002119 }
2120
2121 if (r)
2122 {
2123 dprintf(INFO,
2124 "flash_write_image: write failure @ page %d (src %d)\n",
2125 page,
2126 image - (const unsigned char *)data);
2127
2128 image -= (page & flash.num_pages_per_blk_mask) * wsize;
2129 bytes += (page & flash.num_pages_per_blk_mask) * wsize;
2130 page &= ~flash.num_pages_per_blk_mask;
2131 if (qpic_nand_blk_erase(page))
2132 {
2133 dprintf(INFO,
2134 "flash_write_image: erase failure @ page %d\n",
2135 page);
2136 }
2137
2138 qpic_nand_mark_badblock(page);
2139
2140 dprintf(INFO,
2141 "flash_write_image: restart write @ page %d (src %d)\n",
2142 page, image - (const unsigned char *)data);
2143
2144 page += flash.num_pages_per_blk;
2145 continue;
2146 }
2147 page++;
2148 image += wsize;
2149 bytes -= wsize;
2150 }
2151
2152 /* erase any remaining pages in the partition */
2153 page = (page + flash.num_pages_per_blk_mask) & (~flash.num_pages_per_blk_mask);
2154
2155 while (page < lastpage)
2156 {
2157 if (qpic_nand_blk_erase(page))
2158 {
2159 dprintf(INFO, "flash_write_image: bad block @ %d\n",
2160 page / flash.num_pages_per_blk);
2161 }
2162 page += flash.num_pages_per_blk;
2163 }
2164
2165 dprintf(INFO, "flash_write_image: success\n");
2166 return 0;
2167}
Smita Ghoshf5431c62014-09-18 14:11:14 -07002168
2169uint32_t nand_device_base()
2170{
2171 return nand_base;
2172}