blob: 7fe25f921411497227810bf64458780c2b952f4a [file] [log] [blame]
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001/*
2 * Copyright (c) 2008, Google Inc.
3 * All rights reserved.
Mayank Groverff7de6b2018-05-24 13:41:03 +05304 * Copyright (c) 2009-2016,2018 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;
Parth Dixit8e83bed2017-02-21 17:49:46 +053069static uint32_t val;
Deepa Dinamani0bf2f442012-10-19 11:41:06 -070070
Deepa Dinamanie4573be2012-08-03 16:32:29 -070071static struct flash_id supported_flash[] = {
Sridhar Parasuramfb0d9c82015-02-02 15:23:13 -080072 /* Flash ID Flash ID2 ID Mask ID Mask2 Density(MB) Wid Pgsz Blksz oobsz 8-bit ECCf */
73 {0x1590AC2C, 0x56, 0xFFFFFFFF, 0xFF, 0x20000000, 0, 2048, 0x00020000, 0x40, 0},
74 {0x1590AC2C, 0x57, 0xFFFFFFFF, 0xFF, 0x20000000, 0, 2048, 0x00020000, 0x40, 1},
vijay kumareb2b60a2015-11-16 12:36:38 +053075 {0x1590AA2C, 0x06, 0xFFFFFFFF, 0x0, 0x10000000, 0, 2048, 0x00020000, 0xE0, 0},
Sridhar Parasuramfb0d9c82015-02-02 15:23:13 -080076 {0x2690AC2C, 0x54, 0xFFFFFFFF, 0x0, 0x20000000, 0, 4096, 0x00040000, 0xE0, 1},
77 {0x1590ACAD, 0, 0xFFFFFFFF, 0x0, 0x20000000, 0, 2048, 0x00020000, 0x80, 0},
78 {0x9590DC2C, 0x56, 0xFFFFFFFF, 0x0, 0x10000000, 0, 2048, 0x00020000, 0x40, 0},
79 {0x1590aa98, 0x76, 0xFFFFFFFF, 0x0, 0x10000000, 0, 2048, 0x00020000, 0x80, 1},
vijay kumar94451f82015-07-23 12:41:24 +053080 {0x2690A32C, 0x64, 0xFFFFFFFF, 0x0, 0x20000000, 0, 4096, 0x00040000, 0xE0, 1},
vijay kumarc395fb52015-09-30 19:16:33 +053081 {0x2690AC98, 0x81676, 0xFFFFFFFF, 0x0, 0x20000000, 0, 4096, 0x00040000, 0xE0, 1},
Mayank Grover5338b502016-10-19 19:20:00 +053082 {0x1580a1c2, 0x02, 0xFFFFFFFF, 0xFF, 0x08000000, 0, 2048, 0x00020000, 0x40, 0},
Deepa Dinamanie4573be2012-08-03 16:32:29 -070083 /* Note: Width flag is 0 for 8 bit Flash and 1 for 16 bit flash */
Deepa Dinamanie4573be2012-08-03 16:32:29 -070084};
85
Tanya Brokhman72b44dc2015-01-07 10:20:05 +020086static int qpic_nand_mark_badblock(uint32_t page);
87
Deepa Dinamanie4573be2012-08-03 16:32:29 -070088static void
89qpic_nand_wait_for_cmd_exec(uint32_t num_desc)
90{
91 /* Create a read/write event to notify the periperal of the added desc. */
92 bam_sys_gen_event(&bam, CMD_PIPE_INDEX, num_desc);
93
94 /* Wait for the descriptors to be processed */
95 bam_wait_for_interrupt(&bam, CMD_PIPE_INDEX, P_PRCSD_DESC_EN_MASK);
96
97 /* Read offset update for the circular FIFO */
98 bam_read_offset_update(&bam, CMD_PIPE_INDEX);
99}
100
101static void
102qpic_nand_wait_for_data(uint32_t pipe_num)
103{
104 /* Wait for the descriptors to be processed */
105 bam_wait_for_interrupt(&bam, pipe_num, P_PRCSD_DESC_EN_MASK);
106
107 /* Read offset update for the circular FIFO */
108 bam_read_offset_update(&bam, pipe_num);
109}
110
111static uint32_t
112qpic_nand_read_reg(uint32_t reg_addr,
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800113 uint8_t flags)
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700114{
Parth Dixit8e83bed2017-02-21 17:49:46 +0530115 val = 0;
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800116 struct cmd_element *cmd_list_read_ptr = ce_read_array;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700117
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800118 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 -0700119
120 /* Enqueue the desc for the above command */
121 bam_add_one_desc(&bam,
122 CMD_PIPE_INDEX,
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800123 (unsigned char*)PA((addr_t)cmd_list_read_ptr),
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700124 BAM_CE_SIZE,
125 BAM_DESC_CMD_FLAG| BAM_DESC_INT_FLAG | flags);
126
Parth Dixit8e83bed2017-02-21 17:49:46 +0530127 arch_clean_invalidate_cache_range((addr_t)&val, sizeof(uint32_t));
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700128 qpic_nand_wait_for_cmd_exec(1);
Parth Dixit8e83bed2017-02-21 17:49:46 +0530129 arch_clean_invalidate_cache_range((addr_t)&val, sizeof(uint32_t));
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700130
131 return val;
132}
133
Deepa Dinamani19530062012-10-03 14:43:05 -0700134/* Assume the BAM is in a locked state. */
135void
sundarajan srinivasan7ced6482013-03-21 16:01:18 -0700136qpic_nand_erased_status_reset(struct cmd_element *cmd_list_ptr, uint8_t flags)
Deepa Dinamani19530062012-10-03 14:43:05 -0700137{
Parth Dixit8e83bed2017-02-21 17:49:46 +0530138 val = 0;
Deepa Dinamani19530062012-10-03 14:43:05 -0700139
140 /* Reset the Erased Codeword/Page detection controller. */
141 val = NAND_ERASED_CW_DETECT_CFG_RESET_CTRL;
142
143 bam_add_cmd_element(cmd_list_ptr, NAND_ERASED_CW_DETECT_CFG, val, CE_WRITE_TYPE);
144
145 /* Enqueue the desc for the above command */
146 bam_add_one_desc(&bam,
147 CMD_PIPE_INDEX,
Mayank Grover20fdd882016-10-25 16:53:30 +0530148 (unsigned char*)PA((addr_t)cmd_list_ptr),
Deepa Dinamani19530062012-10-03 14:43:05 -0700149 BAM_CE_SIZE,
sundarajan srinivasan7ced6482013-03-21 16:01:18 -0700150 BAM_DESC_CMD_FLAG | BAM_DESC_INT_FLAG | flags);
Deepa Dinamani19530062012-10-03 14:43:05 -0700151
152 qpic_nand_wait_for_cmd_exec(1);
153
154 /* Enable the Erased Codeword/Page detection
155 * controller to check the data as it arrives.
156 * Also disable ECC reporting for an erased CW.
157 */
158 val = NAND_ERASED_CW_DETECT_CFG_ACTIVATE_CTRL | NAND_ERASED_CW_DETECT_ERASED_CW_ECC_MASK;
159
160 bam_add_cmd_element(cmd_list_ptr, NAND_ERASED_CW_DETECT_CFG, val, CE_WRITE_TYPE);
161
162 /* Enqueue the desc for the above command */
163 bam_add_one_desc(&bam,
164 CMD_PIPE_INDEX,
Mayank Grover20fdd882016-10-25 16:53:30 +0530165 (unsigned char*)PA((addr_t)cmd_list_ptr),
Deepa Dinamani19530062012-10-03 14:43:05 -0700166 BAM_CE_SIZE,
167 BAM_DESC_CMD_FLAG | BAM_DESC_INT_FLAG);
168
169 qpic_nand_wait_for_cmd_exec(1);
170}
171
172static nand_result_t
173qpic_nand_check_status(uint32_t status)
174{
175 uint32_t erase_sts;
176
177 /* Check for errors */
178 if (status & NAND_FLASH_ERR)
179 {
180 /* Check if this is an ECC error on an erased page. */
181 if (status & NAND_FLASH_OP_ERR)
182 {
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800183 erase_sts = qpic_nand_read_reg(NAND_ERASED_CW_DETECT_STATUS, 0);
Deepa Dinamani19530062012-10-03 14:43:05 -0700184 if ((erase_sts & (1 << NAND_ERASED_CW_DETECT_STATUS_PAGE_ALL_ERASED)))
185 {
186 /* Mask the OP ERROR. */
187 status &= ~NAND_FLASH_OP_ERR;
sundarajan srinivasan7ced6482013-03-21 16:01:18 -0700188 qpic_nand_erased_status_reset(ce_array, 0);
Deepa Dinamani19530062012-10-03 14:43:05 -0700189 }
190 }
191
192 /* ECC error flagged on an erased page read.
193 * Ignore and return success.
194 */
195 if (!(status & NAND_FLASH_ERR))
196 return NANDC_RESULT_SUCCESS;
197
198 dprintf(CRITICAL, "Nand Flash error. Status = %d\n", status);
199
200 if (status & NAND_FLASH_TIMEOUT_ERR)
201 return NANDC_RESULT_TIMEOUT;
202 else
203 return NANDC_RESULT_FAILURE;
204 }
205
206 return NANDC_RESULT_SUCCESS;
207}
208
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700209static uint32_t
210qpic_nand_fetch_id(struct flash_info *flash)
211{
212 struct cmd_element *cmd_list_ptr = ce_array;
213 struct cmd_element *cmd_list_ptr_start = ce_array;
214 int num_desc = 0;
215 uint32_t status;
Sridhar Parasuramfb0d9c82015-02-02 15:23:13 -0800216 uint32_t id, id2;
217 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 -0700218 uint32_t exec_cmd = 1;
219 int nand_ret = NANDC_RESULT_SUCCESS;
220
221 /* Issue the Fetch id command to the NANDc */
222 bam_add_cmd_element(cmd_list_ptr, NAND_FLASH_CMD, (uint32_t)flash_cmd, CE_WRITE_TYPE);
223 cmd_list_ptr++;
224
225 /* Execute the cmd */
226 bam_add_cmd_element(cmd_list_ptr, NAND_EXEC_CMD, (uint32_t)exec_cmd, CE_WRITE_TYPE);
227 cmd_list_ptr++;
228
229 /* Prepare the cmd desc for the above commands */
230 bam_add_one_desc(&bam,
231 CMD_PIPE_INDEX,
Mayank Grover20fdd882016-10-25 16:53:30 +0530232 (unsigned char*)PA((addr_t)cmd_list_ptr_start),
Deepa Dinamani0bf2f442012-10-19 11:41:06 -0700233 PA((uint32_t)cmd_list_ptr - (uint32_t)cmd_list_ptr_start),
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700234 BAM_DESC_LOCK_FLAG | BAM_DESC_INT_FLAG |
235 BAM_DESC_NWD_FLAG | BAM_DESC_CMD_FLAG);
236
237 /* Keep track of the number of desc added. */
238 num_desc++;
239 qpic_nand_wait_for_cmd_exec(num_desc);
240
241 cmd_list_ptr_start = ce_array;
242 cmd_list_ptr = ce_array;
243
244 /* Read the status register */
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800245 status = qpic_nand_read_reg(NAND_FLASH_STATUS, 0);
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700246
247 /* Check for errors */
248 nand_ret = qpic_nand_check_status(status);
249 if (nand_ret)
250 {
251 dprintf( CRITICAL, "Read ID cmd status failed\n");
252 goto qpic_nand_fetch_id_err;
253 }
254
255 /* Read the id */
Sridhar Parasuramfb0d9c82015-02-02 15:23:13 -0800256 id = qpic_nand_read_reg(NAND_READ_ID, 0);
257 id2 = qpic_nand_read_reg(NAND_READ_ID2, BAM_DESC_UNLOCK_FLAG);
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700258
259 flash->id = id;
Sridhar Parasuramfb0d9c82015-02-02 15:23:13 -0800260 flash->id2 = id2;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700261 flash->vendor = id & 0xff;
262 flash->device = (id >> 8) & 0xff;
263 flash->dev_cfg = (id >> 24) & 0xFF;
264 flash->widebus = 0;
265 flash->widebus &= (id >> 24) & 0xFF;
266 flash->widebus = flash->widebus? 1: 0;
267
268qpic_nand_fetch_id_err:
269 return nand_ret;
270}
271
272static int
Deepa Dinamanie9ded132012-11-27 15:03:38 -0800273qpic_bam_init(struct qpic_nand_init_config *config)
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700274{
275 uint32_t bam_ret = NANDC_RESULT_SUCCESS;
276
Deepa Dinamanie9ded132012-11-27 15:03:38 -0800277 bam.base = config->bam_base;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700278 /* Set Read pipe params. */
Deepa Dinamanie9ded132012-11-27 15:03:38 -0800279 bam.pipe[DATA_PRODUCER_PIPE_INDEX].pipe_num = config->pipes.read_pipe;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700280 /* System consumer */
281 bam.pipe[DATA_PRODUCER_PIPE_INDEX].trans_type = BAM2SYS;
282 bam.pipe[DATA_PRODUCER_PIPE_INDEX].fifo.size = QPIC_BAM_DATA_FIFO_SIZE;
283 bam.pipe[DATA_PRODUCER_PIPE_INDEX].fifo.head = data_desc_fifo;
Deepa Dinamani536d3f82013-07-09 13:05:56 -0700284 bam.pipe[DATA_PRODUCER_PIPE_INDEX].lock_grp = config->pipes.read_pipe_grp;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700285
286 /* Set Write pipe params. */
Deepa Dinamanie9ded132012-11-27 15:03:38 -0800287 bam.pipe[DATA_CONSUMER_PIPE_INDEX].pipe_num = config->pipes.write_pipe;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700288 /* System producer */
289 bam.pipe[DATA_CONSUMER_PIPE_INDEX].trans_type = SYS2BAM;
290 bam.pipe[DATA_CONSUMER_PIPE_INDEX].fifo.size = QPIC_BAM_DATA_FIFO_SIZE;
291 bam.pipe[DATA_CONSUMER_PIPE_INDEX].fifo.head = data_desc_fifo;
Deepa Dinamani536d3f82013-07-09 13:05:56 -0700292 bam.pipe[DATA_CONSUMER_PIPE_INDEX].lock_grp = config->pipes.write_pipe_grp;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700293
294 /* Set Cmd pipe params. */
Deepa Dinamanie9ded132012-11-27 15:03:38 -0800295 bam.pipe[CMD_PIPE_INDEX].pipe_num = config->pipes.cmd_pipe;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700296 /* System consumer */
Sundarajan Srinivasan357c35a2013-07-23 17:00:54 -0700297 bam.pipe[CMD_PIPE_INDEX].trans_type = SYS2BAM;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700298 bam.pipe[CMD_PIPE_INDEX].fifo.size = QPIC_BAM_CMD_FIFO_SIZE;
299 bam.pipe[CMD_PIPE_INDEX].fifo.head = cmd_desc_fifo;
Deepa Dinamani536d3f82013-07-09 13:05:56 -0700300 bam.pipe[CMD_PIPE_INDEX].lock_grp = config->pipes.cmd_pipe_grp;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700301
302 /* Programs the threshold for BAM transfer
303 * When this threshold is reached, BAM signals the peripheral via the pipe_bytes_available
304 * interface.
305 * The peripheral is signalled with this notification in the following cases:
306 * a. It has accumulated all the descriptors.
307 * b. It has accumulated more than threshold bytes.
308 * c. It has reached EOT (End Of Transfer).
309 * Note: this value needs to be set by the h/w folks and is specific for each peripheral.
310 */
311 bam.threshold = 32;
312
Deepa Dinamanie9ded132012-11-27 15:03:38 -0800313 /* Set the EE. */
314 bam.ee = config->ee;
315
316 /* Set the max desc length for this BAM. */
317 bam.max_desc_len = config->max_desc_len;
318
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700319 /* BAM Init. */
320 bam_init(&bam);
321
322 /* Initialize BAM QPIC read pipe */
323 bam_sys_pipe_init(&bam, DATA_PRODUCER_PIPE_INDEX);
324
325 /* Init read fifo */
326 bam_ret = bam_pipe_fifo_init(&bam, bam.pipe[DATA_PRODUCER_PIPE_INDEX].pipe_num);
327
328 if (bam_ret)
329 {
330 dprintf(CRITICAL, "QPIC:NANDc BAM Read FIFO init error\n");
331 bam_ret = NANDC_RESULT_FAILURE;
332 goto qpic_nand_bam_init_error;
333 }
334
335 /* Initialize BAM QPIC write pipe */
336 bam_sys_pipe_init(&bam, DATA_CONSUMER_PIPE_INDEX);
337
338 /* Init write fifo. Use the same fifo as read fifo. */
339 bam_ret = bam_pipe_fifo_init(&bam, bam.pipe[DATA_CONSUMER_PIPE_INDEX].pipe_num);
340
341 if (bam_ret)
342 {
343 dprintf(CRITICAL, "QPIC: NANDc: BAM Write FIFO init error\n");
344 bam_ret = NANDC_RESULT_FAILURE;
345 goto qpic_nand_bam_init_error;
346 }
347
348 /* Initialize BAM QPIC cmd pipe */
349 bam_sys_pipe_init(&bam, CMD_PIPE_INDEX);
350
351 /* Init cmd fifo */
352 bam_ret = bam_pipe_fifo_init(&bam, bam.pipe[CMD_PIPE_INDEX].pipe_num);
353
354 if (bam_ret)
355 {
356 dprintf(CRITICAL, "QPIC:NANDc BAM CMD FIFO init error\n");
357 bam_ret = NANDC_RESULT_FAILURE;
358 goto qpic_nand_bam_init_error;
359 }
360
361qpic_nand_bam_init_error:
362return bam_ret;
363}
364
365/* Adds command elements for addr and cfg register writes.
366 * cfg: Defines the configuration for the flash cmd.
367 * start: Address where the command elements are added.
368 *
369 * Returns the address where the next cmd element can be added.
370 */
371static struct cmd_element*
372qpic_nand_add_addr_n_cfg_ce(struct cfg_params *cfg,
373 struct cmd_element *start)
374{
375 struct cmd_element *cmd_list_ptr = start;
376
377 bam_add_cmd_element(cmd_list_ptr, NAND_ADDR0, (uint32_t)cfg->addr0, CE_WRITE_TYPE);
378 cmd_list_ptr++;
379 bam_add_cmd_element(cmd_list_ptr, NAND_ADDR1, (uint32_t)cfg->addr1, CE_WRITE_TYPE);
380 cmd_list_ptr++;
381 bam_add_cmd_element(cmd_list_ptr, NAND_DEV0_CFG0, (uint32_t)cfg->cfg0, CE_WRITE_TYPE);
382 cmd_list_ptr++;
383 bam_add_cmd_element(cmd_list_ptr, NAND_DEV0_CFG1, (uint32_t)cfg->cfg1, CE_WRITE_TYPE);
384 cmd_list_ptr++;
385
386 return cmd_list_ptr;
387}
388
389
390static struct cmd_element*
391qpic_nand_add_onfi_probe_ce(struct onfi_probe_params *params,
392 struct cmd_element *start)
393{
394 struct cmd_element *cmd_list_ptr = start;
395
396 cmd_list_ptr = qpic_nand_add_addr_n_cfg_ce(&params->cfg, cmd_list_ptr);
397
398 bam_add_cmd_element(cmd_list_ptr, NAND_DEV_CMD1, (uint32_t)params->dev_cmd1, CE_WRITE_TYPE);
399 cmd_list_ptr++;
400 bam_add_cmd_element(cmd_list_ptr, NAND_DEV_CMD_VLD, (uint32_t)params->vld, CE_WRITE_TYPE);
401 cmd_list_ptr++;
402 bam_add_cmd_element(cmd_list_ptr, NAND_READ_LOCATION_n(0), (uint32_t)params->cfg.addr_loc_0, CE_WRITE_TYPE);
403 cmd_list_ptr++;
404 bam_add_cmd_element(cmd_list_ptr, NAND_FLASH_CMD, (uint32_t)params->cfg.cmd, CE_WRITE_TYPE);
405 cmd_list_ptr++;
406 bam_add_cmd_element(cmd_list_ptr, NAND_EXEC_CMD, (uint32_t)params->cfg.exec, CE_WRITE_TYPE);
407 cmd_list_ptr++;
408
409 return cmd_list_ptr;
410}
411
412static int
413onfi_probe_cmd_exec(struct onfi_probe_params *params,
414 unsigned char* data_ptr,
415 int data_len)
416{
417 struct cmd_element *cmd_list_ptr = ce_array;
418 struct cmd_element *cmd_list_ptr_start = ce_array;
419 int num_desc = 0;
420 uint32_t status = 0;
421 int nand_ret = NANDC_RESULT_SUCCESS;
422 uint8_t desc_flags = BAM_DESC_NWD_FLAG | BAM_DESC_CMD_FLAG
423 | BAM_DESC_LOCK_FLAG | BAM_DESC_INT_FLAG;
424
425 params->cfg.addr_loc_0 = 0;
426 params->cfg.addr_loc_0 |= NAND_RD_LOC_LAST_BIT(1);
427 params->cfg.addr_loc_0 |= NAND_RD_LOC_OFFSET(0);
428 params->cfg.addr_loc_0 |= NAND_RD_LOC_SIZE(data_len);
429
430 cmd_list_ptr = qpic_nand_add_onfi_probe_ce(params, cmd_list_ptr);
431
432 /* Enqueue the desc for the above commands */
433 bam_add_one_desc(&bam,
434 CMD_PIPE_INDEX,
Mayank Grover20fdd882016-10-25 16:53:30 +0530435 (unsigned char*)PA((addr_t)cmd_list_ptr_start),
Deepa Dinamani0bf2f442012-10-19 11:41:06 -0700436 PA((addr_t)(uint32_t)cmd_list_ptr - (uint32_t)cmd_list_ptr_start),
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700437 desc_flags);
438
439 cmd_list_ptr_start = cmd_list_ptr;
440 num_desc++;
441
442 /* Add Data desc */
443 bam_add_desc(&bam,
444 DATA_PRODUCER_PIPE_INDEX,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -0700445 (unsigned char *)PA((addr_t)data_ptr),
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700446 data_len,
447 BAM_DESC_INT_FLAG);
448
449 /* Wait for the commands to be executed */
450 qpic_nand_wait_for_cmd_exec(num_desc);
451
452 /* Read buffer status and check for errors. */
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800453 status = qpic_nand_read_reg(NAND_FLASH_STATUS, 0);
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700454
455 if (qpic_nand_check_status(status))
456 {
457 nand_ret = NANDC_RESULT_FAILURE;
458 goto onfi_probe_exec_err;
459 }
460
461 /* Wait for data to be available */
462 qpic_nand_wait_for_data(DATA_PRODUCER_PIPE_INDEX);
463
464 /* Check for errors */
465 nand_ret = qpic_nand_check_status(status);
466
467onfi_probe_exec_err:
468 return nand_ret;
469}
470
471/* TODO: check why both vld and cmd need to be written. */
472void
473qpic_nand_onfi_probe_cleanup(uint32_t vld, uint32_t dev_cmd1)
474{
475 struct cmd_element *cmd_list_ptr = ce_array;
476 struct cmd_element *cmd_list_ptr_start = ce_array;
477
478 bam_add_cmd_element(cmd_list_ptr, NAND_DEV_CMD1, dev_cmd1, CE_WRITE_TYPE);
479 cmd_list_ptr++;
480 bam_add_cmd_element(cmd_list_ptr, NAND_DEV_CMD_VLD, vld, CE_WRITE_TYPE);
481 cmd_list_ptr++;
482
483 /* Enqueue the desc for the above commands */
484 bam_add_one_desc(&bam,
485 CMD_PIPE_INDEX,
Mayank Grover20fdd882016-10-25 16:53:30 +0530486 (unsigned char*)PA((addr_t)cmd_list_ptr_start),
Deepa Dinamani0bf2f442012-10-19 11:41:06 -0700487 PA((uint32_t)cmd_list_ptr - (uint32_t)cmd_list_ptr_start),
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700488 BAM_DESC_UNLOCK_FLAG | BAM_DESC_CMD_FLAG| BAM_DESC_INT_FLAG);
489
490 qpic_nand_wait_for_cmd_exec(1);
491}
492
493static int
494qpic_nand_onfi_save_params(struct onfi_param_page *param_page, struct flash_info *flash)
495{
496 int onfi_ret = NANDC_RESULT_SUCCESS;
497 uint32_t ecc_bits;
498
499 onfi_ret = qpic_nand_fetch_id(flash);
500
501 if (onfi_ret)
502 {
503 dprintf(CRITICAL, "Fetch ID cmd failed\n");
504 goto onfi_save_params_err;
505 }
506
507 flash->page_size = param_page->data_per_pg;
508 flash->block_size = param_page->pgs_per_blk * flash->page_size;
509 flash->num_blocks = param_page->blks_per_LUN;
510 flash->widebus = param_page->feature_supported & 0x1;
511 flash->density = param_page->blks_per_LUN * flash->blksize;
512 flash->spare_size = param_page->spare_per_pg;
513 ecc_bits = param_page->num_bits_ecc_correctability;
514 flash->num_pages_per_blk = param_page->pgs_per_blk;
515 flash->num_pages_per_blk_mask = param_page->pgs_per_blk - 1;
516
517 if (ecc_bits >= 8)
518 flash->ecc_width = NAND_WITH_8_BIT_ECC;
519 else
520 flash->ecc_width = NAND_WITH_4_BIT_ECC;
521
522 onfi_save_params_err:
523 return onfi_ret;
524}
525
526static void
527qpic_nand_save_config(struct flash_info *flash)
528{
Channagoud Kadabib1dc47c2015-05-21 17:02:44 -0700529 uint32_t spare_bytes = 0;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700530
531 /* Save Configurations */
532 flash->cws_per_page = flash->page_size >> NAND_CW_DIV_RIGHT_SHIFT;
533
Deepa Dinamani16663a62013-02-07 16:25:59 -0800534 /* Verify that we have enough buffer to handle all the cws in a page. */
535 ASSERT(flash->cws_per_page <= QPIC_NAND_MAX_CWS_IN_PAGE);
536
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700537 /* Codeword Size = UD_SIZE_BYTES + ECC_PARITY_SIZE_BYTES
538 * + SPARE_SIZE_BYTES + Bad Block size
539 */
540 if (flash->ecc_width & NAND_WITH_8_BIT_ECC)
541 {
542 flash->cw_size = NAND_CW_SIZE_8_BIT_ECC;
543 ecc_bch_cfg |= (1 << NAND_DEV0_ECC_MODE_SHIFT); /* Use 8-bit ecc */
544
545 if (flash->widebus)
546 {
547 cfg0 |= (0 << NAND_DEV0_CFG0_SPARE_SZ_BYTES_SHIFT); /* spare size bytes in each CW */
548 ecc_bch_cfg |= (14 << NAND_DEV0_ECC_PARITY_SZ_BYTES_SHIFT); /* parity bytes in each CW */
549 }
550 else
551 {
552 cfg0 |= (2 << NAND_DEV0_CFG0_SPARE_SZ_BYTES_SHIFT); /* spare size bytes in each CW */
553 ecc_bch_cfg |= (13 << NAND_DEV0_ECC_PARITY_SZ_BYTES_SHIFT); /* parity bytes in each CW */
554 }
555 }
556 else
557 {
558 flash->cw_size = NAND_CW_SIZE_4_BIT_ECC;
559
560 if (flash->widebus)
561 {
562 cfg0 |= (2 << NAND_DEV0_CFG0_SPARE_SZ_BYTES_SHIFT); /* spare size bytes in each CW */
563 ecc_bch_cfg |= (8 << NAND_DEV0_ECC_PARITY_SZ_BYTES_SHIFT); /* parity bytes in each CW */
564 }
565 else
566 {
567 cfg0 |= (4 << NAND_DEV0_CFG0_SPARE_SZ_BYTES_SHIFT); /* spare size bytes in each CW */
568 ecc_bch_cfg |= (7 << NAND_DEV0_ECC_PARITY_SZ_BYTES_SHIFT); /* parity bytes in each CW */
569 }
570 }
571
572 /* BAD_BLOCK_BYTE_NUM = Page Size -
573 * (CW_PER_PAGE * Codeword Size) + 1
574 * Note: Set CW_PER_PAGE to 1 less than the actual number.
575 */
576 flash->bad_blk_loc = flash->page_size - flash->cw_size * (flash->cws_per_page - 1) + 1;
577
Channagoud Kadabib1dc47c2015-05-21 17:02:44 -0700578 /* Calculate the parity and spare bytes */
579 ecc_parity_bytes = (flash->ecc_width & NAND_WITH_8_BIT_ECC) ? (flash->widebus ? 14 : 13) : (flash->widebus ? 8 : 7) ;
580 spare_bytes = flash->cw_size - (USER_DATA_BYTES_PER_CW + ecc_parity_bytes);
581
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700582 cfg0 |= ((flash->cws_per_page - 1) << NAND_DEV0_CFG0_CW_PER_PAGE_SHIFT) /* 4/8 cw/pg for 2/4k */
583 |(DATA_BYTES_IN_IMG_PER_CW << NAND_DEV0_CFG0_UD_SIZE_BYTES_SHIFT) /* 516 user data bytes */
584 |(5 << NAND_DEV0_CFG0_ADDR_CYCLE_SHIFT) /* 5 address cycles */
585 |(0 << NAND_DEV0_CFG0_DIS_STS_AFTER_WR_SHIFT);/* Send read status cmd after each write. */
586
587 cfg1 |= (7 << NAND_DEV0_CFG1_RECOVERY_CYCLES_SHIFT) /* 8 recovery cycles */
588 |(0 << NAND_DEV0_CFG1_CS_ACTIVE_BSY_SHIFT) /* Allow CS deassertion */
589 |(flash->bad_blk_loc << NAND_DEV0_CFG1_BAD_BLK_BYTE_NUM_SHIFT)/* Bad block marker location */
590 |(0 << NAND_DEV0_CFG1_BAD_BLK_IN_SPARE_SHIFT) /* Bad block in user data area */
591 |(2 << NAND_DEV0_CFG1_WR_RD_BSY_GAP_SHIFT) /* 8 cycle tWB/tRB */
592 |(flash->widebus << NAND_DEV0_CFG1_WIDE_BUS_SHIFT); /* preserve wide flash flag */
593
Channagoud Kadabib1dc47c2015-05-21 17:02:44 -0700594 cfg0_raw = ((flash->cws_per_page - 1) << NAND_DEV0_CFG0_CW_PER_PAGE_SHIFT)
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700595 |(5 << NAND_DEV0_CFG0_ADDR_CYCLE_SHIFT)
Channagoud Kadabib1dc47c2015-05-21 17:02:44 -0700596 |(512 << NAND_DEV0_CFG0_UD_SIZE_BYTES_SHIFT)
597 | (spare_bytes << NAND_DEV0_CFG0_SPARE_SZ_BYTES_SHIFT);
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700598
Channagoud Kadabib1dc47c2015-05-21 17:02:44 -0700599 cfg1_raw = (2 << NAND_DEV0_CFG1_WR_RD_BSY_GAP_SHIFT)
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700600 | (1 << NAND_DEV0_CFG1_BAD_BLK_IN_SPARE_SHIFT)
Channagoud Kadabib1dc47c2015-05-21 17:02:44 -0700601 | (21 << NAND_DEV0_CFG1_BAD_BLK_BYTE_NUM_SHIFT)
602 | (0 << NAND_DEV0_CFG1_CS_ACTIVE_BSY_SHIFT)
603 | (7 << NAND_DEV0_CFG1_RECOVERY_CYCLES_SHIFT)
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700604 | (flash->widebus << NAND_DEV0_CFG1_WIDE_BUS_SHIFT)
605 |1 ; /* to disable reed solomon ecc..this feild is now read only. */
606
607 ecc_bch_cfg |= (0 << NAND_DEV0_ECC_DISABLE_SHIFT) /* Enable ECC */
608 | (0 << NAND_DEV0_ECC_SW_RESET_SHIFT) /* Put ECC core in op mode */
609 | (DATA_BYTES_IN_IMG_PER_CW << NAND_DEV0_ECC_NUM_DATA_BYTES)
610 | (1 << NAND_DEV0_ECC_FORCE_CLK_OPEN_SHIFT); /* Enable all clocks */
Channagoud Kadabib1dc47c2015-05-21 17:02:44 -0700611
612 ecc_cfg_raw = (1 << NAND_DEV0_ECC_FORCE_CLK_OPEN_SHIFT)
613 | (DATA_BYTES_IN_IMG_PER_CW << NAND_DEV0_ECC_NUM_DATA_BYTES)
614 | (ecc_parity_bytes << NAND_DEV0_ECC_PARITY_SZ_BYTES_SHIFT)
615 | (0 << NAND_DEV0_ECC_SW_RESET_SHIFT)
616 | (1 << NAND_DEV0_ECC_DISABLE_SHIFT);
617
618#if DEBUG_QPIC_NAND
619 dprintf(INFO, "CFG0: 0x%08x CFG1: 0x%08x\n", cfg0, cfg1);
620 dprintf(INFO, "CFG0_RAW: 0x%08x CFG1_RAW: 0x%08x\n", cfg0_raw, cfg1_raw);
621 dprintf(INFO, "ECC_BCH_CFG: 0x%08x ECC_CFG_RAW: 0x%08x\n", ecc_bch_cfg, ecc_cfg_raw);
622#endif
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700623}
624
625/* Onfi probe should issue the following commands to the flash device:
626 * 1. Read ID - with addr ONFI_READ_ID_ADDR.
627 * This returns the ONFI ASCII string indicating support for ONFI.
628 * 2. Read Prameter Page - with addr ONFI_READ_PARAM_PAGE_ADDR.
629 * This returns the params for the device.
630 * Each command inturn issues commands- ADDR0, ADDR1, chip_select,
631 * cfg0, cfg1, cmd_vld, dev_cmd1, read_loc0, flash, exec.
632 */
633static int
634qpic_nand_onfi_probe(struct flash_info *flash)
635{
636 struct onfi_probe_params params;
637 uint32_t vld;
638 uint32_t dev_cmd1;
639 unsigned char *buffer;
640 unsigned char onfi_str[4];
641 uint32_t *id;
642 struct onfi_param_page *param_page;
643 int onfi_ret = NANDC_RESULT_SUCCESS;
644
645 /* Allocate memory required to read the onfi param page */
646 buffer = (unsigned char*) malloc(ONFI_READ_PARAM_PAGE_BUFFER_SIZE);
Maria Yu71909742014-07-04 17:30:00 +0800647 ASSERT(buffer != NULL);
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700648
649 /* Read the vld and dev_cmd1 registers before modifying */
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800650 vld = qpic_nand_read_reg(NAND_DEV_CMD_VLD, 0);
651 dev_cmd1 = qpic_nand_read_reg(NAND_DEV_CMD1, 0);
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700652
653 /* Initialize flash cmd */
654 params.cfg.cmd = NAND_CMD_PAGE_READ;
655 params.cfg.exec = 1;
656
657 /* Execute Read ID cmd */
658
659 /* Initialize the config */
660 params.cfg.cfg0 = NAND_CFG0_RAW_ONFI_ID;
661 params.cfg.cfg1 = NAND_CFG1_RAW_ONFI_ID;
662
663 /* Initialize the cmd and vld */
664 params.dev_cmd1 = (dev_cmd1 & 0xFFFFFF00) | ONFI_READ_ID_CMD;
665 params.vld = vld & 0xFFFFFFFE;
666
667 /* Initialize the address
668 * addr1 is not used bcos of the cfg.
669 */
670 params.cfg.addr0 = ONFI_READ_ID_ADDR;
671 params.cfg.addr1 = 0;
672
673 /* Lock the pipe and execute the cmd. */
674 onfi_ret = onfi_probe_cmd_exec(&params, onfi_str, ONFI_READ_ID_BUFFER_SIZE);
675 if (onfi_ret)
676 {
677 dprintf(CRITICAL, "ONFI Read id cmd failed\n");
678 goto qpic_nand_onfi_probe_err;
679 }
680
681 /* Write back vld and cmd and unlock the pipe. */
682 qpic_nand_onfi_probe_cleanup(vld, dev_cmd1);
683
684 /* Check for onfi string */
685 id = (uint32_t*)onfi_str;
686 if (*id != ONFI_SIGNATURE)
687 {
688 dprintf(CRITICAL, "Not an ONFI device\n");
689 /* Not an onfi device. Return error. */
690 onfi_ret = NANDC_RESULT_DEV_NOT_SUPPORTED;
691 goto qpic_nand_onfi_probe_err;
692 }
693
694 dprintf(INFO, "ONFI device found\n");
695 /* Now read the param page */
696 /* Initialize the config */
697 params.cfg.cfg0 = NAND_CFG0_RAW_ONFI_PARAM_PAGE;
698 params.cfg.cfg1 = NAND_CFG1_RAW_ONFI_PARAM_PAGE;
699
700 /* Initialize the cmd and vld */
701 params.dev_cmd1 = (dev_cmd1 & 0xFFFFFF00) | ONFI_READ_PARAM_PAGE_CMD;
702 params.vld = vld & 0xFFFFFFFE;
703
704 /* Initialize the address
705 * addr1 is not used bcos of the cfg.
706 */
707 params.cfg.addr0 = ONFI_READ_PARAM_PAGE_ADDR;
708 params.cfg.addr1 = 0;
709
710 /* Lock the pipe and execute the cmd. */
711 onfi_ret = onfi_probe_cmd_exec(&params, buffer, ONFI_READ_PARAM_PAGE_BUFFER_SIZE);
712 if (onfi_ret)
713 {
714 dprintf(CRITICAL, "ONFI Read param page failed\n");
715 goto qpic_nand_onfi_probe_err;
716 }
717
718 /* Write back vld and cmd and unlock the pipe. */
719 qpic_nand_onfi_probe_cleanup(vld, dev_cmd1);
720
721 /* Verify the integrity of the returned page */
722 param_page = (struct onfi_param_page*)buffer;
723
724 /* TODO: Add CRC check to validate the param page. */
725
726 /* Save the parameter values */
727 onfi_ret = qpic_nand_onfi_save_params(param_page, flash);
728
729qpic_nand_onfi_probe_err:
730 if (onfi_ret)
731 dprintf(CRITICAL, "ONFI probe failed\n");
732
733 free(buffer);
734
735 return onfi_ret;
736}
737
738/* Enquues a desc for a flash cmd with NWD flag set:
739 * cfg: Defines the configuration for the flash cmd.
740 * start: Address where the command elements are added.
741 *
742 * Returns the address where the next cmd element can be added.
743 */
744struct cmd_element*
745qpic_nand_add_cmd_ce(struct cfg_params *cfg,
746 struct cmd_element *start)
747{
748 struct cmd_element *cmd_list_ptr;
749
750 cmd_list_ptr = qpic_nand_add_addr_n_cfg_ce(cfg, start);
751
752 bam_add_cmd_element(cmd_list_ptr, NAND_FLASH_CMD, (uint32_t)cfg->cmd, CE_WRITE_TYPE);
753 cmd_list_ptr++;
754
755 bam_add_cmd_element(cmd_list_ptr, NAND_EXEC_CMD, (uint32_t)cfg->exec, CE_WRITE_TYPE);
756 cmd_list_ptr++;
757
758 return cmd_list_ptr;
759}
760
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800761/* Reads nand_flash_status */
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700762struct cmd_element*
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800763qpic_nand_add_read_ce(struct cmd_element *start, uint32_t *flash_status_read)
764{
765 struct cmd_element *cmd_list_ptr = start;
766
767 bam_add_cmd_element(cmd_list_ptr, NAND_FLASH_STATUS, (uint32_t)PA((addr_t)flash_status_read), CE_READ_TYPE);
768 cmd_list_ptr++;
769
770 return cmd_list_ptr;
771}
772
773/* Resets nand_flash_status and nand_read_status */
774struct cmd_element*
775qpic_nand_reset_status_ce(struct cmd_element *start, uint32_t read_status)
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700776{
777 struct cmd_element *cmd_list_ptr = start;
778 uint32_t flash_status_reset;
779 uint32_t read_status_reset;
780
781 /* Read and reset the status registers. */
782 flash_status_reset = NAND_FLASH_STATUS_RESET;
783 read_status_reset = NAND_READ_STATUS_RESET;
784
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700785 bam_add_cmd_element(cmd_list_ptr, NAND_FLASH_STATUS, (uint32_t)flash_status_reset, CE_WRITE_TYPE);
786 cmd_list_ptr++;
787
788 if (read_status)
789 {
790 bam_add_cmd_element(cmd_list_ptr, NAND_READ_STATUS, (uint32_t)read_status_reset, CE_WRITE_TYPE);
791 cmd_list_ptr++;
792 }
793
794 return cmd_list_ptr;
795}
796
797struct cmd_element*
798qpic_nand_add_isbad_cmd_ce(struct cfg_params *cfg,
799 struct cmd_element *start)
800{
801 struct cmd_element *cmd_list_ptr = start;
802
803 bam_add_cmd_element(cmd_list_ptr, NAND_DEV0_ECC_CFG, (uint32_t)cfg->ecc_cfg, CE_WRITE_TYPE);
804 cmd_list_ptr++;
805
806 bam_add_cmd_element(cmd_list_ptr, NAND_READ_LOCATION_n(0), (uint32_t)cfg->addr_loc_0, CE_WRITE_TYPE);
807 cmd_list_ptr++;
808
809 cmd_list_ptr = qpic_nand_add_cmd_ce(cfg, cmd_list_ptr);
810
811 return cmd_list_ptr;
812}
813
814static int
815qpic_nand_block_isbad_exec(struct cfg_params *params,
816 uint8_t *bad_block)
817{
818
819 struct cmd_element *cmd_list_ptr = ce_array;
820 struct cmd_element *cmd_list_ptr_start = ce_array;
821 uint8_t desc_flags = BAM_DESC_NWD_FLAG | BAM_DESC_CMD_FLAG
822 | BAM_DESC_LOCK_FLAG | BAM_DESC_INT_FLAG;
823 int num_desc = 0;
824 uint32_t status = 0;
825 int nand_ret = NANDC_RESULT_SUCCESS;
826
827 cmd_list_ptr = qpic_nand_add_isbad_cmd_ce(params, cmd_list_ptr);
828
829 /* Enqueue the desc for the above commands */
830 bam_add_one_desc(&bam,
831 CMD_PIPE_INDEX,
Mayank Grover20fdd882016-10-25 16:53:30 +0530832 (unsigned char*)PA((addr_t)cmd_list_ptr_start),
Deepa Dinamani0bf2f442012-10-19 11:41:06 -0700833 PA((uint32_t)cmd_list_ptr - (uint32_t)cmd_list_ptr_start),
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700834 desc_flags);
835
836 num_desc++;
837
838 /* Add Data desc */
839 bam_add_desc(&bam,
840 DATA_PRODUCER_PIPE_INDEX,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -0700841 (unsigned char *)PA((addr_t)bad_block),
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700842 4,
843 BAM_DESC_INT_FLAG);
844
Parth Dixit8e83bed2017-02-21 17:49:46 +0530845 arch_clean_invalidate_cache_range((addr_t)bad_block, sizeof(uint32_t));
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700846 qpic_nand_wait_for_cmd_exec(num_desc);
Parth Dixit8e83bed2017-02-21 17:49:46 +0530847 arch_clean_invalidate_cache_range((addr_t)bad_block, sizeof(uint32_t));
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700848
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800849 status = qpic_nand_read_reg(NAND_FLASH_STATUS, 0);
Deepa Dinamani19530062012-10-03 14:43:05 -0700850
851 nand_ret = qpic_nand_check_status(status);
852
853 /* Dummy read to unlock pipe. */
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800854 status = qpic_nand_read_reg(NAND_FLASH_STATUS, BAM_DESC_UNLOCK_FLAG);
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700855
Deepa Dinamani19530062012-10-03 14:43:05 -0700856 if (nand_ret)
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700857 return NANDC_RESULT_FAILURE;
858
859 qpic_nand_wait_for_data(DATA_PRODUCER_PIPE_INDEX);
860
861 return nand_ret;
862}
863
Tanya Brokhman72b44dc2015-01-07 10:20:05 +0200864/**
865 * qpic_nand_block_isbad() - Checks is given block is bad
866 * @page - number of page the block starts at
867 *
868 * Returns nand_result_t
869 */
870nand_result_t qpic_nand_block_isbad(unsigned page)
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700871{
872 unsigned cwperpage;
873 struct cfg_params params;
Parth Dixit8e83bed2017-02-21 17:49:46 +0530874 static uint8_t bad_block[4];
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700875 unsigned nand_ret = NANDC_RESULT_SUCCESS;
Deepa Dinamanidc1381e2012-11-15 14:53:24 -0800876 uint32_t blk = page / flash.num_pages_per_blk;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700877
Deepa Dinamanidc1381e2012-11-15 14:53:24 -0800878 if (bbtbl[blk] == NAND_BAD_BLK_VALUE_IS_GOOD)
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700879 return NANDC_RESULT_SUCCESS;
Deepa Dinamanidc1381e2012-11-15 14:53:24 -0800880 else if (bbtbl[blk] == NAND_BAD_BLK_VALUE_IS_BAD)
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700881 return NANDC_RESULT_BAD_BLOCK;
882 else
883 {
884 /* Read the bad block value from the flash.
885 * Bad block value is stored in the first page of the block.
886 */
887 /* Read the first page in the block. */
Mayank Grover705ccf12018-07-18 15:26:34 +0530888 /* Ensure we always read first page of block */
889 if (page & flash.num_pages_per_blk_mask)
890 page = page - (page & flash.num_pages_per_blk_mask);
891
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700892 cwperpage = flash.cws_per_page;
893
894 /* Read page cmd */
Deepa Dinamanidc1381e2012-11-15 14:53:24 -0800895 params.cmd = NAND_CMD_PAGE_READ_ECC;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700896 /* Clear the CW per page bits */
897 params.cfg0 = cfg0_raw & ~(7U << NAND_DEV0_CFG0_CW_PER_PAGE_SHIFT);
898 params.cfg1 = cfg1_raw;
Deepa Dinamanidc1381e2012-11-15 14:53:24 -0800899 /* addr0 - Write column addr + few bits in row addr upto 32 bits. */
900 params.addr0 = (page << 16) | (USER_DATA_BYTES_PER_CW * cwperpage);
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700901
902 /* addr1 - Write rest of row addr.
903 * This will be all 0s.
904 */
Deepa Dinamanidc1381e2012-11-15 14:53:24 -0800905 params.addr1 = (page >> 16) & 0xff;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700906 params.addr_loc_0 = NAND_RD_LOC_OFFSET(0);
907 params.addr_loc_0 |= NAND_RD_LOC_LAST_BIT(1);
908 params.addr_loc_0 |= NAND_RD_LOC_SIZE(4); /* Read 4 bytes */
Deepa Dinamanidc1381e2012-11-15 14:53:24 -0800909 params.ecc_cfg = ecc_bch_cfg | 0x1; /* Disable ECC */
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700910 params.exec = 1;
911
912 if (qpic_nand_block_isbad_exec(&params, bad_block))
913 {
914 dprintf(CRITICAL,
915 "Could not read bad block value\n");
916 return NANDC_RESULT_FAILURE;
917 }
918
919 if (flash.widebus)
920 {
921 if (bad_block[0] != 0xFF && bad_block[1] != 0xFF)
922 {
Deepa Dinamanidc1381e2012-11-15 14:53:24 -0800923 bbtbl[blk] = NAND_BAD_BLK_VALUE_IS_BAD;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700924 nand_ret = NANDC_RESULT_BAD_BLOCK;
925 }
926 }
927 else if (bad_block[0] != 0xFF)
928 {
Deepa Dinamanidc1381e2012-11-15 14:53:24 -0800929 bbtbl[blk] = NAND_BAD_BLK_VALUE_IS_BAD;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700930 nand_ret = NANDC_RESULT_BAD_BLOCK;
931 }
932 else
Deepa Dinamanidc1381e2012-11-15 14:53:24 -0800933 bbtbl[blk] = NAND_BAD_BLK_VALUE_IS_GOOD;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700934
Parth Dixit8e83bed2017-02-21 17:49:46 +0530935
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700936 return nand_ret;
937 }
938}
939
940/* Function to erase a block on the nand.
941 * page: Starting page address for the block.
942 */
Tanya Brokhman72b44dc2015-01-07 10:20:05 +0200943nand_result_t qpic_nand_blk_erase(uint32_t page)
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700944{
945 struct cfg_params cfg;
946 struct cmd_element *cmd_list_ptr = ce_array;
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800947 struct cmd_element *cmd_list_read_ptr = ce_read_array;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700948 struct cmd_element *cmd_list_ptr_start = ce_array;
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800949 struct cmd_element *cmd_list_read_ptr_start = ce_read_array;
Veera Sundaram Sankaran00181512014-12-09 11:23:39 -0800950 uint32_t status;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700951 int num_desc = 0;
952 uint32_t blk_addr = page / flash.num_pages_per_blk;
953
954 /* Erase only if the block is not bad */
Deepa Dinamanidc1381e2012-11-15 14:53:24 -0800955 if (qpic_nand_block_isbad(page))
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700956 {
957 dprintf(CRITICAL,
958 "NAND Erase error: Block address belongs to bad block: %d\n",
959 blk_addr);
960 return NANDC_RESULT_FAILURE;
961 }
962
963 /* Fill in params for the erase flash cmd */
964 cfg.addr0 = page;
965 cfg.addr1 = 0;
966 /* Clear CW_PER_PAGE in cfg0 */
967 cfg.cfg0 = cfg0 & ~(7U << NAND_DEV0_CFG0_CW_PER_PAGE_SHIFT);
968 cfg.cfg1 = cfg1;
969 cfg.cmd = NAND_CMD_BLOCK_ERASE;
970 cfg.exec = 1;
971
972 cmd_list_ptr = qpic_nand_add_cmd_ce(&cfg, cmd_list_ptr);
973
974 /* Enqueue the desc for the above commands */
975 bam_add_one_desc(&bam,
976 CMD_PIPE_INDEX,
Mayank Grover20fdd882016-10-25 16:53:30 +0530977 (unsigned char*)PA((addr_t)cmd_list_ptr_start),
Deepa Dinamani0bf2f442012-10-19 11:41:06 -0700978 PA((uint32_t)cmd_list_ptr - (uint32_t)cmd_list_ptr_start),
Deepa Dinamani2467bbb2012-10-02 13:59:58 -0700979 BAM_DESC_NWD_FLAG | BAM_DESC_CMD_FLAG | BAM_DESC_INT_FLAG | BAM_DESC_LOCK_FLAG);
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700980
981 cmd_list_ptr_start = cmd_list_ptr;
982 num_desc++;
983
984 qpic_nand_wait_for_cmd_exec(num_desc);
985
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800986 status = qpic_nand_read_reg(NAND_FLASH_STATUS, 0);
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700987
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700988 cmd_list_ptr_start = cmd_list_ptr;
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800989 cmd_list_read_ptr_start = cmd_list_read_ptr;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700990
991 /* QPIC controller automatically sends
992 * GET_STATUS cmd to the nand card because
993 * of the configuration programmed.
994 * Read the result of GET_STATUS cmd.
995 */
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800996 cmd_list_read_ptr = qpic_nand_add_read_ce(cmd_list_read_ptr, &status);
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700997
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800998 /* Enqueue the desc for the NAND_FLASH_STATUS read command */
999 bam_add_one_desc(&bam,
1000 CMD_PIPE_INDEX,
Mayank Grover20fdd882016-10-25 16:53:30 +05301001 (unsigned char*)PA((addr_t)cmd_list_read_ptr_start),
Sridhar Parasuramf5188d82014-11-17 15:39:55 -08001002 PA((uint32_t)cmd_list_read_ptr - (uint32_t)cmd_list_read_ptr_start),
1003 BAM_DESC_CMD_FLAG) ;
1004
1005 cmd_list_ptr = qpic_nand_reset_status_ce(cmd_list_ptr, 1);
1006
1007 /* Enqueue the desc for NAND_FLASH_STATUS and NAND_READ_STATUS write commands */
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001008 bam_add_one_desc(&bam,
1009 CMD_PIPE_INDEX,
Mayank Grover20fdd882016-10-25 16:53:30 +05301010 (unsigned char*)PA((addr_t)cmd_list_ptr_start),
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001011 PA((uint32_t)cmd_list_ptr - (uint32_t)cmd_list_ptr_start),
Deepa Dinamani19530062012-10-03 14:43:05 -07001012 BAM_DESC_INT_FLAG | BAM_DESC_CMD_FLAG) ;
Sridhar Parasuramf5188d82014-11-17 15:39:55 -08001013 num_desc = 2;
Parth Dixit8e83bed2017-02-21 17:49:46 +05301014 arch_clean_invalidate_cache_range((addr_t)&status, sizeof(uint32_t));
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001015 qpic_nand_wait_for_cmd_exec(num_desc);
Parth Dixit8e83bed2017-02-21 17:49:46 +05301016 arch_clean_invalidate_cache_range((addr_t)&status, sizeof(uint32_t));
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001017
Deepa Dinamani19530062012-10-03 14:43:05 -07001018 status = qpic_nand_check_status(status);
1019
1020 /* Dummy read to unlock pipe. */
Veera Sundaram Sankaran00181512014-12-09 11:23:39 -08001021 qpic_nand_read_reg(NAND_FLASH_STATUS, BAM_DESC_UNLOCK_FLAG);
Deepa Dinamani19530062012-10-03 14:43:05 -07001022
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001023 /* Check for status errors*/
Deepa Dinamani19530062012-10-03 14:43:05 -07001024 if (status)
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001025 {
1026 dprintf(CRITICAL,
1027 "NAND Erase error: Block address belongs to bad block: %d\n",
1028 blk_addr);
Tanya Brokhman72b44dc2015-01-07 10:20:05 +02001029 qpic_nand_mark_badblock(page);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001030 return NANDC_RESULT_FAILURE;
1031 }
1032
1033 /* Check for PROG_ERASE_OP_RESULT bit for the result of erase operation. */
Deepa Dinamani2467bbb2012-10-02 13:59:58 -07001034 if (!(status & PROG_ERASE_OP_RESULT))
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001035 return NANDC_RESULT_SUCCESS;
1036
Tanya Brokhman72b44dc2015-01-07 10:20:05 +02001037 qpic_nand_mark_badblock(page);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001038 return NANDC_RESULT_FAILURE;
1039}
1040
1041/* Return num of desc added. */
Deepa Dinamani19530062012-10-03 14:43:05 -07001042static void
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001043qpic_nand_add_wr_page_cws_cmd_desc(struct cfg_params *cfg,
1044 uint32_t status[],
1045 enum nand_cfg_value cfg_mode)
1046{
1047 struct cmd_element *cmd_list_ptr = ce_array;
Sridhar Parasuramf5188d82014-11-17 15:39:55 -08001048 struct cmd_element *cmd_list_read_ptr = ce_read_array;
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001049 struct cmd_element *cmd_list_ptr_start = ce_array;
Sridhar Parasuramf5188d82014-11-17 15:39:55 -08001050 struct cmd_element *cmd_list_read_ptr_start = ce_read_array;
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001051 uint32_t ecc;
1052 int num_desc = 0;
1053 int int_flag = 0;
1054
1055 if (cfg_mode == NAND_CFG)
1056 ecc = ecc_bch_cfg;
1057 else
Deepa Dinamanidc1381e2012-11-15 14:53:24 -08001058 ecc = ecc_bch_cfg | 0x1; /* Disable ECC */
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001059
1060 /* Add ECC configuration */
1061 bam_add_cmd_element(cmd_list_ptr, NAND_DEV0_ECC_CFG,
1062 (uint32_t)ecc, CE_WRITE_TYPE);
1063 cmd_list_ptr++;
1064 cmd_list_ptr = qpic_nand_add_addr_n_cfg_ce(cfg, cmd_list_ptr);
1065
1066 bam_add_cmd_element(cmd_list_ptr, NAND_FLASH_CMD,
1067 (uint32_t)cfg->cmd, CE_WRITE_TYPE);
1068 cmd_list_ptr++;
1069
1070 /* Enqueue the desc for the above commands */
1071 bam_add_one_desc(&bam,
1072 CMD_PIPE_INDEX,
Mayank Grover20fdd882016-10-25 16:53:30 +05301073 (unsigned char*)PA((addr_t)cmd_list_ptr_start),
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001074 PA((uint32_t)cmd_list_ptr - (uint32_t)cmd_list_ptr_start),
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001075 BAM_DESC_CMD_FLAG | BAM_DESC_LOCK_FLAG);
1076
1077 num_desc++;
1078
1079 /* Add CE for all the CWs */
1080 for (unsigned i = 0; i < flash.cws_per_page; i++)
1081 {
1082 cmd_list_ptr_start = cmd_list_ptr;
Deepa Dinamani19530062012-10-03 14:43:05 -07001083 int_flag = BAM_DESC_INT_FLAG;
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001084
1085 bam_add_cmd_element(cmd_list_ptr, NAND_EXEC_CMD, (uint32_t)cfg->exec, CE_WRITE_TYPE);
1086 cmd_list_ptr++;
1087
1088 /* Enqueue the desc for the above commands */
1089 bam_add_one_desc(&bam,
1090 CMD_PIPE_INDEX,
Mayank Grover20fdd882016-10-25 16:53:30 +05301091 (unsigned char*)PA((addr_t)cmd_list_ptr_start),
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001092 PA((uint32_t)cmd_list_ptr - (uint32_t)cmd_list_ptr_start),
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001093 BAM_DESC_NWD_FLAG | BAM_DESC_CMD_FLAG);
1094
1095 num_desc++;
1096 cmd_list_ptr_start = cmd_list_ptr;
Sridhar Parasuramf5188d82014-11-17 15:39:55 -08001097 cmd_list_read_ptr_start = cmd_list_read_ptr;
1098
1099 cmd_list_read_ptr = qpic_nand_add_read_ce(cmd_list_read_ptr_start, &status[i]);
1100 /* Enqueue the desc for the NAND_FLASH_STATUS read command */
1101 bam_add_one_desc(&bam,
1102 CMD_PIPE_INDEX,
Mayank Grover20fdd882016-10-25 16:53:30 +05301103 (unsigned char*)PA((addr_t)cmd_list_read_ptr_start),
Sridhar Parasuramf5188d82014-11-17 15:39:55 -08001104 PA((uint32_t)cmd_list_read_ptr - (uint32_t)cmd_list_read_ptr_start),
1105 BAM_DESC_CMD_FLAG);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001106
1107 /* Set interrupt bit only for the last CW */
1108 if (i == flash.cws_per_page - 1)
Sridhar Parasuramf5188d82014-11-17 15:39:55 -08001109 cmd_list_ptr = qpic_nand_reset_status_ce(cmd_list_ptr, 1);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001110 else
Sridhar Parasuramf5188d82014-11-17 15:39:55 -08001111 cmd_list_ptr = qpic_nand_reset_status_ce(cmd_list_ptr, 0);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001112
Sridhar Parasuramf5188d82014-11-17 15:39:55 -08001113 /* Enqueue the desc for NAND_FLASH_STATUS and NAND_READ_STATUS write commands */
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001114 bam_add_one_desc(&bam,
1115 CMD_PIPE_INDEX,
Mayank Grover20fdd882016-10-25 16:53:30 +05301116 (unsigned char*)PA((addr_t)cmd_list_ptr_start),
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001117 PA((uint32_t)cmd_list_ptr - (uint32_t)cmd_list_ptr_start),
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001118 int_flag | BAM_DESC_CMD_FLAG);
Sridhar Parasuramf5188d82014-11-17 15:39:55 -08001119 num_desc += 2;
Deepa Dinamani19530062012-10-03 14:43:05 -07001120
Parth Dixit8e83bed2017-02-21 17:49:46 +05301121 arch_clean_invalidate_cache_range((addr_t)&status[i], sizeof(uint32_t));
Deepa Dinamani19530062012-10-03 14:43:05 -07001122 qpic_nand_wait_for_cmd_exec(num_desc);
Parth Dixit8e83bed2017-02-21 17:49:46 +05301123 arch_clean_invalidate_cache_range((addr_t)&status[i], sizeof(uint32_t));
Deepa Dinamani19530062012-10-03 14:43:05 -07001124
1125 status[i] = qpic_nand_check_status(status[i]);
1126
1127 num_desc = 0;
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001128 }
Deepa Dinamani19530062012-10-03 14:43:05 -07001129 return;
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001130}
1131
1132void
1133qpic_add_wr_page_cws_data_desc(const void *buffer,
1134 enum nand_cfg_value cfg_mode,
1135 const void *spareaddr)
1136{
1137 int len;
1138 int flags;
1139 uint32_t start;
1140 unsigned num_desc = 0;
1141
1142 for( unsigned i = 0; i < flash.cws_per_page; i++)
1143 {
1144 flags = 0;
1145
1146 /* Set the interrupt flag on the last CW write for the page. */
1147 if( i == flash.cws_per_page - 1)
1148 flags |= BAM_DESC_INT_FLAG;
1149
1150 if (cfg_mode != NAND_CFG_RAW)
1151 {
1152 start = (uint32_t)buffer + i * DATA_BYTES_IN_IMG_PER_CW;
1153
1154 if (i < (flash.cws_per_page - 1))
1155 {
1156 len = DATA_BYTES_IN_IMG_PER_CW;
1157 flags |= BAM_DESC_EOT_FLAG;
1158 }
1159 else
1160 {
1161 /* Allow space for spare bytes in the last page */
1162 len = USER_DATA_BYTES_PER_CW - ((flash.cws_per_page - 1) << 2);
1163 flags = 0;
1164 }
1165 }
1166 else
1167 {
1168 start = (uint32_t)buffer;
1169 len = flash.cw_size;
1170 flags |= BAM_DESC_EOT_FLAG;
1171 }
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001172 bam_add_one_desc(&bam, DATA_CONSUMER_PIPE_INDEX, (unsigned char*)PA(start), len, flags);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001173 num_desc++;
1174
1175 if ((i == (flash.cws_per_page - 1)) && (cfg_mode == NAND_CFG))
1176 {
1177 /* write extra data */
1178 start = (uint32_t)spareaddr;
1179 len = (flash.cws_per_page << 2);
1180 flags = BAM_DESC_EOT_FLAG | BAM_DESC_INT_FLAG;
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001181 bam_add_one_desc(&bam, DATA_CONSUMER_PIPE_INDEX, (unsigned char*)PA(start), len, flags);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001182 num_desc++;
1183 }
1184 }
1185
1186 bam_sys_gen_event(&bam, DATA_CONSUMER_PIPE_INDEX, num_desc);
1187}
1188
1189static nand_result_t
1190qpic_nand_write_page(uint32_t pg_addr,
1191 enum nand_cfg_value cfg_mode,
1192 const void* buffer,
1193 const void* spareaddr)
1194{
1195 struct cfg_params cfg;
Deepa Dinamani16663a62013-02-07 16:25:59 -08001196 uint32_t status[QPIC_NAND_MAX_CWS_IN_PAGE];
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001197 int nand_ret = NANDC_RESULT_SUCCESS;
1198
1199 if (cfg_mode == NAND_CFG_RAW)
1200 {
1201 cfg.cfg0 = cfg0_raw;
1202 cfg.cfg1 = cfg1_raw;
1203 }
1204 else
1205 {
1206 cfg.cfg0 = cfg0;
1207 cfg.cfg1 = cfg1;
1208 }
1209
1210 cfg.cmd = NAND_CMD_PRG_PAGE;
1211 cfg.exec = 1;
1212
1213 cfg.addr0 = pg_addr << 16;
1214 cfg.addr1 = (pg_addr >> 16) & 0xff;
1215
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001216 qpic_add_wr_page_cws_data_desc(buffer, cfg_mode, spareaddr);
1217
Deepa Dinamani19530062012-10-03 14:43:05 -07001218 qpic_nand_add_wr_page_cws_cmd_desc(&cfg, status, cfg_mode);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001219
1220 /* Check for errors */
1221 for(unsigned i = 0; i < flash.cws_per_page; i++)
1222 {
1223 nand_ret = qpic_nand_check_status(status[i]);
1224 if (nand_ret)
1225 {
1226 dprintf(CRITICAL,
1227 "Failed to write CW %d for page: %d\n",
1228 i, pg_addr);
1229 break;
1230 }
1231 }
1232
1233 /* Wait for data to be available */
1234 qpic_nand_wait_for_data(DATA_CONSUMER_PIPE_INDEX);
1235
1236 return nand_ret;
1237}
1238
1239static int
1240qpic_nand_mark_badblock(uint32_t page)
1241{
1242 char empty_buf[NAND_CW_SIZE_8_BIT_ECC];
1243
1244 memset(empty_buf, 0, NAND_CW_SIZE_8_BIT_ECC);
1245
1246 /* Going to first page of the block */
1247 if (page & flash.num_pages_per_blk_mask)
1248 page = page - (page & flash.num_pages_per_blk_mask);
1249
1250 return qpic_nand_write_page(page, NAND_CFG_RAW, empty_buf, 0);
1251}
1252
1253static void
1254qpic_nand_non_onfi_probe(struct flash_info *flash)
1255{
1256 int dev_found = 0;
1257 unsigned index;
1258 uint32_t ecc_bits;
1259
1260 /* Read the nand id. */
1261 qpic_nand_fetch_id(flash);
1262
1263 /* Check if we support the device */
Deepa Dinamani649a94a2013-03-07 14:37:31 -08001264 for (index = 0; index < (ARRAY_SIZE(supported_flash)); index++)
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001265 {
Sridhar Parasuramfb0d9c82015-02-02 15:23:13 -08001266 if (((flash->id & supported_flash[index].mask) ==
1267 (supported_flash[index].flash_id & (supported_flash[index].mask))) &&
1268 ((flash->id2 & supported_flash[index].mask2) ==
1269 (supported_flash[index].flash_id2 & (supported_flash[index].mask2))))
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001270 {
1271 dev_found = 1;
1272 break;
1273 }
1274 }
1275
1276 if (dev_found)
1277 {
1278 flash->page_size = supported_flash[index].pagesize;
1279 flash->block_size = supported_flash[index].blksize;
1280 flash->spare_size = supported_flash[index].oobsize;
1281 ecc_bits = supported_flash[index].ecc_8_bits;
1282
1283 /* Make sure that the block size and page size are defined. */
1284 ASSERT(flash->block_size);
1285 ASSERT(flash->page_size);
1286
1287 flash->num_blocks = supported_flash[index].density;
1288 flash->num_blocks /= (flash->block_size);
1289 flash->num_pages_per_blk = flash->block_size / flash->page_size;
1290 flash->num_pages_per_blk_mask = flash->num_pages_per_blk - 1;
1291
1292 /* Look for 8bit BCH ECC Nand, TODO: ECC Correctability >= 8 */
1293 if (ecc_bits)
1294 flash->ecc_width = NAND_WITH_8_BIT_ECC;
1295 else
1296 flash->ecc_width = NAND_WITH_4_BIT_ECC;
1297
1298 flash->density = supported_flash[index].density;
1299 flash->widebus = supported_flash[index].widebus;
1300
1301 return;
1302 }
1303
1304 /* Flash device is not supported, print flash device info and halt */
1305 if (dev_found == 0)
1306 {
1307 dprintf(CRITICAL, "NAND device is not supported: nandid: 0x%x"
1308 "maker=0x%02x device=0x%02x\n",
1309 flash->id,
1310 flash->vendor,
1311 flash->device);
1312 ASSERT(0);
1313 }
1314
1315 dprintf(INFO, "nandid: 0x%x maker=0x%02x device=0x%02x page_size=%d\n",
1316 flash->id,
1317 flash->vendor,
1318 flash->device,
1319 flash->page_size);
1320
1321 dprintf(INFO, "spare_size=%d block_size=%d num_blocks=%d\n",
1322 flash->spare_size,
1323 flash->block_size,
1324 flash->num_blocks);
1325}
1326
1327void
1328qpic_nand_init(struct qpic_nand_init_config *config)
1329{
1330 uint32_t i;
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001331
1332 nand_base = config->nand_base;
1333
Deepa Dinamanie9ded132012-11-27 15:03:38 -08001334 qpic_bam_init(config);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001335
Deepa Dinamani649a94a2013-03-07 14:37:31 -08001336 qpic_nand_non_onfi_probe(&flash);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001337
1338 /* Save the RAW and read/write configs */
1339 qpic_nand_save_config(&flash);
1340
1341 flash_spare_bytes = (unsigned char *)malloc(flash.spare_size);
1342
1343 if (flash_spare_bytes == NULL)
1344 {
1345 dprintf(CRITICAL, "Failed to allocate memory for spare bytes\n");
1346 return;
1347 }
1348
1349 /* Create a bad block table */
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001350 bbtbl = (uint8_t *) malloc(sizeof(uint8_t) * flash.num_blocks);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001351
1352 if (bbtbl == NULL)
1353 {
1354 dprintf(CRITICAL, "Failed to allocate memory for bad block table\n");
1355 return;
1356 }
1357
1358 for (i = 0; i < flash.num_blocks; i++)
1359 bbtbl[i] = NAND_BAD_BLK_VALUE_NOT_READ;
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001360
1361 /* Set aside contiguous memory for reads/writes.
1362 * This is needed as the BAM transfers only work with
1363 * physically contiguous buffers.
1364 * We will copy any data to be written/ to be read from
1365 * nand to this buffer and this buffer will be submitted to BAM.
1366 */
1367 rdwr_buf = (uint8_t*) malloc(flash.page_size + flash.spare_size);
1368
1369 if (rdwr_buf == NULL)
1370 {
1371 dprintf(CRITICAL, "Failed to allocate memory for page reads or writes\n");
1372 return;
1373 }
1374
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001375}
1376
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -07001377unsigned
1378flash_page_size(void)
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001379{
1380 return flash.page_size;
1381}
1382
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -07001383unsigned
1384flash_block_size(void)
1385{
1386 return flash.block_size;
1387}
1388
Deepa Dinamani8e6b2432012-10-17 17:12:44 -07001389unsigned
1390flash_num_blocks(void)
1391{
1392 return flash.num_blocks;
1393}
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -07001394
Tanya Brokhman72b44dc2015-01-07 10:20:05 +02001395unsigned
Gaurav Nebhwani64092f22016-05-20 13:58:21 +05301396flash_num_pages_per_blk(void)
1397{
1398 return flash.num_pages_per_blk;
1399}
1400
1401unsigned
Tanya Brokhman72b44dc2015-01-07 10:20:05 +02001402flash_spare_size(void)
1403{
1404 return flash.spare_size;
1405}
1406
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -07001407struct ptable *
1408flash_get_ptable(void)
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001409{
1410 return flash_ptable;
1411}
1412
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -07001413void
Deepa Dinamani87feab82012-10-04 14:28:05 -07001414qpic_nand_uninit()
1415{
1416 bam_pipe_reset(&bam, DATA_PRODUCER_PIPE_INDEX);
1417 bam_pipe_reset(&bam, DATA_CONSUMER_PIPE_INDEX);
1418 bam_pipe_reset(&bam, CMD_PIPE_INDEX);
1419
1420}
1421void
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -07001422flash_set_ptable(struct ptable *new_ptable)
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001423{
1424 ASSERT(flash_ptable == NULL && new_ptable != NULL);
1425 flash_ptable = new_ptable;
1426}
1427
Channagoud Kadabib1dc47c2015-05-21 17:02:44 -07001428static int find_num_zeros_per_cw(uint8_t *ecc_buf, uint32_t ecc_bytes)
1429{
1430 uint8_t val;
1431 uint32_t i;
1432 int num_zeros = 0;
1433
1434 for (i = 0; i < ecc_bytes; i++)
1435 {
1436 val = ecc_buf[i];
1437 while (val)
1438 {
1439 if ((val & 1) == 0)
1440 num_zeros++;
1441 if (num_zeros > THRESHOLD_BIT_FLIPS)
1442 goto out;
1443 val >>= 1;
1444 }
1445 }
1446
1447out:
1448 return num_zeros;
1449}
1450
1451static int qpic_nand_read_erased_page(uint32_t page)
1452{
1453 struct cfg_params params;
1454 uint32_t ecc;
1455 uint32_t flash_sts[QPIC_NAND_MAX_CWS_IN_PAGE];
1456 uint32_t buffer_sts[QPIC_NAND_MAX_CWS_IN_PAGE];
1457 uint32_t addr_loc_0;
1458 uint32_t total_ecc_bytes = 0;
1459 struct cmd_element *cmd_list_ptr = ce_array;
1460 struct cmd_element *cmd_list_ptr_start = ce_array;
1461 uint32_t num_cmd_desc = 0;
1462 uint32_t num_data_desc = 0;
1463 uint32_t i;
1464 int nand_ret = NANDC_RESULT_SUCCESS;
1465 uint8_t flags = 0;
1466 uint32_t *cmd_list_temp = NULL;
1467 uint8_t *ecc_buf = NULL;
1468 uint8_t *ecc_temp = NULL;
1469 int num_zeros = 0;
1470#if DEBUG_QPIC_NAND
1471 uint32_t *buffer_temp = NULL;
1472#endif
1473
1474 total_ecc_bytes = (ecc_parity_bytes * flash.cws_per_page);
1475 ecc_buf = memalign(16, total_ecc_bytes);
1476 ASSERT(ecc_buf);
1477
1478 memset(ecc_buf, 0, total_ecc_bytes);
1479
1480 ecc_temp = ecc_buf;
1481#if DEBUG_QPIC_NAND
1482 buffer_temp = (uint32_t*)ecc_buf;
1483#endif
1484 params.addr0 = page << 16;
1485 params.addr1 = (page >> 16) & 0xff;
1486 params.cfg0 = cfg0_raw;
1487 params.cfg1 = cfg1_raw;
1488 params.cmd = NAND_CMD_PAGE_READ;
1489 params.exec = 1;
1490 ecc = ecc_cfg_raw;
1491
1492 /* Read all the Data bytes in the first 3 CWs. */
1493 addr_loc_0 = NAND_RD_LOC_OFFSET(517);
1494 addr_loc_0 |= NAND_RD_LOC_SIZE(ecc_parity_bytes);
1495 addr_loc_0 |= NAND_RD_LOC_LAST_BIT(1);
1496
1497 /* Queue up the command and data descriptors for all the codewords in a page
1498 * and do a single bam transfer at the end.*/
1499 for (i = 0; i < flash.cws_per_page; i++)
1500 {
1501 num_cmd_desc = 0;
1502 num_data_desc = 0;
1503 flags = 0;
1504
1505 if (i == 0)
1506 {
1507 /* Set the lock flag for the first CW */
1508 flags = BAM_DESC_LOCK_FLAG;
1509
1510 cmd_list_ptr = qpic_nand_add_addr_n_cfg_ce(&params, cmd_list_ptr);
1511
1512 bam_add_cmd_element(cmd_list_ptr, NAND_DEV0_ECC_CFG,(uint32_t)ecc, CE_WRITE_TYPE);
1513 cmd_list_ptr++;
1514
1515 bam_add_cmd_element(cmd_list_ptr, NAND_FLASH_CMD, (uint32_t)params.cmd, CE_WRITE_TYPE);
1516 cmd_list_ptr++;
1517
1518 /* Write addr loc 0. */
1519 bam_add_cmd_element(cmd_list_ptr,
1520 NAND_READ_LOCATION_n(0),
1521 (uint32_t)addr_loc_0,
1522 CE_WRITE_TYPE);
1523
1524 cmd_list_ptr++;
1525 }
1526 else
1527 cmd_list_ptr_start = cmd_list_ptr;
1528
1529 if (i == flash.cws_per_page - 1)
1530 flags = BAM_DESC_INT_FLAG;
1531
1532 /* Add Data desc */
1533 bam_add_one_desc(&bam,
1534 DATA_PRODUCER_PIPE_INDEX,
1535 (unsigned char *)PA((addr_t)ecc_temp),
1536 ecc_parity_bytes,
1537 flags);
1538 num_data_desc++;
1539 bam_sys_gen_event(&bam, DATA_PRODUCER_PIPE_INDEX, num_data_desc);
1540
1541 bam_add_cmd_element(cmd_list_ptr,
1542 NAND_EXEC_CMD,
1543 (uint32_t)params.exec,
1544 CE_WRITE_TYPE);
1545 cmd_list_ptr++;
1546
1547 /* Enqueue the desc for the above commands */
1548 bam_add_one_desc(&bam,
1549 CMD_PIPE_INDEX,
Mayank Grover20fdd882016-10-25 16:53:30 +05301550 (unsigned char*)PA((addr_t)cmd_list_ptr_start),
Channagoud Kadabib1dc47c2015-05-21 17:02:44 -07001551 PA((uint32_t)cmd_list_ptr - (uint32_t)cmd_list_ptr_start),
1552 BAM_DESC_NWD_FLAG | BAM_DESC_CMD_FLAG | flags);
1553 num_cmd_desc++;
1554
1555 bam_add_cmd_element(cmd_list_ptr, NAND_FLASH_STATUS, (uint32_t)PA((addr_t)&(flash_sts[i])), CE_READ_TYPE);
Parth Dixit8e83bed2017-02-21 17:49:46 +05301556 arch_clean_invalidate_cache_range((addr_t)&(flash_sts[i]), sizeof(uint32_t));
Channagoud Kadabib1dc47c2015-05-21 17:02:44 -07001557
1558 cmd_list_temp = (uint32_t *)cmd_list_ptr;
1559
1560 cmd_list_ptr++;
1561
1562 bam_add_cmd_element(cmd_list_ptr, NAND_BUFFER_STATUS, (uint32_t)PA((addr_t)&(buffer_sts[i])), CE_READ_TYPE);
Parth Dixit8e83bed2017-02-21 17:49:46 +05301563 arch_clean_invalidate_cache_range((addr_t)&(buffer_sts[i]), sizeof(uint32_t));
Channagoud Kadabib1dc47c2015-05-21 17:02:44 -07001564 cmd_list_ptr++;
1565
1566 if (i == flash.cws_per_page - 1)
1567 {
1568 /* Unlock flag for the last CW */
1569 flags = BAM_DESC_CMD_FLAG | BAM_DESC_UNLOCK_FLAG;
1570 }
1571 else
1572 flags = BAM_DESC_CMD_FLAG;
1573
1574 /* Enqueue the desc for the above command */
1575 bam_add_one_desc(&bam,
1576 CMD_PIPE_INDEX,
1577 (unsigned char*)PA((addr_t)cmd_list_temp),
1578 PA((uint32_t)cmd_list_ptr - (uint32_t)cmd_list_temp),
1579 flags);
1580 num_cmd_desc++;
1581
1582 ecc_temp += ecc_parity_bytes;
1583
1584 /* Notify BAM HW about the newly added descriptors */
1585 bam_sys_gen_event(&bam, CMD_PIPE_INDEX, num_cmd_desc);
Parth Dixit8e83bed2017-02-21 17:49:46 +05301586 arch_clean_invalidate_cache_range((addr_t)&(flash_sts[i]), sizeof(uint32_t));
1587 arch_clean_invalidate_cache_range((addr_t)&(buffer_sts[i]), sizeof(uint32_t));
Channagoud Kadabib1dc47c2015-05-21 17:02:44 -07001588 }
1589
1590 qpic_nand_wait_for_data(DATA_PRODUCER_PIPE_INDEX);
1591
1592 /* Find number of bit flips in the ecc & if there are more than "threshold" bit flips then
1593 * the page is bad otherwise the page is erased page
1594 */
1595 ecc_temp = ecc_buf;
1596
1597 for (i = 0; i < flash.cws_per_page; i++)
1598 {
1599 num_zeros = find_num_zeros_per_cw(ecc_temp, ecc_parity_bytes);
1600
1601 if (num_zeros > THRESHOLD_BIT_FLIPS)
1602 {
1603 nand_ret = NANDC_RESULT_BAD_PAGE;
1604 goto qpic_nand_read_page_error;
1605 }
1606
1607 ecc_temp += ecc_parity_bytes;
1608 }
1609
1610qpic_nand_read_page_error:
1611
1612#if DEBUG_QPIC_NAND
1613 for(i = 0; i < 24; i += 8)
1614 {
1615 printf("ECC: %08x %08x %08x %08x %08x %08x %08x %08x\n",
1616 buffer_temp[i], buffer_temp[i+1], buffer_temp[i+2], buffer_temp[i+3],
1617 buffer_temp[i+4], buffer_temp[i+5], buffer_temp[i+6], buffer_temp[i+7]);
1618 }
1619 printf("ECC: %08x %08x\n", buffer_temp[24], buffer_temp[25]);
1620#endif
1621
1622 free(ecc_buf);
1623 return nand_ret;
1624}
1625
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001626/* Note: No support for raw reads. */
1627static int
1628qpic_nand_read_page(uint32_t page, unsigned char* buffer, unsigned char* spareaddr)
1629{
1630 struct cfg_params params;
1631 uint32_t ecc;
Channagoud Kadabib1dc47c2015-05-21 17:02:44 -07001632 uint32_t flash_sts[QPIC_NAND_MAX_CWS_IN_PAGE] = {0};
1633 uint32_t buffer_sts[QPIC_NAND_MAX_CWS_IN_PAGE] = {0};
1634 uint32_t erased_cw_sts[QPIC_NAND_MAX_CWS_IN_PAGE] = {0};
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001635 uint32_t addr_loc_0;
1636 uint32_t addr_loc_1;
1637 struct cmd_element *cmd_list_ptr = ce_array;
1638 struct cmd_element *cmd_list_ptr_start = ce_array;
1639 uint32_t num_cmd_desc = 0;
1640 uint32_t num_data_desc = 0;
1641 uint32_t status;
1642 uint32_t i;
1643 int nand_ret = NANDC_RESULT_SUCCESS;
Sundarajan Srinivasan024bda52014-02-27 16:48:48 -08001644 uint8_t flags = 0;
1645 uint32_t *cmd_list_temp = NULL;
Channagoud Kadabib1dc47c2015-05-21 17:02:44 -07001646#if DEBUG_QPIC_NAND
1647 uint8_t *buffer_temp = buffer;
1648#endif
Sundarajan Srinivasan024bda52014-02-27 16:48:48 -08001649
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001650 /* UD bytes in last CW is 512 - cws_per_page *4.
1651 * Since each of the CW read earlier reads 4 spare bytes.
1652 */
1653 uint16_t ud_bytes_in_last_cw = USER_DATA_BYTES_PER_CW - ((flash.cws_per_page - 1) << 2);
1654 uint16_t oob_bytes = DATA_BYTES_IN_IMG_PER_CW - ud_bytes_in_last_cw;
1655
1656 params.addr0 = page << 16;
1657 params.addr1 = (page >> 16) & 0xff;
1658 params.cfg0 = cfg0;
1659 params.cfg1 = cfg1;
Channagoud Kadabib1dc47c2015-05-21 17:02:44 -07001660 params.cmd = NAND_CMD_PAGE_READ_ECC;
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001661 params.exec = 1;
1662 ecc = ecc_bch_cfg;
1663
1664 /* Read all the Data bytes in the first 3 CWs. */
1665 addr_loc_0 = NAND_RD_LOC_OFFSET(0);
1666 addr_loc_0 |= NAND_RD_LOC_SIZE(DATA_BYTES_IN_IMG_PER_CW);
1667 addr_loc_0 |= NAND_RD_LOC_LAST_BIT(1);
1668
1669
1670 addr_loc_1 = NAND_RD_LOC_OFFSET(ud_bytes_in_last_cw);
1671 addr_loc_1 |= NAND_RD_LOC_SIZE(oob_bytes);
1672 addr_loc_1 |= NAND_RD_LOC_LAST_BIT(1);
1673
Deepa Dinamanidc1381e2012-11-15 14:53:24 -08001674 status = qpic_nand_block_isbad(page);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001675
1676 if (status)
1677 return status;
1678
sundarajan srinivasan7ced6482013-03-21 16:01:18 -07001679 /* Reset and Configure erased CW/page detection controller */
1680 qpic_nand_erased_status_reset(ce_array, BAM_DESC_LOCK_FLAG);
1681
Sundarajan Srinivasan024bda52014-02-27 16:48:48 -08001682 /* Queue up the command and data descriptors for all the codewords in a page
1683 * and do a single bam transfer at the end.*/
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001684 for (i = 0; i < flash.cws_per_page; i++)
1685 {
1686 num_cmd_desc = 0;
1687 num_data_desc = 0;
1688
1689 if (i == 0)
1690 {
1691 cmd_list_ptr = qpic_nand_add_addr_n_cfg_ce(&params, cmd_list_ptr);
1692
1693 bam_add_cmd_element(cmd_list_ptr, NAND_DEV0_ECC_CFG,(uint32_t)ecc, CE_WRITE_TYPE);
1694 cmd_list_ptr++;
1695 }
1696 else
1697 cmd_list_ptr_start = cmd_list_ptr;
1698
1699 bam_add_cmd_element(cmd_list_ptr, NAND_FLASH_CMD, (uint32_t)params.cmd, CE_WRITE_TYPE);
1700 cmd_list_ptr++;
1701
1702 if (i == flash.cws_per_page - 1)
1703 {
1704 addr_loc_0 = NAND_RD_LOC_OFFSET(0);
1705 addr_loc_0 |= NAND_RD_LOC_SIZE(ud_bytes_in_last_cw);
1706 addr_loc_0 |= NAND_RD_LOC_LAST_BIT(0);
1707
1708 /* Write addr loc 1 only for the last CW. */
1709 bam_add_cmd_element(cmd_list_ptr, NAND_READ_LOCATION_n(1), (uint32_t)addr_loc_1, CE_WRITE_TYPE);
1710 cmd_list_ptr++;
1711
1712 /* Add Data desc */
1713 bam_add_one_desc(&bam,
1714 DATA_PRODUCER_PIPE_INDEX,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001715 (unsigned char *)PA((addr_t)buffer),
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001716 ud_bytes_in_last_cw,
1717 0);
1718 num_data_desc++;
1719
1720 bam_add_one_desc(&bam,
1721 DATA_PRODUCER_PIPE_INDEX,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001722 (unsigned char *)PA((addr_t)spareaddr),
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001723 oob_bytes,
1724 BAM_DESC_INT_FLAG);
1725 num_data_desc++;
1726
1727 bam_sys_gen_event(&bam, DATA_PRODUCER_PIPE_INDEX, num_data_desc);
1728 }
1729 else
1730 {
1731 /* Add Data desc */
1732 bam_add_one_desc(&bam,
1733 DATA_PRODUCER_PIPE_INDEX,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001734 (unsigned char *)PA((addr_t)buffer),
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001735 DATA_BYTES_IN_IMG_PER_CW,
Sundarajan Srinivasan024bda52014-02-27 16:48:48 -08001736 0);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001737 num_data_desc++;
1738 bam_sys_gen_event(&bam, DATA_PRODUCER_PIPE_INDEX, num_data_desc);
1739 }
1740
1741 /* Write addr loc 0. */
1742 bam_add_cmd_element(cmd_list_ptr,
1743 NAND_READ_LOCATION_n(0),
1744 (uint32_t)addr_loc_0,
1745 CE_WRITE_TYPE);
1746
1747 cmd_list_ptr++;
1748 bam_add_cmd_element(cmd_list_ptr,
1749 NAND_EXEC_CMD,
1750 (uint32_t)params.exec,
1751 CE_WRITE_TYPE);
1752 cmd_list_ptr++;
1753
Sundarajan Srinivasan024bda52014-02-27 16:48:48 -08001754 /* Enqueue the desc for the above commands */
1755 bam_add_one_desc(&bam,
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001756 CMD_PIPE_INDEX,
Mayank Grover20fdd882016-10-25 16:53:30 +05301757 (unsigned char*)PA((addr_t)cmd_list_ptr_start),
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001758 PA((uint32_t)cmd_list_ptr - (uint32_t)cmd_list_ptr_start),
Sundarajan Srinivasan024bda52014-02-27 16:48:48 -08001759 BAM_DESC_NWD_FLAG | BAM_DESC_CMD_FLAG);
1760 num_cmd_desc++;
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001761
Sundarajan Srinivasan024bda52014-02-27 16:48:48 -08001762 bam_add_cmd_element(cmd_list_ptr, NAND_FLASH_STATUS, (uint32_t)PA((addr_t)&(flash_sts[i])), CE_READ_TYPE);
1763
vijay kumar4f4405f2014-08-08 11:49:53 +05301764 cmd_list_temp = (uint32_t *)cmd_list_ptr;
Sundarajan Srinivasan024bda52014-02-27 16:48:48 -08001765
1766 cmd_list_ptr++;
1767
1768 bam_add_cmd_element(cmd_list_ptr, NAND_BUFFER_STATUS, (uint32_t)PA((addr_t)&(buffer_sts[i])), CE_READ_TYPE);
1769 cmd_list_ptr++;
1770
Channagoud Kadabib1dc47c2015-05-21 17:02:44 -07001771 /* Read erased CW status */
1772 bam_add_cmd_element(cmd_list_ptr, NAND_ERASED_CW_DETECT_STATUS, (uint32_t)PA((addr_t)&erased_cw_sts[i]), CE_READ_TYPE);
1773 cmd_list_ptr++;
1774
Sundarajan Srinivasan024bda52014-02-27 16:48:48 -08001775 if (i == flash.cws_per_page - 1)
1776 {
1777 flags = BAM_DESC_CMD_FLAG | BAM_DESC_UNLOCK_FLAG;
1778 }
1779 else
1780 flags = BAM_DESC_CMD_FLAG;
1781
1782 /* Enqueue the desc for the above command */
1783 bam_add_one_desc(&bam,
1784 CMD_PIPE_INDEX,
1785 (unsigned char*)PA((addr_t)cmd_list_temp),
1786 PA((uint32_t)cmd_list_ptr - (uint32_t)cmd_list_temp),
1787 flags);
1788 num_cmd_desc++;
1789
1790 buffer += DATA_BYTES_IN_IMG_PER_CW;
1791
1792 /* Notify BAM HW about the newly added descriptors */
1793 bam_sys_gen_event(&bam, CMD_PIPE_INDEX, num_cmd_desc);
1794 }
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001795
1796 qpic_nand_wait_for_data(DATA_PRODUCER_PIPE_INDEX);
1797
Channagoud Kadabib1dc47c2015-05-21 17:02:44 -07001798 /* Check flash read status & errors */
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001799 for (i = 0; i < flash.cws_per_page ; i ++)
Sundarajan Srinivasan024bda52014-02-27 16:48:48 -08001800 {
Channagoud Kadabib1dc47c2015-05-21 17:02:44 -07001801#if DEBUG_QPIC_NAND
1802 dprintf(INFO, "FLASH STATUS: 0x%08x, BUFFER STATUS: 0x%08x, ERASED CW STATUS: 0x%08x\n",
1803 flash_sts[i], buffer_sts[i], erased_cw_sts[i]);
1804#endif
1805
1806 /* If MPU or flash op erros are set, look for erased cw status.
1807 * If erased CW status is not set then look for bit flips to confirm
1808 * if the page is and erased page or a bad page
1809 */
1810 if (flash_sts[i] & (NAND_FLASH_OP_ERR | NAND_FLASH_MPU_ERR))
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001811 {
Channagoud Kadabib1dc47c2015-05-21 17:02:44 -07001812 if ((erased_cw_sts[i] & NAND_ERASED_CW) != NAND_ERASED_CW)
1813 {
1814#if DEBUG_QPIC_NAND
1815 dprintf(CRITICAL, "Page: 0x%08x, addr0: 0x%08x, addr1: 0x%08x\n", page, params.addr0, params.addr1);
1816#endif
1817 /*
1818 * Depending on the process technology used there could be bit flips on
1819 * pages on the NAND card
1820 * When any page is erased the controller fills the page with all 1's.
1821 * When we try to read from an erased page and there are bit flips the
1822 * controller would not detect the page as erased page instead throws
1823 * an uncorrectable ecc error.
1824 * The NAND data sheet for that card would specify the number of bit flips
1825 * expected per code word. If the number of bit flips is less than expected
1826 * bit flips then we should ignore the uncorrectable ECC error and consider
1827 * the page as an erased page.
1828 */
1829#if DEBUG_QPIC_NAND
1830 for(i = 0; i < 4096; i += 8)
1831 {
1832 printf("DATA: %x %x %x %x %x %x %x %x",
1833 buffer_temp[i], buffer_temp[i+1], buffer_temp[i+2], buffer_temp[i+3],
1834 buffer_temp[i+4], buffer_temp[i+5], buffer_temp[i+6], buffer_temp[i+7]);
1835 i += 8;
1836 printf("DATA: %x %x %x %x %x %x %x %x\n",
1837 buffer_temp[i], buffer_temp[i+1], buffer_temp[i+2], buffer_temp[i+3],
1838 buffer_temp[i+4], buffer_temp[i+5], buffer_temp[i+6], buffer_temp[i+7]);
1839 }
1840#endif
1841 nand_ret = qpic_nand_read_erased_page(page);
1842 goto qpic_nand_read_page_error;
1843 }
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001844 }
Sundarajan Srinivasan024bda52014-02-27 16:48:48 -08001845 }
Channagoud Kadabib1dc47c2015-05-21 17:02:44 -07001846
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001847qpic_nand_read_page_error:
Channagoud Kadabib1dc47c2015-05-21 17:02:44 -07001848 return nand_ret;
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001849}
1850
Tanya Brokhman72b44dc2015-01-07 10:20:05 +02001851/**
1852 * qpic_nand_read() - read data
1853 * @start_page: number of page to begin reading from
1854 * @num_pages: number of pages to read
1855 * @buffer: buffer where to store the read data
1856 * @spareaddr: buffer where to store spare data.
1857 * If null, spare data wont be read
1858 *
1859 * This function reads @num_pages starting from @start_page and stores the
1860 * read data in buffer. Note that it's in the caller responsibility to make
1861 * sure the read pages are all from same partition.
1862 *
1863 * Returns nand_result_t
1864 */
1865nand_result_t qpic_nand_read(uint32_t start_page, uint32_t num_pages,
1866 unsigned char* buffer, unsigned char* spareaddr)
1867{
1868 unsigned i = 0, ret = 0;
1869
1870 if (!buffer) {
1871 dprintf(CRITICAL, "qpic_nand_read: buffer = null\n");
1872 return NANDC_RESULT_PARAM_INVALID;
1873 }
1874 while (i < num_pages) {
1875 ret = qpic_nand_read_page(start_page + i, buffer + flash.page_size * i,
1876 spareaddr);
1877 i++;
1878 if (ret == NANDC_RESULT_BAD_PAGE)
1879 qpic_nand_mark_badblock(start_page + i);
1880 if (ret) {
1881 dprintf(CRITICAL,
1882 "qpic_nand_read: reading page %d failed with %d err\n",
1883 start_page + i, ret);
1884 return ret;
1885 }
1886 }
1887 return NANDC_RESULT_SUCCESS;
1888}
1889
1890/**
1891 * qpic_nand_write() - read data
1892 * @start_page: number of page to begin writing to
1893 * @num_pages: number of pages to write
1894 * @buffer: buffer to be written
1895 * @write_extra_bytes: true if spare data (ox 0xff) to be written
1896 *
1897 * This function writes @num_pages starting from @start_page. Note that it's
1898 * in the caller responsibility to make sure the written pages are all from
1899 * same partition.
1900 *
1901 * Returns nand_result_t
1902 */
1903nand_result_t qpic_nand_write(uint32_t start_page, uint32_t num_pages,
1904 unsigned char* buffer, unsigned write_extra_bytes)
1905{
1906 int i = 0, ret = NANDC_RESULT_SUCCESS;
1907 uint32_t *spare = (unsigned *)flash_spare_bytes;
1908 uint32_t wsize;
1909 uint32_t spare_byte_count = 0;
1910
1911 if (!buffer) {
1912 dprintf(CRITICAL, "qpic_nand_write: buffer = null\n");
1913 return NANDC_RESULT_PARAM_INVALID;
1914 }
1915 spare_byte_count = ((flash.cw_size * flash.cws_per_page)- flash.page_size);
1916
1917 if (write_extra_bytes)
1918 wsize = flash.page_size + spare_byte_count;
1919 else
1920 wsize = flash.page_size;
1921
1922 memset(spare, 0xff, (spare_byte_count / flash.cws_per_page));
1923
1924 for (i = 0; i < (int)num_pages; i++) {
1925 memcpy(rdwr_buf, buffer, flash.page_size);
1926 if (write_extra_bytes) {
1927 memcpy(rdwr_buf + flash.page_size,
1928 buffer + flash.page_size, spare_byte_count);
1929 ret = qpic_nand_write_page(start_page + i,
1930 NAND_CFG, rdwr_buf, rdwr_buf + flash.page_size);
1931 } else {
1932 ret = qpic_nand_write_page(start_page + i,
1933 NAND_CFG, rdwr_buf, spare);
1934 }
1935 if (ret) {
1936 dprintf(CRITICAL,
1937 "flash_write: write failure @ page %d, block %d\n",
1938 start_page + i,
1939 (start_page + i) / flash.num_pages_per_blk);
1940 if (ret == NANDC_RESULT_BAD_PAGE)
1941 qpic_nand_mark_badblock(start_page + i);
1942 goto out;
1943 }
1944 buffer += wsize;
1945 }
1946out:
1947 return ret;
1948}
1949
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001950/* Function to read a flash partition.
1951 * ptn : Partition to read.
1952 * extra_per_page : Spare data to be read.
1953 * offset : Num of bytes offset into the partition.
1954 * data : Buffer to read the data into.
1955 * bytes : Num of bytes to be read.
1956 */
1957 /* TODO: call this func read_partition. */
1958int
1959flash_read_ext(struct ptentry *ptn,
1960 unsigned extra_per_page,
1961 unsigned offset,
1962 void *data,
1963 unsigned bytes)
1964{
1965 uint32_t page =
1966 (ptn->start * flash.num_pages_per_blk) + (offset / flash.page_size);
1967 uint32_t lastpage = (ptn->start + ptn->length) * flash.num_pages_per_blk;
1968 uint32_t count =
1969 (bytes + flash.page_size - 1 + extra_per_page) / (flash.page_size +
1970 extra_per_page);
1971 uint32_t *spare = (unsigned *)flash_spare_bytes;
1972 uint32_t errors = 0;
1973 unsigned char *image = data;
1974 int result = 0;
1975 uint32_t current_block =
1976 (page - (page & flash.num_pages_per_blk_mask)) / flash.num_pages_per_blk;
1977 uint32_t start_block = ptn->start;
1978 uint32_t start_block_count = 0;
1979 uint32_t isbad = 0;
Deepa Dinamani2f7006c2013-08-19 11:59:38 -07001980 uint32_t current_page;
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001981
1982 /* Verify first byte is at page boundary. */
1983 if (offset & (flash.page_size - 1))
1984 {
1985 dprintf(CRITICAL, "Read request start not at page boundary: %d\n",
1986 offset);
1987 return NANDC_RESULT_PARAM_INVALID;
1988 }
1989
Deepa Dinamani2f7006c2013-08-19 11:59:38 -07001990 current_page = start_block * flash.num_pages_per_blk;
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001991 /* Adjust page offset based on number of bad blocks from start to current page */
1992 if (start_block < current_block)
1993 {
1994 start_block_count = (current_block - start_block);
1995 while (start_block_count
1996 && (start_block < (ptn->start + ptn->length)))
1997 {
Deepa Dinamani2f7006c2013-08-19 11:59:38 -07001998 isbad = qpic_nand_block_isbad(current_page);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001999 if (isbad)
2000 page += flash.num_pages_per_blk;
2001 else
2002 start_block_count--;
2003 start_block++;
Deepa Dinamani2f7006c2013-08-19 11:59:38 -07002004 current_page += flash.num_pages_per_blk;
Deepa Dinamanie4573be2012-08-03 16:32:29 -07002005 }
2006 }
2007
2008 while ((page < lastpage) && !start_block_count)
2009 {
2010 if (count == 0)
2011 {
Deepa Dinamani52aca8d2013-02-05 11:41:41 -08002012 dprintf(SPEW, "flash_read_image: success (%d errors)\n",
Deepa Dinamanie4573be2012-08-03 16:32:29 -07002013 errors);
2014 return NANDC_RESULT_SUCCESS;
2015 }
2016
Sundarajan Srinivasan29d927c2014-02-10 14:11:24 -08002017#if CONTIGUOUS_MEMORY
2018 result = qpic_nand_read_page(page, image, (unsigned char *) spare);
2019#else
2020 result = qpic_nand_read_page(page, rdwr_buf, (unsigned char *) spare);
2021#endif
Deepa Dinamanie4573be2012-08-03 16:32:29 -07002022 if (result == NANDC_RESULT_BAD_PAGE)
2023 {
2024 /* bad page, go to next page. */
2025 page++;
2026 errors++;
2027 continue;
2028 }
2029 else if (result == NANDC_RESULT_BAD_BLOCK)
2030 {
2031 /* bad block, go to next block same offset. */
2032 page += flash.num_pages_per_blk;
2033 errors++;
2034 continue;
2035 }
2036
Sundarajan Srinivasan29d927c2014-02-10 14:11:24 -08002037#ifndef CONTIGUOUS_MEMORY
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07002038 /* Copy the read page into correct location. */
2039 memcpy(image, rdwr_buf, flash.page_size);
Sundarajan Srinivasan29d927c2014-02-10 14:11:24 -08002040#endif
Deepa Dinamanie4573be2012-08-03 16:32:29 -07002041 page++;
2042 image += flash.page_size;
2043 /* Copy spare bytes to image */
Sundarajan Srinivasan29d927c2014-02-10 14:11:24 -08002044 if(extra_per_page)
2045 {
2046 memcpy(image, spare, extra_per_page);
2047 image += extra_per_page;
2048 }
2049
Deepa Dinamanie4573be2012-08-03 16:32:29 -07002050 count -= 1;
2051 }
2052
2053 /* could not find enough valid pages before we hit the end */
2054 dprintf(CRITICAL, "flash_read_image: failed (%d errors)\n", errors);
2055 return NANDC_RESULT_FAILURE;
2056}
2057
2058int
2059flash_erase(struct ptentry *ptn)
2060{
Tanya Brokhman646eedb2015-01-06 23:09:54 +02002061 int ret = 0, i;
Deepa Dinamani2467bbb2012-10-02 13:59:58 -07002062
Tanya Brokhman646eedb2015-01-06 23:09:54 +02002063 for (i = 0; i < (int)ptn->length; i++) {
2064 ret = qpic_nand_blk_erase((ptn->start + i) * flash.num_pages_per_blk);
2065 if (ret)
2066 dprintf(CRITICAL, "Erase operation failed @ page #%d\n",
2067 ptn->start + i);
2068 }
Mayank Groverff7de6b2018-05-24 13:41:03 +05302069 return NANDC_RESULT_SUCCESS;
Deepa Dinamanie4573be2012-08-03 16:32:29 -07002070}
Deepa Dinamani2467bbb2012-10-02 13:59:58 -07002071
Deepa Dinamanie4573be2012-08-03 16:32:29 -07002072int
2073flash_ecc_bch_enabled()
2074{
2075 return (flash.ecc_width == NAND_WITH_4_BIT_ECC)? 0 : 1;
2076}
2077
2078int
2079flash_write(struct ptentry *ptn,
Deepa Dinamanic13d5942013-04-30 15:48:53 -07002080 unsigned write_extra_bytes,
Deepa Dinamanie4573be2012-08-03 16:32:29 -07002081 const void *data,
2082 unsigned bytes)
2083{
2084 uint32_t page = ptn->start * flash.num_pages_per_blk;
2085 uint32_t lastpage = (ptn->start + ptn->length) * flash.num_pages_per_blk;
2086 uint32_t *spare = (unsigned *)flash_spare_bytes;
2087 const unsigned char *image = data;
Deepa Dinamanic13d5942013-04-30 15:48:53 -07002088 uint32_t wsize;
Sundarajan Srinivasan223d7002014-02-11 19:48:11 -08002089 uint32_t spare_byte_count = 0;
Deepa Dinamanie4573be2012-08-03 16:32:29 -07002090 int r;
2091
Sundarajan Srinivasan223d7002014-02-11 19:48:11 -08002092 spare_byte_count = ((flash.cw_size * flash.cws_per_page)- flash.page_size);
2093
Deepa Dinamanic13d5942013-04-30 15:48:53 -07002094 if(write_extra_bytes)
Sundarajan Srinivasan223d7002014-02-11 19:48:11 -08002095 wsize = flash.page_size + spare_byte_count;
Deepa Dinamanic13d5942013-04-30 15:48:53 -07002096 else
2097 wsize = flash.page_size;
2098
Sundarajan Srinivasan223d7002014-02-11 19:48:11 -08002099 memset(spare, 0xff, (spare_byte_count / flash.cws_per_page));
Deepa Dinamanie4573be2012-08-03 16:32:29 -07002100
2101 while (bytes > 0)
2102 {
2103 if (bytes < wsize)
2104 {
2105 dprintf(CRITICAL,
2106 "flash_write_image: image undersized (%d < %d)\n",
2107 bytes,
2108 wsize);
2109 return -1;
2110 }
2111
2112 if (page >= lastpage)
2113 {
2114 dprintf(CRITICAL, "flash_write_image: out of space\n");
2115 return -1;
2116 }
2117
2118 if ((page & flash.num_pages_per_blk_mask) == 0)
2119 {
Deepa Dinamani2467bbb2012-10-02 13:59:58 -07002120 if (qpic_nand_blk_erase(page))
Deepa Dinamanie4573be2012-08-03 16:32:29 -07002121 {
2122 dprintf(INFO,
2123 "flash_write_image: bad block @ %d\n",
2124 page / flash.num_pages_per_blk);
2125
2126 page += flash.num_pages_per_blk;
2127 continue;
2128 }
2129 }
2130
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07002131 memcpy(rdwr_buf, image, flash.page_size);
2132
Deepa Dinamanic13d5942013-04-30 15:48:53 -07002133 if (write_extra_bytes)
Deepa Dinamanie4573be2012-08-03 16:32:29 -07002134 {
Sundarajan Srinivasan223d7002014-02-11 19:48:11 -08002135 memcpy(rdwr_buf + flash.page_size, image + flash.page_size, spare_byte_count);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07002136 r = qpic_nand_write_page(page,
2137 NAND_CFG,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07002138 rdwr_buf,
2139 rdwr_buf + flash.page_size);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07002140 }
2141 else
2142 {
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07002143 r = qpic_nand_write_page(page, NAND_CFG, rdwr_buf, spare);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07002144 }
2145
2146 if (r)
2147 {
2148 dprintf(INFO,
2149 "flash_write_image: write failure @ page %d (src %d)\n",
2150 page,
2151 image - (const unsigned char *)data);
2152
2153 image -= (page & flash.num_pages_per_blk_mask) * wsize;
2154 bytes += (page & flash.num_pages_per_blk_mask) * wsize;
2155 page &= ~flash.num_pages_per_blk_mask;
2156 if (qpic_nand_blk_erase(page))
2157 {
2158 dprintf(INFO,
2159 "flash_write_image: erase failure @ page %d\n",
2160 page);
2161 }
2162
2163 qpic_nand_mark_badblock(page);
2164
2165 dprintf(INFO,
2166 "flash_write_image: restart write @ page %d (src %d)\n",
2167 page, image - (const unsigned char *)data);
2168
2169 page += flash.num_pages_per_blk;
2170 continue;
2171 }
2172 page++;
2173 image += wsize;
2174 bytes -= wsize;
2175 }
2176
2177 /* erase any remaining pages in the partition */
2178 page = (page + flash.num_pages_per_blk_mask) & (~flash.num_pages_per_blk_mask);
2179
2180 while (page < lastpage)
2181 {
2182 if (qpic_nand_blk_erase(page))
2183 {
2184 dprintf(INFO, "flash_write_image: bad block @ %d\n",
2185 page / flash.num_pages_per_blk);
2186 }
2187 page += flash.num_pages_per_blk;
2188 }
2189
2190 dprintf(INFO, "flash_write_image: success\n");
2191 return 0;
2192}
Smita Ghoshf5431c62014-09-18 14:11:14 -07002193
2194uint32_t nand_device_base()
2195{
2196 return nand_base;
2197}