blob: 91d081555be308d1f24b6f155973164403c04c5f [file] [log] [blame]
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001/*
2 * Copyright (c) 2008, Google Inc.
3 * All rights reserved.
Joonwoo Park342b2362014-08-25 15:41:39 -07004 * Copyright (c) 2009-2014, The Linux Foundation. All rights reserved.
Deepa Dinamanie4573be2012-08-03 16:32:29 -07005 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in
12 * the documentation and/or other materials provided with the
13 * distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29#include <qpic_nand.h>
30#include <bam.h>
31#include <dev/flash.h>
32#include <lib/ptable.h>
33#include <debug.h>
34#include <string.h>
35#include <malloc.h>
36#include <sys/types.h>
Deepa Dinamani0bf2f442012-10-19 11:41:06 -070037#include <platform.h>
Amol Jadib726c3b2012-09-13 13:51:23 -070038#include <platform/clock.h>
Smita Ghoshf5431c62014-09-18 14:11:14 -070039#include <platform/iomap.h>
Deepa Dinamanie4573be2012-08-03 16:32:29 -070040
41static uint32_t nand_base;
42static struct ptable *flash_ptable;
43static struct flash_info flash;
44static unsigned char *flash_spare_bytes;
45static uint32_t cfg0;
46static uint32_t cfg1;
47static uint32_t cfg0_raw;
48static uint32_t cfg1_raw;
49static uint32_t ecc_bch_cfg;
50
Sridhar Parasuramf5188d82014-11-17 15:39:55 -080051struct cmd_element ce_array[100] __attribute__ ((aligned(16)));
52struct cmd_element ce_read_array[20] __attribute__ ((aligned(16)));
Deepa Dinamanie4573be2012-08-03 16:32:29 -070053
54#define QPIC_BAM_DATA_FIFO_SIZE 64
55#define QPIC_BAM_CMD_FIFO_SIZE 64
56
57static struct bam_desc cmd_desc_fifo[QPIC_BAM_CMD_FIFO_SIZE] __attribute__ ((aligned(BAM_DESC_SIZE)));
58static struct bam_desc data_desc_fifo[QPIC_BAM_DATA_FIFO_SIZE] __attribute__ ((aligned(BAM_DESC_SIZE)));
59
60static struct bam_instance bam;
61static uint8_t *bbtbl;
62
Deepa Dinamani0bf2f442012-10-19 11:41:06 -070063static uint8_t* rdwr_buf;
64
Deepa Dinamanie4573be2012-08-03 16:32:29 -070065static struct flash_id supported_flash[] = {
Deepa Dinamani649a94a2013-03-07 14:37:31 -080066 /* Flash ID ID Mask Density(MB) Wid Pgsz Blksz oobsz 8-bit ECCf */
67 {0x1590AC2C, 0xFFFFFFFF, 0x20000000, 0, 2048, 0x00020000, 0x40, 0},
Sundarajan Srinivasand4e21952013-08-27 15:59:10 -070068 {0x1590AA2C, 0xFFFFFFFF, 0x10000000, 0, 2048, 0x00020000, 0xE0, 1},
Deepa Dinamani649a94a2013-03-07 14:37:31 -080069 {0x2690AC2C, 0xFFFFFFFF, 0x20000000, 0, 4096, 0x00040000, 0xE0, 1},
Sundarajan Srinivasand69c0d32013-08-09 16:47:33 -070070 {0x1590ACAD, 0xFFFFFFFF, 0x20000000, 0, 2048, 0x00020000, 0x80, 0},
Joonwoo Park342b2362014-08-25 15:41:39 -070071 {0x9590DC2C, 0xFFFFFFFF, 0x10000000, 0, 2048, 0x00020000, 0x40, 0},
Channagoud Kadabi12b96932014-09-23 15:18:11 -070072 {0x1590aa98, 0xFFFFFFFF, 0x10000000, 0, 2048, 0x00020000, 0x80, 1},
Deepa Dinamanie4573be2012-08-03 16:32:29 -070073 /* Note: Width flag is 0 for 8 bit Flash and 1 for 16 bit flash */
Deepa Dinamanie4573be2012-08-03 16:32:29 -070074};
75
Tanya Brokhman72b44dc2015-01-07 10:20:05 +020076static int qpic_nand_mark_badblock(uint32_t page);
77
Deepa Dinamanie4573be2012-08-03 16:32:29 -070078static void
79qpic_nand_wait_for_cmd_exec(uint32_t num_desc)
80{
81 /* Create a read/write event to notify the periperal of the added desc. */
82 bam_sys_gen_event(&bam, CMD_PIPE_INDEX, num_desc);
83
84 /* Wait for the descriptors to be processed */
85 bam_wait_for_interrupt(&bam, CMD_PIPE_INDEX, P_PRCSD_DESC_EN_MASK);
86
87 /* Read offset update for the circular FIFO */
88 bam_read_offset_update(&bam, CMD_PIPE_INDEX);
89}
90
91static void
92qpic_nand_wait_for_data(uint32_t pipe_num)
93{
94 /* Wait for the descriptors to be processed */
95 bam_wait_for_interrupt(&bam, pipe_num, P_PRCSD_DESC_EN_MASK);
96
97 /* Read offset update for the circular FIFO */
98 bam_read_offset_update(&bam, pipe_num);
99}
100
101static uint32_t
102qpic_nand_read_reg(uint32_t reg_addr,
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800103 uint8_t flags)
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700104{
105 uint32_t val;
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800106 struct cmd_element *cmd_list_read_ptr = ce_read_array;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700107
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800108 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 -0700109
110 /* Enqueue the desc for the above command */
111 bam_add_one_desc(&bam,
112 CMD_PIPE_INDEX,
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800113 (unsigned char*)PA((addr_t)cmd_list_read_ptr),
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700114 BAM_CE_SIZE,
115 BAM_DESC_CMD_FLAG| BAM_DESC_INT_FLAG | flags);
116
117 qpic_nand_wait_for_cmd_exec(1);
118
119 return val;
120}
121
Deepa Dinamani19530062012-10-03 14:43:05 -0700122/* Assume the BAM is in a locked state. */
123void
sundarajan srinivasan7ced6482013-03-21 16:01:18 -0700124qpic_nand_erased_status_reset(struct cmd_element *cmd_list_ptr, uint8_t flags)
Deepa Dinamani19530062012-10-03 14:43:05 -0700125{
126 uint32_t val = 0;
127
128 /* Reset the Erased Codeword/Page detection controller. */
129 val = NAND_ERASED_CW_DETECT_CFG_RESET_CTRL;
130
131 bam_add_cmd_element(cmd_list_ptr, NAND_ERASED_CW_DETECT_CFG, val, CE_WRITE_TYPE);
132
133 /* Enqueue the desc for the above command */
134 bam_add_one_desc(&bam,
135 CMD_PIPE_INDEX,
136 (unsigned char*)cmd_list_ptr,
137 BAM_CE_SIZE,
sundarajan srinivasan7ced6482013-03-21 16:01:18 -0700138 BAM_DESC_CMD_FLAG | BAM_DESC_INT_FLAG | flags);
Deepa Dinamani19530062012-10-03 14:43:05 -0700139
140 qpic_nand_wait_for_cmd_exec(1);
141
142 /* Enable the Erased Codeword/Page detection
143 * controller to check the data as it arrives.
144 * Also disable ECC reporting for an erased CW.
145 */
146 val = NAND_ERASED_CW_DETECT_CFG_ACTIVATE_CTRL | NAND_ERASED_CW_DETECT_ERASED_CW_ECC_MASK;
147
148 bam_add_cmd_element(cmd_list_ptr, NAND_ERASED_CW_DETECT_CFG, val, CE_WRITE_TYPE);
149
150 /* Enqueue the desc for the above command */
151 bam_add_one_desc(&bam,
152 CMD_PIPE_INDEX,
153 (unsigned char*)cmd_list_ptr,
154 BAM_CE_SIZE,
155 BAM_DESC_CMD_FLAG | BAM_DESC_INT_FLAG);
156
157 qpic_nand_wait_for_cmd_exec(1);
158}
159
160static nand_result_t
161qpic_nand_check_status(uint32_t status)
162{
163 uint32_t erase_sts;
164
165 /* Check for errors */
166 if (status & NAND_FLASH_ERR)
167 {
168 /* Check if this is an ECC error on an erased page. */
169 if (status & NAND_FLASH_OP_ERR)
170 {
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800171 erase_sts = qpic_nand_read_reg(NAND_ERASED_CW_DETECT_STATUS, 0);
Deepa Dinamani19530062012-10-03 14:43:05 -0700172 if ((erase_sts & (1 << NAND_ERASED_CW_DETECT_STATUS_PAGE_ALL_ERASED)))
173 {
174 /* Mask the OP ERROR. */
175 status &= ~NAND_FLASH_OP_ERR;
sundarajan srinivasan7ced6482013-03-21 16:01:18 -0700176 qpic_nand_erased_status_reset(ce_array, 0);
Deepa Dinamani19530062012-10-03 14:43:05 -0700177 }
178 }
179
180 /* ECC error flagged on an erased page read.
181 * Ignore and return success.
182 */
183 if (!(status & NAND_FLASH_ERR))
184 return NANDC_RESULT_SUCCESS;
185
186 dprintf(CRITICAL, "Nand Flash error. Status = %d\n", status);
187
188 if (status & NAND_FLASH_TIMEOUT_ERR)
189 return NANDC_RESULT_TIMEOUT;
190 else
191 return NANDC_RESULT_FAILURE;
192 }
193
194 return NANDC_RESULT_SUCCESS;
195}
196
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700197static uint32_t
198qpic_nand_fetch_id(struct flash_info *flash)
199{
200 struct cmd_element *cmd_list_ptr = ce_array;
201 struct cmd_element *cmd_list_ptr_start = ce_array;
202 int num_desc = 0;
203 uint32_t status;
204 uint32_t id;
205 uint32_t flash_cmd = NAND_CMD_FETCH_ID;
206 uint32_t exec_cmd = 1;
207 int nand_ret = NANDC_RESULT_SUCCESS;
208
209 /* Issue the Fetch id command to the NANDc */
210 bam_add_cmd_element(cmd_list_ptr, NAND_FLASH_CMD, (uint32_t)flash_cmd, CE_WRITE_TYPE);
211 cmd_list_ptr++;
212
213 /* Execute the cmd */
214 bam_add_cmd_element(cmd_list_ptr, NAND_EXEC_CMD, (uint32_t)exec_cmd, CE_WRITE_TYPE);
215 cmd_list_ptr++;
216
217 /* Prepare the cmd desc for the above commands */
218 bam_add_one_desc(&bam,
219 CMD_PIPE_INDEX,
220 (unsigned char*)cmd_list_ptr_start,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -0700221 PA((uint32_t)cmd_list_ptr - (uint32_t)cmd_list_ptr_start),
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700222 BAM_DESC_LOCK_FLAG | BAM_DESC_INT_FLAG |
223 BAM_DESC_NWD_FLAG | BAM_DESC_CMD_FLAG);
224
225 /* Keep track of the number of desc added. */
226 num_desc++;
227 qpic_nand_wait_for_cmd_exec(num_desc);
228
229 cmd_list_ptr_start = ce_array;
230 cmd_list_ptr = ce_array;
231
232 /* Read the status register */
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800233 status = qpic_nand_read_reg(NAND_FLASH_STATUS, 0);
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700234
235 /* Check for errors */
236 nand_ret = qpic_nand_check_status(status);
237 if (nand_ret)
238 {
239 dprintf( CRITICAL, "Read ID cmd status failed\n");
240 goto qpic_nand_fetch_id_err;
241 }
242
243 /* Read the id */
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800244 id = qpic_nand_read_reg(NAND_READ_ID, BAM_DESC_UNLOCK_FLAG);
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700245
246 flash->id = id;
247 flash->vendor = id & 0xff;
248 flash->device = (id >> 8) & 0xff;
249 flash->dev_cfg = (id >> 24) & 0xFF;
250 flash->widebus = 0;
251 flash->widebus &= (id >> 24) & 0xFF;
252 flash->widebus = flash->widebus? 1: 0;
253
254qpic_nand_fetch_id_err:
255 return nand_ret;
256}
257
258static int
Deepa Dinamanie9ded132012-11-27 15:03:38 -0800259qpic_bam_init(struct qpic_nand_init_config *config)
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700260{
261 uint32_t bam_ret = NANDC_RESULT_SUCCESS;
262
Deepa Dinamanie9ded132012-11-27 15:03:38 -0800263 bam.base = config->bam_base;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700264 /* Set Read pipe params. */
Deepa Dinamanie9ded132012-11-27 15:03:38 -0800265 bam.pipe[DATA_PRODUCER_PIPE_INDEX].pipe_num = config->pipes.read_pipe;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700266 /* System consumer */
267 bam.pipe[DATA_PRODUCER_PIPE_INDEX].trans_type = BAM2SYS;
268 bam.pipe[DATA_PRODUCER_PIPE_INDEX].fifo.size = QPIC_BAM_DATA_FIFO_SIZE;
269 bam.pipe[DATA_PRODUCER_PIPE_INDEX].fifo.head = data_desc_fifo;
Deepa Dinamani536d3f82013-07-09 13:05:56 -0700270 bam.pipe[DATA_PRODUCER_PIPE_INDEX].lock_grp = config->pipes.read_pipe_grp;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700271
272 /* Set Write pipe params. */
Deepa Dinamanie9ded132012-11-27 15:03:38 -0800273 bam.pipe[DATA_CONSUMER_PIPE_INDEX].pipe_num = config->pipes.write_pipe;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700274 /* System producer */
275 bam.pipe[DATA_CONSUMER_PIPE_INDEX].trans_type = SYS2BAM;
276 bam.pipe[DATA_CONSUMER_PIPE_INDEX].fifo.size = QPIC_BAM_DATA_FIFO_SIZE;
277 bam.pipe[DATA_CONSUMER_PIPE_INDEX].fifo.head = data_desc_fifo;
Deepa Dinamani536d3f82013-07-09 13:05:56 -0700278 bam.pipe[DATA_CONSUMER_PIPE_INDEX].lock_grp = config->pipes.write_pipe_grp;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700279
280 /* Set Cmd pipe params. */
Deepa Dinamanie9ded132012-11-27 15:03:38 -0800281 bam.pipe[CMD_PIPE_INDEX].pipe_num = config->pipes.cmd_pipe;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700282 /* System consumer */
Sundarajan Srinivasan357c35a2013-07-23 17:00:54 -0700283 bam.pipe[CMD_PIPE_INDEX].trans_type = SYS2BAM;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700284 bam.pipe[CMD_PIPE_INDEX].fifo.size = QPIC_BAM_CMD_FIFO_SIZE;
285 bam.pipe[CMD_PIPE_INDEX].fifo.head = cmd_desc_fifo;
Deepa Dinamani536d3f82013-07-09 13:05:56 -0700286 bam.pipe[CMD_PIPE_INDEX].lock_grp = config->pipes.cmd_pipe_grp;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700287
288 /* Programs the threshold for BAM transfer
289 * When this threshold is reached, BAM signals the peripheral via the pipe_bytes_available
290 * interface.
291 * The peripheral is signalled with this notification in the following cases:
292 * a. It has accumulated all the descriptors.
293 * b. It has accumulated more than threshold bytes.
294 * c. It has reached EOT (End Of Transfer).
295 * Note: this value needs to be set by the h/w folks and is specific for each peripheral.
296 */
297 bam.threshold = 32;
298
Deepa Dinamanie9ded132012-11-27 15:03:38 -0800299 /* Set the EE. */
300 bam.ee = config->ee;
301
302 /* Set the max desc length for this BAM. */
303 bam.max_desc_len = config->max_desc_len;
304
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700305 /* BAM Init. */
306 bam_init(&bam);
307
308 /* Initialize BAM QPIC read pipe */
309 bam_sys_pipe_init(&bam, DATA_PRODUCER_PIPE_INDEX);
310
311 /* Init read fifo */
312 bam_ret = bam_pipe_fifo_init(&bam, bam.pipe[DATA_PRODUCER_PIPE_INDEX].pipe_num);
313
314 if (bam_ret)
315 {
316 dprintf(CRITICAL, "QPIC:NANDc BAM Read FIFO init error\n");
317 bam_ret = NANDC_RESULT_FAILURE;
318 goto qpic_nand_bam_init_error;
319 }
320
321 /* Initialize BAM QPIC write pipe */
322 bam_sys_pipe_init(&bam, DATA_CONSUMER_PIPE_INDEX);
323
324 /* Init write fifo. Use the same fifo as read fifo. */
325 bam_ret = bam_pipe_fifo_init(&bam, bam.pipe[DATA_CONSUMER_PIPE_INDEX].pipe_num);
326
327 if (bam_ret)
328 {
329 dprintf(CRITICAL, "QPIC: NANDc: BAM Write FIFO init error\n");
330 bam_ret = NANDC_RESULT_FAILURE;
331 goto qpic_nand_bam_init_error;
332 }
333
334 /* Initialize BAM QPIC cmd pipe */
335 bam_sys_pipe_init(&bam, CMD_PIPE_INDEX);
336
337 /* Init cmd fifo */
338 bam_ret = bam_pipe_fifo_init(&bam, bam.pipe[CMD_PIPE_INDEX].pipe_num);
339
340 if (bam_ret)
341 {
342 dprintf(CRITICAL, "QPIC:NANDc BAM CMD FIFO init error\n");
343 bam_ret = NANDC_RESULT_FAILURE;
344 goto qpic_nand_bam_init_error;
345 }
346
347qpic_nand_bam_init_error:
348return bam_ret;
349}
350
351/* Adds command elements for addr and cfg register writes.
352 * cfg: Defines the configuration for the flash cmd.
353 * start: Address where the command elements are added.
354 *
355 * Returns the address where the next cmd element can be added.
356 */
357static struct cmd_element*
358qpic_nand_add_addr_n_cfg_ce(struct cfg_params *cfg,
359 struct cmd_element *start)
360{
361 struct cmd_element *cmd_list_ptr = start;
362
363 bam_add_cmd_element(cmd_list_ptr, NAND_ADDR0, (uint32_t)cfg->addr0, CE_WRITE_TYPE);
364 cmd_list_ptr++;
365 bam_add_cmd_element(cmd_list_ptr, NAND_ADDR1, (uint32_t)cfg->addr1, CE_WRITE_TYPE);
366 cmd_list_ptr++;
367 bam_add_cmd_element(cmd_list_ptr, NAND_DEV0_CFG0, (uint32_t)cfg->cfg0, CE_WRITE_TYPE);
368 cmd_list_ptr++;
369 bam_add_cmd_element(cmd_list_ptr, NAND_DEV0_CFG1, (uint32_t)cfg->cfg1, CE_WRITE_TYPE);
370 cmd_list_ptr++;
371
372 return cmd_list_ptr;
373}
374
375
376static struct cmd_element*
377qpic_nand_add_onfi_probe_ce(struct onfi_probe_params *params,
378 struct cmd_element *start)
379{
380 struct cmd_element *cmd_list_ptr = start;
381
382 cmd_list_ptr = qpic_nand_add_addr_n_cfg_ce(&params->cfg, cmd_list_ptr);
383
384 bam_add_cmd_element(cmd_list_ptr, NAND_DEV_CMD1, (uint32_t)params->dev_cmd1, CE_WRITE_TYPE);
385 cmd_list_ptr++;
386 bam_add_cmd_element(cmd_list_ptr, NAND_DEV_CMD_VLD, (uint32_t)params->vld, CE_WRITE_TYPE);
387 cmd_list_ptr++;
388 bam_add_cmd_element(cmd_list_ptr, NAND_READ_LOCATION_n(0), (uint32_t)params->cfg.addr_loc_0, CE_WRITE_TYPE);
389 cmd_list_ptr++;
390 bam_add_cmd_element(cmd_list_ptr, NAND_FLASH_CMD, (uint32_t)params->cfg.cmd, CE_WRITE_TYPE);
391 cmd_list_ptr++;
392 bam_add_cmd_element(cmd_list_ptr, NAND_EXEC_CMD, (uint32_t)params->cfg.exec, CE_WRITE_TYPE);
393 cmd_list_ptr++;
394
395 return cmd_list_ptr;
396}
397
398static int
399onfi_probe_cmd_exec(struct onfi_probe_params *params,
400 unsigned char* data_ptr,
401 int data_len)
402{
403 struct cmd_element *cmd_list_ptr = ce_array;
404 struct cmd_element *cmd_list_ptr_start = ce_array;
405 int num_desc = 0;
406 uint32_t status = 0;
407 int nand_ret = NANDC_RESULT_SUCCESS;
408 uint8_t desc_flags = BAM_DESC_NWD_FLAG | BAM_DESC_CMD_FLAG
409 | BAM_DESC_LOCK_FLAG | BAM_DESC_INT_FLAG;
410
411 params->cfg.addr_loc_0 = 0;
412 params->cfg.addr_loc_0 |= NAND_RD_LOC_LAST_BIT(1);
413 params->cfg.addr_loc_0 |= NAND_RD_LOC_OFFSET(0);
414 params->cfg.addr_loc_0 |= NAND_RD_LOC_SIZE(data_len);
415
416 cmd_list_ptr = qpic_nand_add_onfi_probe_ce(params, cmd_list_ptr);
417
418 /* Enqueue the desc for the above commands */
419 bam_add_one_desc(&bam,
420 CMD_PIPE_INDEX,
421 (unsigned char*)cmd_list_ptr_start,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -0700422 PA((addr_t)(uint32_t)cmd_list_ptr - (uint32_t)cmd_list_ptr_start),
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700423 desc_flags);
424
425 cmd_list_ptr_start = cmd_list_ptr;
426 num_desc++;
427
428 /* Add Data desc */
429 bam_add_desc(&bam,
430 DATA_PRODUCER_PIPE_INDEX,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -0700431 (unsigned char *)PA((addr_t)data_ptr),
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700432 data_len,
433 BAM_DESC_INT_FLAG);
434
435 /* Wait for the commands to be executed */
436 qpic_nand_wait_for_cmd_exec(num_desc);
437
438 /* Read buffer status and check for errors. */
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800439 status = qpic_nand_read_reg(NAND_FLASH_STATUS, 0);
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700440
441 if (qpic_nand_check_status(status))
442 {
443 nand_ret = NANDC_RESULT_FAILURE;
444 goto onfi_probe_exec_err;
445 }
446
447 /* Wait for data to be available */
448 qpic_nand_wait_for_data(DATA_PRODUCER_PIPE_INDEX);
449
450 /* Check for errors */
451 nand_ret = qpic_nand_check_status(status);
452
453onfi_probe_exec_err:
454 return nand_ret;
455}
456
457/* TODO: check why both vld and cmd need to be written. */
458void
459qpic_nand_onfi_probe_cleanup(uint32_t vld, uint32_t dev_cmd1)
460{
461 struct cmd_element *cmd_list_ptr = ce_array;
462 struct cmd_element *cmd_list_ptr_start = ce_array;
463
464 bam_add_cmd_element(cmd_list_ptr, NAND_DEV_CMD1, dev_cmd1, CE_WRITE_TYPE);
465 cmd_list_ptr++;
466 bam_add_cmd_element(cmd_list_ptr, NAND_DEV_CMD_VLD, vld, CE_WRITE_TYPE);
467 cmd_list_ptr++;
468
469 /* Enqueue the desc for the above commands */
470 bam_add_one_desc(&bam,
471 CMD_PIPE_INDEX,
472 (unsigned char*)cmd_list_ptr_start,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -0700473 PA((uint32_t)cmd_list_ptr - (uint32_t)cmd_list_ptr_start),
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700474 BAM_DESC_UNLOCK_FLAG | BAM_DESC_CMD_FLAG| BAM_DESC_INT_FLAG);
475
476 qpic_nand_wait_for_cmd_exec(1);
477}
478
479static int
480qpic_nand_onfi_save_params(struct onfi_param_page *param_page, struct flash_info *flash)
481{
482 int onfi_ret = NANDC_RESULT_SUCCESS;
483 uint32_t ecc_bits;
484
485 onfi_ret = qpic_nand_fetch_id(flash);
486
487 if (onfi_ret)
488 {
489 dprintf(CRITICAL, "Fetch ID cmd failed\n");
490 goto onfi_save_params_err;
491 }
492
493 flash->page_size = param_page->data_per_pg;
494 flash->block_size = param_page->pgs_per_blk * flash->page_size;
495 flash->num_blocks = param_page->blks_per_LUN;
496 flash->widebus = param_page->feature_supported & 0x1;
497 flash->density = param_page->blks_per_LUN * flash->blksize;
498 flash->spare_size = param_page->spare_per_pg;
499 ecc_bits = param_page->num_bits_ecc_correctability;
500 flash->num_pages_per_blk = param_page->pgs_per_blk;
501 flash->num_pages_per_blk_mask = param_page->pgs_per_blk - 1;
502
503 if (ecc_bits >= 8)
504 flash->ecc_width = NAND_WITH_8_BIT_ECC;
505 else
506 flash->ecc_width = NAND_WITH_4_BIT_ECC;
507
508 onfi_save_params_err:
509 return onfi_ret;
510}
511
512static void
513qpic_nand_save_config(struct flash_info *flash)
514{
515
516 /* Save Configurations */
517 flash->cws_per_page = flash->page_size >> NAND_CW_DIV_RIGHT_SHIFT;
518
Deepa Dinamani16663a62013-02-07 16:25:59 -0800519 /* Verify that we have enough buffer to handle all the cws in a page. */
520 ASSERT(flash->cws_per_page <= QPIC_NAND_MAX_CWS_IN_PAGE);
521
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700522 /* Codeword Size = UD_SIZE_BYTES + ECC_PARITY_SIZE_BYTES
523 * + SPARE_SIZE_BYTES + Bad Block size
524 */
525 if (flash->ecc_width & NAND_WITH_8_BIT_ECC)
526 {
527 flash->cw_size = NAND_CW_SIZE_8_BIT_ECC;
528 ecc_bch_cfg |= (1 << NAND_DEV0_ECC_MODE_SHIFT); /* Use 8-bit ecc */
529
530 if (flash->widebus)
531 {
532 cfg0 |= (0 << NAND_DEV0_CFG0_SPARE_SZ_BYTES_SHIFT); /* spare size bytes in each CW */
533 ecc_bch_cfg |= (14 << NAND_DEV0_ECC_PARITY_SZ_BYTES_SHIFT); /* parity bytes in each CW */
534 }
535 else
536 {
537 cfg0 |= (2 << NAND_DEV0_CFG0_SPARE_SZ_BYTES_SHIFT); /* spare size bytes in each CW */
538 ecc_bch_cfg |= (13 << NAND_DEV0_ECC_PARITY_SZ_BYTES_SHIFT); /* parity bytes in each CW */
539 }
540 }
541 else
542 {
543 flash->cw_size = NAND_CW_SIZE_4_BIT_ECC;
544
545 if (flash->widebus)
546 {
547 cfg0 |= (2 << NAND_DEV0_CFG0_SPARE_SZ_BYTES_SHIFT); /* spare size bytes in each CW */
548 ecc_bch_cfg |= (8 << NAND_DEV0_ECC_PARITY_SZ_BYTES_SHIFT); /* parity bytes in each CW */
549 }
550 else
551 {
552 cfg0 |= (4 << NAND_DEV0_CFG0_SPARE_SZ_BYTES_SHIFT); /* spare size bytes in each CW */
553 ecc_bch_cfg |= (7 << NAND_DEV0_ECC_PARITY_SZ_BYTES_SHIFT); /* parity bytes in each CW */
554 }
555 }
556
557 /* BAD_BLOCK_BYTE_NUM = Page Size -
558 * (CW_PER_PAGE * Codeword Size) + 1
559 * Note: Set CW_PER_PAGE to 1 less than the actual number.
560 */
561 flash->bad_blk_loc = flash->page_size - flash->cw_size * (flash->cws_per_page - 1) + 1;
562
563 cfg0 |= ((flash->cws_per_page - 1) << NAND_DEV0_CFG0_CW_PER_PAGE_SHIFT) /* 4/8 cw/pg for 2/4k */
564 |(DATA_BYTES_IN_IMG_PER_CW << NAND_DEV0_CFG0_UD_SIZE_BYTES_SHIFT) /* 516 user data bytes */
565 |(5 << NAND_DEV0_CFG0_ADDR_CYCLE_SHIFT) /* 5 address cycles */
566 |(0 << NAND_DEV0_CFG0_DIS_STS_AFTER_WR_SHIFT);/* Send read status cmd after each write. */
567
568 cfg1 |= (7 << NAND_DEV0_CFG1_RECOVERY_CYCLES_SHIFT) /* 8 recovery cycles */
569 |(0 << NAND_DEV0_CFG1_CS_ACTIVE_BSY_SHIFT) /* Allow CS deassertion */
570 |(flash->bad_blk_loc << NAND_DEV0_CFG1_BAD_BLK_BYTE_NUM_SHIFT)/* Bad block marker location */
571 |(0 << NAND_DEV0_CFG1_BAD_BLK_IN_SPARE_SHIFT) /* Bad block in user data area */
572 |(2 << NAND_DEV0_CFG1_WR_RD_BSY_GAP_SHIFT) /* 8 cycle tWB/tRB */
573 |(flash->widebus << NAND_DEV0_CFG1_WIDE_BUS_SHIFT); /* preserve wide flash flag */
574
575 cfg0_raw = ((flash->cws_per_page- 1) << NAND_DEV0_CFG0_CW_PER_PAGE_SHIFT)
576 |(5 << NAND_DEV0_CFG0_ADDR_CYCLE_SHIFT)
577 |(516 << NAND_DEV0_CFG0_UD_SIZE_BYTES_SHIFT) //figure out the size of cw
578 | (1 << NAND_DEV0_CFG0_DIS_STS_AFTER_WR_SHIFT);
579
580 cfg1_raw = (7 << NAND_DEV0_CFG1_RECOVERY_CYCLES_SHIFT)
581 | (0 << NAND_DEV0_CFG1_CS_ACTIVE_BSY_SHIFT)
582 | (17 << NAND_DEV0_CFG1_BAD_BLK_BYTE_NUM_SHIFT)
583 | (1 << NAND_DEV0_CFG1_BAD_BLK_IN_SPARE_SHIFT)
584 | (2 << NAND_DEV0_CFG1_WR_RD_BSY_GAP_SHIFT)
585 | (flash->widebus << NAND_DEV0_CFG1_WIDE_BUS_SHIFT)
586 |1 ; /* to disable reed solomon ecc..this feild is now read only. */
587
588 ecc_bch_cfg |= (0 << NAND_DEV0_ECC_DISABLE_SHIFT) /* Enable ECC */
589 | (0 << NAND_DEV0_ECC_SW_RESET_SHIFT) /* Put ECC core in op mode */
590 | (DATA_BYTES_IN_IMG_PER_CW << NAND_DEV0_ECC_NUM_DATA_BYTES)
591 | (1 << NAND_DEV0_ECC_FORCE_CLK_OPEN_SHIFT); /* Enable all clocks */
592}
593
594/* Onfi probe should issue the following commands to the flash device:
595 * 1. Read ID - with addr ONFI_READ_ID_ADDR.
596 * This returns the ONFI ASCII string indicating support for ONFI.
597 * 2. Read Prameter Page - with addr ONFI_READ_PARAM_PAGE_ADDR.
598 * This returns the params for the device.
599 * Each command inturn issues commands- ADDR0, ADDR1, chip_select,
600 * cfg0, cfg1, cmd_vld, dev_cmd1, read_loc0, flash, exec.
601 */
602static int
603qpic_nand_onfi_probe(struct flash_info *flash)
604{
605 struct onfi_probe_params params;
606 uint32_t vld;
607 uint32_t dev_cmd1;
608 unsigned char *buffer;
609 unsigned char onfi_str[4];
610 uint32_t *id;
611 struct onfi_param_page *param_page;
612 int onfi_ret = NANDC_RESULT_SUCCESS;
613
614 /* Allocate memory required to read the onfi param page */
615 buffer = (unsigned char*) malloc(ONFI_READ_PARAM_PAGE_BUFFER_SIZE);
Maria Yu71909742014-07-04 17:30:00 +0800616 ASSERT(buffer != NULL);
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700617
618 /* Read the vld and dev_cmd1 registers before modifying */
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800619 vld = qpic_nand_read_reg(NAND_DEV_CMD_VLD, 0);
620 dev_cmd1 = qpic_nand_read_reg(NAND_DEV_CMD1, 0);
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700621
622 /* Initialize flash cmd */
623 params.cfg.cmd = NAND_CMD_PAGE_READ;
624 params.cfg.exec = 1;
625
626 /* Execute Read ID cmd */
627
628 /* Initialize the config */
629 params.cfg.cfg0 = NAND_CFG0_RAW_ONFI_ID;
630 params.cfg.cfg1 = NAND_CFG1_RAW_ONFI_ID;
631
632 /* Initialize the cmd and vld */
633 params.dev_cmd1 = (dev_cmd1 & 0xFFFFFF00) | ONFI_READ_ID_CMD;
634 params.vld = vld & 0xFFFFFFFE;
635
636 /* Initialize the address
637 * addr1 is not used bcos of the cfg.
638 */
639 params.cfg.addr0 = ONFI_READ_ID_ADDR;
640 params.cfg.addr1 = 0;
641
642 /* Lock the pipe and execute the cmd. */
643 onfi_ret = onfi_probe_cmd_exec(&params, onfi_str, ONFI_READ_ID_BUFFER_SIZE);
644 if (onfi_ret)
645 {
646 dprintf(CRITICAL, "ONFI Read id cmd failed\n");
647 goto qpic_nand_onfi_probe_err;
648 }
649
650 /* Write back vld and cmd and unlock the pipe. */
651 qpic_nand_onfi_probe_cleanup(vld, dev_cmd1);
652
653 /* Check for onfi string */
654 id = (uint32_t*)onfi_str;
655 if (*id != ONFI_SIGNATURE)
656 {
657 dprintf(CRITICAL, "Not an ONFI device\n");
658 /* Not an onfi device. Return error. */
659 onfi_ret = NANDC_RESULT_DEV_NOT_SUPPORTED;
660 goto qpic_nand_onfi_probe_err;
661 }
662
663 dprintf(INFO, "ONFI device found\n");
664 /* Now read the param page */
665 /* Initialize the config */
666 params.cfg.cfg0 = NAND_CFG0_RAW_ONFI_PARAM_PAGE;
667 params.cfg.cfg1 = NAND_CFG1_RAW_ONFI_PARAM_PAGE;
668
669 /* Initialize the cmd and vld */
670 params.dev_cmd1 = (dev_cmd1 & 0xFFFFFF00) | ONFI_READ_PARAM_PAGE_CMD;
671 params.vld = vld & 0xFFFFFFFE;
672
673 /* Initialize the address
674 * addr1 is not used bcos of the cfg.
675 */
676 params.cfg.addr0 = ONFI_READ_PARAM_PAGE_ADDR;
677 params.cfg.addr1 = 0;
678
679 /* Lock the pipe and execute the cmd. */
680 onfi_ret = onfi_probe_cmd_exec(&params, buffer, ONFI_READ_PARAM_PAGE_BUFFER_SIZE);
681 if (onfi_ret)
682 {
683 dprintf(CRITICAL, "ONFI Read param page failed\n");
684 goto qpic_nand_onfi_probe_err;
685 }
686
687 /* Write back vld and cmd and unlock the pipe. */
688 qpic_nand_onfi_probe_cleanup(vld, dev_cmd1);
689
690 /* Verify the integrity of the returned page */
691 param_page = (struct onfi_param_page*)buffer;
692
693 /* TODO: Add CRC check to validate the param page. */
694
695 /* Save the parameter values */
696 onfi_ret = qpic_nand_onfi_save_params(param_page, flash);
697
698qpic_nand_onfi_probe_err:
699 if (onfi_ret)
700 dprintf(CRITICAL, "ONFI probe failed\n");
701
702 free(buffer);
703
704 return onfi_ret;
705}
706
707/* Enquues a desc for a flash cmd with NWD flag set:
708 * cfg: Defines the configuration for the flash cmd.
709 * start: Address where the command elements are added.
710 *
711 * Returns the address where the next cmd element can be added.
712 */
713struct cmd_element*
714qpic_nand_add_cmd_ce(struct cfg_params *cfg,
715 struct cmd_element *start)
716{
717 struct cmd_element *cmd_list_ptr;
718
719 cmd_list_ptr = qpic_nand_add_addr_n_cfg_ce(cfg, start);
720
721 bam_add_cmd_element(cmd_list_ptr, NAND_FLASH_CMD, (uint32_t)cfg->cmd, CE_WRITE_TYPE);
722 cmd_list_ptr++;
723
724 bam_add_cmd_element(cmd_list_ptr, NAND_EXEC_CMD, (uint32_t)cfg->exec, CE_WRITE_TYPE);
725 cmd_list_ptr++;
726
727 return cmd_list_ptr;
728}
729
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800730/* Reads nand_flash_status */
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700731struct cmd_element*
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800732qpic_nand_add_read_ce(struct cmd_element *start, uint32_t *flash_status_read)
733{
734 struct cmd_element *cmd_list_ptr = start;
735
736 bam_add_cmd_element(cmd_list_ptr, NAND_FLASH_STATUS, (uint32_t)PA((addr_t)flash_status_read), CE_READ_TYPE);
737 cmd_list_ptr++;
738
739 return cmd_list_ptr;
740}
741
742/* Resets nand_flash_status and nand_read_status */
743struct cmd_element*
744qpic_nand_reset_status_ce(struct cmd_element *start, uint32_t read_status)
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700745{
746 struct cmd_element *cmd_list_ptr = start;
747 uint32_t flash_status_reset;
748 uint32_t read_status_reset;
749
750 /* Read and reset the status registers. */
751 flash_status_reset = NAND_FLASH_STATUS_RESET;
752 read_status_reset = NAND_READ_STATUS_RESET;
753
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700754 bam_add_cmd_element(cmd_list_ptr, NAND_FLASH_STATUS, (uint32_t)flash_status_reset, CE_WRITE_TYPE);
755 cmd_list_ptr++;
756
757 if (read_status)
758 {
759 bam_add_cmd_element(cmd_list_ptr, NAND_READ_STATUS, (uint32_t)read_status_reset, CE_WRITE_TYPE);
760 cmd_list_ptr++;
761 }
762
763 return cmd_list_ptr;
764}
765
766struct cmd_element*
767qpic_nand_add_isbad_cmd_ce(struct cfg_params *cfg,
768 struct cmd_element *start)
769{
770 struct cmd_element *cmd_list_ptr = start;
771
772 bam_add_cmd_element(cmd_list_ptr, NAND_DEV0_ECC_CFG, (uint32_t)cfg->ecc_cfg, CE_WRITE_TYPE);
773 cmd_list_ptr++;
774
775 bam_add_cmd_element(cmd_list_ptr, NAND_READ_LOCATION_n(0), (uint32_t)cfg->addr_loc_0, CE_WRITE_TYPE);
776 cmd_list_ptr++;
777
778 cmd_list_ptr = qpic_nand_add_cmd_ce(cfg, cmd_list_ptr);
779
780 return cmd_list_ptr;
781}
782
783static int
784qpic_nand_block_isbad_exec(struct cfg_params *params,
785 uint8_t *bad_block)
786{
787
788 struct cmd_element *cmd_list_ptr = ce_array;
789 struct cmd_element *cmd_list_ptr_start = ce_array;
790 uint8_t desc_flags = BAM_DESC_NWD_FLAG | BAM_DESC_CMD_FLAG
791 | BAM_DESC_LOCK_FLAG | BAM_DESC_INT_FLAG;
792 int num_desc = 0;
793 uint32_t status = 0;
794 int nand_ret = NANDC_RESULT_SUCCESS;
795
796 cmd_list_ptr = qpic_nand_add_isbad_cmd_ce(params, cmd_list_ptr);
797
798 /* Enqueue the desc for the above commands */
799 bam_add_one_desc(&bam,
800 CMD_PIPE_INDEX,
801 (unsigned char*)cmd_list_ptr_start,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -0700802 PA((uint32_t)cmd_list_ptr - (uint32_t)cmd_list_ptr_start),
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700803 desc_flags);
804
805 num_desc++;
806
807 /* Add Data desc */
808 bam_add_desc(&bam,
809 DATA_PRODUCER_PIPE_INDEX,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -0700810 (unsigned char *)PA((addr_t)bad_block),
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700811 4,
812 BAM_DESC_INT_FLAG);
813
814 qpic_nand_wait_for_cmd_exec(num_desc);
815
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800816 status = qpic_nand_read_reg(NAND_FLASH_STATUS, 0);
Deepa Dinamani19530062012-10-03 14:43:05 -0700817
818 nand_ret = qpic_nand_check_status(status);
819
820 /* Dummy read to unlock pipe. */
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800821 status = qpic_nand_read_reg(NAND_FLASH_STATUS, BAM_DESC_UNLOCK_FLAG);
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700822
Deepa Dinamani19530062012-10-03 14:43:05 -0700823 if (nand_ret)
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700824 return NANDC_RESULT_FAILURE;
825
826 qpic_nand_wait_for_data(DATA_PRODUCER_PIPE_INDEX);
827
828 return nand_ret;
829}
830
Tanya Brokhman72b44dc2015-01-07 10:20:05 +0200831/**
832 * qpic_nand_block_isbad() - Checks is given block is bad
833 * @page - number of page the block starts at
834 *
835 * Returns nand_result_t
836 */
837nand_result_t qpic_nand_block_isbad(unsigned page)
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700838{
839 unsigned cwperpage;
840 struct cfg_params params;
841 uint8_t bad_block[4];
842 unsigned nand_ret = NANDC_RESULT_SUCCESS;
Deepa Dinamanidc1381e2012-11-15 14:53:24 -0800843 uint32_t blk = page / flash.num_pages_per_blk;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700844
Deepa Dinamanidc1381e2012-11-15 14:53:24 -0800845 if (bbtbl[blk] == NAND_BAD_BLK_VALUE_IS_GOOD)
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700846 return NANDC_RESULT_SUCCESS;
Deepa Dinamanidc1381e2012-11-15 14:53:24 -0800847 else if (bbtbl[blk] == NAND_BAD_BLK_VALUE_IS_BAD)
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700848 return NANDC_RESULT_BAD_BLOCK;
849 else
850 {
851 /* Read the bad block value from the flash.
852 * Bad block value is stored in the first page of the block.
853 */
854 /* Read the first page in the block. */
855 cwperpage = flash.cws_per_page;
856
857 /* Read page cmd */
Deepa Dinamanidc1381e2012-11-15 14:53:24 -0800858 params.cmd = NAND_CMD_PAGE_READ_ECC;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700859 /* Clear the CW per page bits */
860 params.cfg0 = cfg0_raw & ~(7U << NAND_DEV0_CFG0_CW_PER_PAGE_SHIFT);
861 params.cfg1 = cfg1_raw;
Deepa Dinamanidc1381e2012-11-15 14:53:24 -0800862 /* addr0 - Write column addr + few bits in row addr upto 32 bits. */
863 params.addr0 = (page << 16) | (USER_DATA_BYTES_PER_CW * cwperpage);
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700864
865 /* addr1 - Write rest of row addr.
866 * This will be all 0s.
867 */
Deepa Dinamanidc1381e2012-11-15 14:53:24 -0800868 params.addr1 = (page >> 16) & 0xff;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700869 params.addr_loc_0 = NAND_RD_LOC_OFFSET(0);
870 params.addr_loc_0 |= NAND_RD_LOC_LAST_BIT(1);
871 params.addr_loc_0 |= NAND_RD_LOC_SIZE(4); /* Read 4 bytes */
Deepa Dinamanidc1381e2012-11-15 14:53:24 -0800872 params.ecc_cfg = ecc_bch_cfg | 0x1; /* Disable ECC */
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700873 params.exec = 1;
874
875 if (qpic_nand_block_isbad_exec(&params, bad_block))
876 {
877 dprintf(CRITICAL,
878 "Could not read bad block value\n");
879 return NANDC_RESULT_FAILURE;
880 }
881
882 if (flash.widebus)
883 {
884 if (bad_block[0] != 0xFF && bad_block[1] != 0xFF)
885 {
Deepa Dinamanidc1381e2012-11-15 14:53:24 -0800886 bbtbl[blk] = NAND_BAD_BLK_VALUE_IS_BAD;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700887 nand_ret = NANDC_RESULT_BAD_BLOCK;
888 }
889 }
890 else if (bad_block[0] != 0xFF)
891 {
Deepa Dinamanidc1381e2012-11-15 14:53:24 -0800892 bbtbl[blk] = NAND_BAD_BLK_VALUE_IS_BAD;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700893 nand_ret = NANDC_RESULT_BAD_BLOCK;
894 }
895 else
Deepa Dinamanidc1381e2012-11-15 14:53:24 -0800896 bbtbl[blk] = NAND_BAD_BLK_VALUE_IS_GOOD;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700897
898 return nand_ret;
899 }
900}
901
902/* Function to erase a block on the nand.
903 * page: Starting page address for the block.
904 */
Tanya Brokhman72b44dc2015-01-07 10:20:05 +0200905nand_result_t qpic_nand_blk_erase(uint32_t page)
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700906{
907 struct cfg_params cfg;
908 struct cmd_element *cmd_list_ptr = ce_array;
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800909 struct cmd_element *cmd_list_read_ptr = ce_read_array;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700910 struct cmd_element *cmd_list_ptr_start = ce_array;
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800911 struct cmd_element *cmd_list_read_ptr_start = ce_read_array;
Veera Sundaram Sankaran00181512014-12-09 11:23:39 -0800912 uint32_t status;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700913 int num_desc = 0;
914 uint32_t blk_addr = page / flash.num_pages_per_blk;
915
916 /* Erase only if the block is not bad */
Deepa Dinamanidc1381e2012-11-15 14:53:24 -0800917 if (qpic_nand_block_isbad(page))
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700918 {
919 dprintf(CRITICAL,
920 "NAND Erase error: Block address belongs to bad block: %d\n",
921 blk_addr);
922 return NANDC_RESULT_FAILURE;
923 }
924
925 /* Fill in params for the erase flash cmd */
926 cfg.addr0 = page;
927 cfg.addr1 = 0;
928 /* Clear CW_PER_PAGE in cfg0 */
929 cfg.cfg0 = cfg0 & ~(7U << NAND_DEV0_CFG0_CW_PER_PAGE_SHIFT);
930 cfg.cfg1 = cfg1;
931 cfg.cmd = NAND_CMD_BLOCK_ERASE;
932 cfg.exec = 1;
933
934 cmd_list_ptr = qpic_nand_add_cmd_ce(&cfg, cmd_list_ptr);
935
936 /* Enqueue the desc for the above commands */
937 bam_add_one_desc(&bam,
938 CMD_PIPE_INDEX,
939 (unsigned char*)cmd_list_ptr_start,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -0700940 PA((uint32_t)cmd_list_ptr - (uint32_t)cmd_list_ptr_start),
Deepa Dinamani2467bbb2012-10-02 13:59:58 -0700941 BAM_DESC_NWD_FLAG | BAM_DESC_CMD_FLAG | BAM_DESC_INT_FLAG | BAM_DESC_LOCK_FLAG);
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700942
943 cmd_list_ptr_start = cmd_list_ptr;
944 num_desc++;
945
946 qpic_nand_wait_for_cmd_exec(num_desc);
947
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800948 status = qpic_nand_read_reg(NAND_FLASH_STATUS, 0);
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700949
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700950 cmd_list_ptr_start = cmd_list_ptr;
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800951 cmd_list_read_ptr_start = cmd_list_read_ptr;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700952
953 /* QPIC controller automatically sends
954 * GET_STATUS cmd to the nand card because
955 * of the configuration programmed.
956 * Read the result of GET_STATUS cmd.
957 */
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800958 cmd_list_read_ptr = qpic_nand_add_read_ce(cmd_list_read_ptr, &status);
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700959
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800960 /* Enqueue the desc for the NAND_FLASH_STATUS read command */
961 bam_add_one_desc(&bam,
962 CMD_PIPE_INDEX,
963 (unsigned char*)cmd_list_read_ptr_start,
964 PA((uint32_t)cmd_list_read_ptr - (uint32_t)cmd_list_read_ptr_start),
965 BAM_DESC_CMD_FLAG) ;
966
967 cmd_list_ptr = qpic_nand_reset_status_ce(cmd_list_ptr, 1);
968
969 /* Enqueue the desc for NAND_FLASH_STATUS and NAND_READ_STATUS write commands */
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700970 bam_add_one_desc(&bam,
971 CMD_PIPE_INDEX,
972 (unsigned char*)cmd_list_ptr_start,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -0700973 PA((uint32_t)cmd_list_ptr - (uint32_t)cmd_list_ptr_start),
Deepa Dinamani19530062012-10-03 14:43:05 -0700974 BAM_DESC_INT_FLAG | BAM_DESC_CMD_FLAG) ;
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800975 num_desc = 2;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700976 qpic_nand_wait_for_cmd_exec(num_desc);
977
Deepa Dinamani19530062012-10-03 14:43:05 -0700978 status = qpic_nand_check_status(status);
979
980 /* Dummy read to unlock pipe. */
Veera Sundaram Sankaran00181512014-12-09 11:23:39 -0800981 qpic_nand_read_reg(NAND_FLASH_STATUS, BAM_DESC_UNLOCK_FLAG);
Deepa Dinamani19530062012-10-03 14:43:05 -0700982
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700983 /* Check for status errors*/
Deepa Dinamani19530062012-10-03 14:43:05 -0700984 if (status)
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700985 {
986 dprintf(CRITICAL,
987 "NAND Erase error: Block address belongs to bad block: %d\n",
988 blk_addr);
Tanya Brokhman72b44dc2015-01-07 10:20:05 +0200989 qpic_nand_mark_badblock(page);
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700990 return NANDC_RESULT_FAILURE;
991 }
992
993 /* Check for PROG_ERASE_OP_RESULT bit for the result of erase operation. */
Deepa Dinamani2467bbb2012-10-02 13:59:58 -0700994 if (!(status & PROG_ERASE_OP_RESULT))
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700995 return NANDC_RESULT_SUCCESS;
996
Tanya Brokhman72b44dc2015-01-07 10:20:05 +0200997 qpic_nand_mark_badblock(page);
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700998 return NANDC_RESULT_FAILURE;
999}
1000
1001/* Return num of desc added. */
Deepa Dinamani19530062012-10-03 14:43:05 -07001002static void
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001003qpic_nand_add_wr_page_cws_cmd_desc(struct cfg_params *cfg,
1004 uint32_t status[],
1005 enum nand_cfg_value cfg_mode)
1006{
1007 struct cmd_element *cmd_list_ptr = ce_array;
Sridhar Parasuramf5188d82014-11-17 15:39:55 -08001008 struct cmd_element *cmd_list_read_ptr = ce_read_array;
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001009 struct cmd_element *cmd_list_ptr_start = ce_array;
Sridhar Parasuramf5188d82014-11-17 15:39:55 -08001010 struct cmd_element *cmd_list_read_ptr_start = ce_read_array;
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001011 uint32_t ecc;
1012 int num_desc = 0;
1013 int int_flag = 0;
1014
1015 if (cfg_mode == NAND_CFG)
1016 ecc = ecc_bch_cfg;
1017 else
Deepa Dinamanidc1381e2012-11-15 14:53:24 -08001018 ecc = ecc_bch_cfg | 0x1; /* Disable ECC */
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001019
1020 /* Add ECC configuration */
1021 bam_add_cmd_element(cmd_list_ptr, NAND_DEV0_ECC_CFG,
1022 (uint32_t)ecc, CE_WRITE_TYPE);
1023 cmd_list_ptr++;
1024 cmd_list_ptr = qpic_nand_add_addr_n_cfg_ce(cfg, cmd_list_ptr);
1025
1026 bam_add_cmd_element(cmd_list_ptr, NAND_FLASH_CMD,
1027 (uint32_t)cfg->cmd, CE_WRITE_TYPE);
1028 cmd_list_ptr++;
1029
1030 /* Enqueue the desc for the above commands */
1031 bam_add_one_desc(&bam,
1032 CMD_PIPE_INDEX,
1033 (unsigned char*)cmd_list_ptr_start,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001034 PA((uint32_t)cmd_list_ptr - (uint32_t)cmd_list_ptr_start),
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001035 BAM_DESC_CMD_FLAG | BAM_DESC_LOCK_FLAG);
1036
1037 num_desc++;
1038
1039 /* Add CE for all the CWs */
1040 for (unsigned i = 0; i < flash.cws_per_page; i++)
1041 {
1042 cmd_list_ptr_start = cmd_list_ptr;
Deepa Dinamani19530062012-10-03 14:43:05 -07001043 int_flag = BAM_DESC_INT_FLAG;
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001044
1045 bam_add_cmd_element(cmd_list_ptr, NAND_EXEC_CMD, (uint32_t)cfg->exec, CE_WRITE_TYPE);
1046 cmd_list_ptr++;
1047
1048 /* Enqueue the desc for the above commands */
1049 bam_add_one_desc(&bam,
1050 CMD_PIPE_INDEX,
1051 (unsigned char*)cmd_list_ptr_start,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001052 PA((uint32_t)cmd_list_ptr - (uint32_t)cmd_list_ptr_start),
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001053 BAM_DESC_NWD_FLAG | BAM_DESC_CMD_FLAG);
1054
1055 num_desc++;
1056 cmd_list_ptr_start = cmd_list_ptr;
Sridhar Parasuramf5188d82014-11-17 15:39:55 -08001057 cmd_list_read_ptr_start = cmd_list_read_ptr;
1058
1059 cmd_list_read_ptr = qpic_nand_add_read_ce(cmd_list_read_ptr_start, &status[i]);
1060 /* Enqueue the desc for the NAND_FLASH_STATUS read command */
1061 bam_add_one_desc(&bam,
1062 CMD_PIPE_INDEX,
1063 (unsigned char*)cmd_list_read_ptr_start,
1064 PA((uint32_t)cmd_list_read_ptr - (uint32_t)cmd_list_read_ptr_start),
1065 BAM_DESC_CMD_FLAG);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001066
1067 /* Set interrupt bit only for the last CW */
1068 if (i == flash.cws_per_page - 1)
Sridhar Parasuramf5188d82014-11-17 15:39:55 -08001069 cmd_list_ptr = qpic_nand_reset_status_ce(cmd_list_ptr, 1);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001070 else
Sridhar Parasuramf5188d82014-11-17 15:39:55 -08001071 cmd_list_ptr = qpic_nand_reset_status_ce(cmd_list_ptr, 0);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001072
Sridhar Parasuramf5188d82014-11-17 15:39:55 -08001073 /* Enqueue the desc for NAND_FLASH_STATUS and NAND_READ_STATUS write commands */
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001074 bam_add_one_desc(&bam,
1075 CMD_PIPE_INDEX,
1076 (unsigned char*)cmd_list_ptr_start,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001077 PA((uint32_t)cmd_list_ptr - (uint32_t)cmd_list_ptr_start),
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001078 int_flag | BAM_DESC_CMD_FLAG);
Sridhar Parasuramf5188d82014-11-17 15:39:55 -08001079 num_desc += 2;
Deepa Dinamani19530062012-10-03 14:43:05 -07001080
1081 qpic_nand_wait_for_cmd_exec(num_desc);
1082
1083 status[i] = qpic_nand_check_status(status[i]);
1084
1085 num_desc = 0;
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001086 }
Deepa Dinamani19530062012-10-03 14:43:05 -07001087 return;
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001088}
1089
1090void
1091qpic_add_wr_page_cws_data_desc(const void *buffer,
1092 enum nand_cfg_value cfg_mode,
1093 const void *spareaddr)
1094{
1095 int len;
1096 int flags;
1097 uint32_t start;
1098 unsigned num_desc = 0;
1099
1100 for( unsigned i = 0; i < flash.cws_per_page; i++)
1101 {
1102 flags = 0;
1103
1104 /* Set the interrupt flag on the last CW write for the page. */
1105 if( i == flash.cws_per_page - 1)
1106 flags |= BAM_DESC_INT_FLAG;
1107
1108 if (cfg_mode != NAND_CFG_RAW)
1109 {
1110 start = (uint32_t)buffer + i * DATA_BYTES_IN_IMG_PER_CW;
1111
1112 if (i < (flash.cws_per_page - 1))
1113 {
1114 len = DATA_BYTES_IN_IMG_PER_CW;
1115 flags |= BAM_DESC_EOT_FLAG;
1116 }
1117 else
1118 {
1119 /* Allow space for spare bytes in the last page */
1120 len = USER_DATA_BYTES_PER_CW - ((flash.cws_per_page - 1) << 2);
1121 flags = 0;
1122 }
1123 }
1124 else
1125 {
1126 start = (uint32_t)buffer;
1127 len = flash.cw_size;
1128 flags |= BAM_DESC_EOT_FLAG;
1129 }
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001130 bam_add_one_desc(&bam, DATA_CONSUMER_PIPE_INDEX, (unsigned char*)PA(start), len, flags);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001131 num_desc++;
1132
1133 if ((i == (flash.cws_per_page - 1)) && (cfg_mode == NAND_CFG))
1134 {
1135 /* write extra data */
1136 start = (uint32_t)spareaddr;
1137 len = (flash.cws_per_page << 2);
1138 flags = BAM_DESC_EOT_FLAG | BAM_DESC_INT_FLAG;
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001139 bam_add_one_desc(&bam, DATA_CONSUMER_PIPE_INDEX, (unsigned char*)PA(start), len, flags);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001140 num_desc++;
1141 }
1142 }
1143
1144 bam_sys_gen_event(&bam, DATA_CONSUMER_PIPE_INDEX, num_desc);
1145}
1146
1147static nand_result_t
1148qpic_nand_write_page(uint32_t pg_addr,
1149 enum nand_cfg_value cfg_mode,
1150 const void* buffer,
1151 const void* spareaddr)
1152{
1153 struct cfg_params cfg;
Deepa Dinamani16663a62013-02-07 16:25:59 -08001154 uint32_t status[QPIC_NAND_MAX_CWS_IN_PAGE];
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001155 int nand_ret = NANDC_RESULT_SUCCESS;
1156
1157 if (cfg_mode == NAND_CFG_RAW)
1158 {
1159 cfg.cfg0 = cfg0_raw;
1160 cfg.cfg1 = cfg1_raw;
1161 }
1162 else
1163 {
1164 cfg.cfg0 = cfg0;
1165 cfg.cfg1 = cfg1;
1166 }
1167
1168 cfg.cmd = NAND_CMD_PRG_PAGE;
1169 cfg.exec = 1;
1170
1171 cfg.addr0 = pg_addr << 16;
1172 cfg.addr1 = (pg_addr >> 16) & 0xff;
1173
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001174 qpic_add_wr_page_cws_data_desc(buffer, cfg_mode, spareaddr);
1175
Deepa Dinamani19530062012-10-03 14:43:05 -07001176 qpic_nand_add_wr_page_cws_cmd_desc(&cfg, status, cfg_mode);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001177
1178 /* Check for errors */
1179 for(unsigned i = 0; i < flash.cws_per_page; i++)
1180 {
1181 nand_ret = qpic_nand_check_status(status[i]);
1182 if (nand_ret)
1183 {
1184 dprintf(CRITICAL,
1185 "Failed to write CW %d for page: %d\n",
1186 i, pg_addr);
1187 break;
1188 }
1189 }
1190
1191 /* Wait for data to be available */
1192 qpic_nand_wait_for_data(DATA_CONSUMER_PIPE_INDEX);
1193
1194 return nand_ret;
1195}
1196
1197static int
1198qpic_nand_mark_badblock(uint32_t page)
1199{
1200 char empty_buf[NAND_CW_SIZE_8_BIT_ECC];
1201
1202 memset(empty_buf, 0, NAND_CW_SIZE_8_BIT_ECC);
1203
1204 /* Going to first page of the block */
1205 if (page & flash.num_pages_per_blk_mask)
1206 page = page - (page & flash.num_pages_per_blk_mask);
1207
1208 return qpic_nand_write_page(page, NAND_CFG_RAW, empty_buf, 0);
1209}
1210
1211static void
1212qpic_nand_non_onfi_probe(struct flash_info *flash)
1213{
1214 int dev_found = 0;
1215 unsigned index;
1216 uint32_t ecc_bits;
1217
1218 /* Read the nand id. */
1219 qpic_nand_fetch_id(flash);
1220
1221 /* Check if we support the device */
Deepa Dinamani649a94a2013-03-07 14:37:31 -08001222 for (index = 0; index < (ARRAY_SIZE(supported_flash)); index++)
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001223 {
1224 if ((flash->id & supported_flash[index].mask) ==
1225 (supported_flash[index].flash_id & (supported_flash[index].mask)))
1226 {
1227 dev_found = 1;
1228 break;
1229 }
1230 }
1231
1232 if (dev_found)
1233 {
1234 flash->page_size = supported_flash[index].pagesize;
1235 flash->block_size = supported_flash[index].blksize;
1236 flash->spare_size = supported_flash[index].oobsize;
1237 ecc_bits = supported_flash[index].ecc_8_bits;
1238
1239 /* Make sure that the block size and page size are defined. */
1240 ASSERT(flash->block_size);
1241 ASSERT(flash->page_size);
1242
1243 flash->num_blocks = supported_flash[index].density;
1244 flash->num_blocks /= (flash->block_size);
1245 flash->num_pages_per_blk = flash->block_size / flash->page_size;
1246 flash->num_pages_per_blk_mask = flash->num_pages_per_blk - 1;
1247
1248 /* Look for 8bit BCH ECC Nand, TODO: ECC Correctability >= 8 */
1249 if (ecc_bits)
1250 flash->ecc_width = NAND_WITH_8_BIT_ECC;
1251 else
1252 flash->ecc_width = NAND_WITH_4_BIT_ECC;
1253
1254 flash->density = supported_flash[index].density;
1255 flash->widebus = supported_flash[index].widebus;
1256
1257 return;
1258 }
1259
1260 /* Flash device is not supported, print flash device info and halt */
1261 if (dev_found == 0)
1262 {
1263 dprintf(CRITICAL, "NAND device is not supported: nandid: 0x%x"
1264 "maker=0x%02x device=0x%02x\n",
1265 flash->id,
1266 flash->vendor,
1267 flash->device);
1268 ASSERT(0);
1269 }
1270
1271 dprintf(INFO, "nandid: 0x%x maker=0x%02x device=0x%02x page_size=%d\n",
1272 flash->id,
1273 flash->vendor,
1274 flash->device,
1275 flash->page_size);
1276
1277 dprintf(INFO, "spare_size=%d block_size=%d num_blocks=%d\n",
1278 flash->spare_size,
1279 flash->block_size,
1280 flash->num_blocks);
1281}
1282
1283void
1284qpic_nand_init(struct qpic_nand_init_config *config)
1285{
1286 uint32_t i;
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001287
1288 nand_base = config->nand_base;
1289
Deepa Dinamanie9ded132012-11-27 15:03:38 -08001290 qpic_bam_init(config);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001291
Deepa Dinamani649a94a2013-03-07 14:37:31 -08001292 qpic_nand_non_onfi_probe(&flash);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001293
1294 /* Save the RAW and read/write configs */
1295 qpic_nand_save_config(&flash);
1296
1297 flash_spare_bytes = (unsigned char *)malloc(flash.spare_size);
1298
1299 if (flash_spare_bytes == NULL)
1300 {
1301 dprintf(CRITICAL, "Failed to allocate memory for spare bytes\n");
1302 return;
1303 }
1304
1305 /* Create a bad block table */
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001306 bbtbl = (uint8_t *) malloc(sizeof(uint8_t) * flash.num_blocks);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001307
1308 if (bbtbl == NULL)
1309 {
1310 dprintf(CRITICAL, "Failed to allocate memory for bad block table\n");
1311 return;
1312 }
1313
1314 for (i = 0; i < flash.num_blocks; i++)
1315 bbtbl[i] = NAND_BAD_BLK_VALUE_NOT_READ;
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001316
1317 /* Set aside contiguous memory for reads/writes.
1318 * This is needed as the BAM transfers only work with
1319 * physically contiguous buffers.
1320 * We will copy any data to be written/ to be read from
1321 * nand to this buffer and this buffer will be submitted to BAM.
1322 */
1323 rdwr_buf = (uint8_t*) malloc(flash.page_size + flash.spare_size);
1324
1325 if (rdwr_buf == NULL)
1326 {
1327 dprintf(CRITICAL, "Failed to allocate memory for page reads or writes\n");
1328 return;
1329 }
1330
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001331}
1332
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -07001333unsigned
1334flash_page_size(void)
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001335{
1336 return flash.page_size;
1337}
1338
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -07001339unsigned
1340flash_block_size(void)
1341{
1342 return flash.block_size;
1343}
1344
Deepa Dinamani8e6b2432012-10-17 17:12:44 -07001345unsigned
1346flash_num_blocks(void)
1347{
1348 return flash.num_blocks;
1349}
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -07001350
Tanya Brokhman72b44dc2015-01-07 10:20:05 +02001351unsigned
1352flash_spare_size(void)
1353{
1354 return flash.spare_size;
1355}
1356
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -07001357struct ptable *
1358flash_get_ptable(void)
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001359{
1360 return flash_ptable;
1361}
1362
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -07001363void
Deepa Dinamani87feab82012-10-04 14:28:05 -07001364qpic_nand_uninit()
1365{
1366 bam_pipe_reset(&bam, DATA_PRODUCER_PIPE_INDEX);
1367 bam_pipe_reset(&bam, DATA_CONSUMER_PIPE_INDEX);
1368 bam_pipe_reset(&bam, CMD_PIPE_INDEX);
1369
1370}
1371void
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -07001372flash_set_ptable(struct ptable *new_ptable)
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001373{
1374 ASSERT(flash_ptable == NULL && new_ptable != NULL);
1375 flash_ptable = new_ptable;
1376}
1377
1378/* Note: No support for raw reads. */
1379static int
1380qpic_nand_read_page(uint32_t page, unsigned char* buffer, unsigned char* spareaddr)
1381{
1382 struct cfg_params params;
1383 uint32_t ecc;
Deepa Dinamani16663a62013-02-07 16:25:59 -08001384 uint32_t flash_sts[QPIC_NAND_MAX_CWS_IN_PAGE];
1385 uint32_t buffer_sts[QPIC_NAND_MAX_CWS_IN_PAGE];
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001386 uint32_t addr_loc_0;
1387 uint32_t addr_loc_1;
1388 struct cmd_element *cmd_list_ptr = ce_array;
1389 struct cmd_element *cmd_list_ptr_start = ce_array;
1390 uint32_t num_cmd_desc = 0;
1391 uint32_t num_data_desc = 0;
1392 uint32_t status;
1393 uint32_t i;
1394 int nand_ret = NANDC_RESULT_SUCCESS;
Sundarajan Srinivasan024bda52014-02-27 16:48:48 -08001395 uint8_t flags = 0;
1396 uint32_t *cmd_list_temp = NULL;
1397
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001398 /* UD bytes in last CW is 512 - cws_per_page *4.
1399 * Since each of the CW read earlier reads 4 spare bytes.
1400 */
1401 uint16_t ud_bytes_in_last_cw = USER_DATA_BYTES_PER_CW - ((flash.cws_per_page - 1) << 2);
1402 uint16_t oob_bytes = DATA_BYTES_IN_IMG_PER_CW - ud_bytes_in_last_cw;
1403
1404 params.addr0 = page << 16;
1405 params.addr1 = (page >> 16) & 0xff;
1406 params.cfg0 = cfg0;
1407 params.cfg1 = cfg1;
1408 params.cmd = NAND_CMD_PAGE_READ_ALL;
1409 params.exec = 1;
1410 ecc = ecc_bch_cfg;
1411
1412 /* Read all the Data bytes in the first 3 CWs. */
1413 addr_loc_0 = NAND_RD_LOC_OFFSET(0);
1414 addr_loc_0 |= NAND_RD_LOC_SIZE(DATA_BYTES_IN_IMG_PER_CW);
1415 addr_loc_0 |= NAND_RD_LOC_LAST_BIT(1);
1416
1417
1418 addr_loc_1 = NAND_RD_LOC_OFFSET(ud_bytes_in_last_cw);
1419 addr_loc_1 |= NAND_RD_LOC_SIZE(oob_bytes);
1420 addr_loc_1 |= NAND_RD_LOC_LAST_BIT(1);
1421
Deepa Dinamanidc1381e2012-11-15 14:53:24 -08001422 status = qpic_nand_block_isbad(page);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001423
1424 if (status)
1425 return status;
1426
sundarajan srinivasan7ced6482013-03-21 16:01:18 -07001427 /* Reset and Configure erased CW/page detection controller */
1428 qpic_nand_erased_status_reset(ce_array, BAM_DESC_LOCK_FLAG);
1429
Sundarajan Srinivasan024bda52014-02-27 16:48:48 -08001430 /* Queue up the command and data descriptors for all the codewords in a page
1431 * and do a single bam transfer at the end.*/
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001432 for (i = 0; i < flash.cws_per_page; i++)
1433 {
1434 num_cmd_desc = 0;
1435 num_data_desc = 0;
1436
1437 if (i == 0)
1438 {
1439 cmd_list_ptr = qpic_nand_add_addr_n_cfg_ce(&params, cmd_list_ptr);
1440
1441 bam_add_cmd_element(cmd_list_ptr, NAND_DEV0_ECC_CFG,(uint32_t)ecc, CE_WRITE_TYPE);
1442 cmd_list_ptr++;
1443 }
1444 else
1445 cmd_list_ptr_start = cmd_list_ptr;
1446
1447 bam_add_cmd_element(cmd_list_ptr, NAND_FLASH_CMD, (uint32_t)params.cmd, CE_WRITE_TYPE);
1448 cmd_list_ptr++;
1449
1450 if (i == flash.cws_per_page - 1)
1451 {
1452 addr_loc_0 = NAND_RD_LOC_OFFSET(0);
1453 addr_loc_0 |= NAND_RD_LOC_SIZE(ud_bytes_in_last_cw);
1454 addr_loc_0 |= NAND_RD_LOC_LAST_BIT(0);
1455
1456 /* Write addr loc 1 only for the last CW. */
1457 bam_add_cmd_element(cmd_list_ptr, NAND_READ_LOCATION_n(1), (uint32_t)addr_loc_1, CE_WRITE_TYPE);
1458 cmd_list_ptr++;
1459
1460 /* Add Data desc */
1461 bam_add_one_desc(&bam,
1462 DATA_PRODUCER_PIPE_INDEX,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001463 (unsigned char *)PA((addr_t)buffer),
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001464 ud_bytes_in_last_cw,
1465 0);
1466 num_data_desc++;
1467
1468 bam_add_one_desc(&bam,
1469 DATA_PRODUCER_PIPE_INDEX,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001470 (unsigned char *)PA((addr_t)spareaddr),
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001471 oob_bytes,
1472 BAM_DESC_INT_FLAG);
1473 num_data_desc++;
1474
1475 bam_sys_gen_event(&bam, DATA_PRODUCER_PIPE_INDEX, num_data_desc);
1476 }
1477 else
1478 {
1479 /* Add Data desc */
1480 bam_add_one_desc(&bam,
1481 DATA_PRODUCER_PIPE_INDEX,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001482 (unsigned char *)PA((addr_t)buffer),
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001483 DATA_BYTES_IN_IMG_PER_CW,
Sundarajan Srinivasan024bda52014-02-27 16:48:48 -08001484 0);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001485 num_data_desc++;
1486 bam_sys_gen_event(&bam, DATA_PRODUCER_PIPE_INDEX, num_data_desc);
1487 }
1488
1489 /* Write addr loc 0. */
1490 bam_add_cmd_element(cmd_list_ptr,
1491 NAND_READ_LOCATION_n(0),
1492 (uint32_t)addr_loc_0,
1493 CE_WRITE_TYPE);
1494
1495 cmd_list_ptr++;
1496 bam_add_cmd_element(cmd_list_ptr,
1497 NAND_EXEC_CMD,
1498 (uint32_t)params.exec,
1499 CE_WRITE_TYPE);
1500 cmd_list_ptr++;
1501
Sundarajan Srinivasan024bda52014-02-27 16:48:48 -08001502 /* Enqueue the desc for the above commands */
1503 bam_add_one_desc(&bam,
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001504 CMD_PIPE_INDEX,
1505 (unsigned char*)cmd_list_ptr_start,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001506 PA((uint32_t)cmd_list_ptr - (uint32_t)cmd_list_ptr_start),
Sundarajan Srinivasan024bda52014-02-27 16:48:48 -08001507 BAM_DESC_NWD_FLAG | BAM_DESC_CMD_FLAG);
1508 num_cmd_desc++;
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001509
Sundarajan Srinivasan024bda52014-02-27 16:48:48 -08001510 bam_add_cmd_element(cmd_list_ptr, NAND_FLASH_STATUS, (uint32_t)PA((addr_t)&(flash_sts[i])), CE_READ_TYPE);
1511
vijay kumar4f4405f2014-08-08 11:49:53 +05301512 cmd_list_temp = (uint32_t *)cmd_list_ptr;
Sundarajan Srinivasan024bda52014-02-27 16:48:48 -08001513
1514 cmd_list_ptr++;
1515
1516 bam_add_cmd_element(cmd_list_ptr, NAND_BUFFER_STATUS, (uint32_t)PA((addr_t)&(buffer_sts[i])), CE_READ_TYPE);
1517 cmd_list_ptr++;
1518
1519 if (i == flash.cws_per_page - 1)
1520 {
1521 flags = BAM_DESC_CMD_FLAG | BAM_DESC_UNLOCK_FLAG;
1522 }
1523 else
1524 flags = BAM_DESC_CMD_FLAG;
1525
1526 /* Enqueue the desc for the above command */
1527 bam_add_one_desc(&bam,
1528 CMD_PIPE_INDEX,
1529 (unsigned char*)PA((addr_t)cmd_list_temp),
1530 PA((uint32_t)cmd_list_ptr - (uint32_t)cmd_list_temp),
1531 flags);
1532 num_cmd_desc++;
1533
1534 buffer += DATA_BYTES_IN_IMG_PER_CW;
1535
1536 /* Notify BAM HW about the newly added descriptors */
1537 bam_sys_gen_event(&bam, CMD_PIPE_INDEX, num_cmd_desc);
1538 }
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001539
1540 qpic_nand_wait_for_data(DATA_PRODUCER_PIPE_INDEX);
1541
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001542 /* Check status */
1543 for (i = 0; i < flash.cws_per_page ; i ++)
Sundarajan Srinivasan024bda52014-02-27 16:48:48 -08001544 {
1545 flash_sts[i] = qpic_nand_check_status(flash_sts[i]);
Deepa Dinamani19530062012-10-03 14:43:05 -07001546 if (flash_sts[i])
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001547 {
1548 nand_ret = NANDC_RESULT_BAD_PAGE;
Sundarajan Srinivasan024bda52014-02-27 16:48:48 -08001549 dprintf(CRITICAL, "NAND page read failed. page: %x status %x\n", page, flash_sts[i]);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001550 goto qpic_nand_read_page_error;
1551 }
Sundarajan Srinivasan024bda52014-02-27 16:48:48 -08001552 }
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001553qpic_nand_read_page_error:
1554return nand_ret;
1555}
1556
Tanya Brokhman72b44dc2015-01-07 10:20:05 +02001557/**
1558 * qpic_nand_read() - read data
1559 * @start_page: number of page to begin reading from
1560 * @num_pages: number of pages to read
1561 * @buffer: buffer where to store the read data
1562 * @spareaddr: buffer where to store spare data.
1563 * If null, spare data wont be read
1564 *
1565 * This function reads @num_pages starting from @start_page and stores the
1566 * read data in buffer. Note that it's in the caller responsibility to make
1567 * sure the read pages are all from same partition.
1568 *
1569 * Returns nand_result_t
1570 */
1571nand_result_t qpic_nand_read(uint32_t start_page, uint32_t num_pages,
1572 unsigned char* buffer, unsigned char* spareaddr)
1573{
1574 unsigned i = 0, ret = 0;
1575
1576 if (!buffer) {
1577 dprintf(CRITICAL, "qpic_nand_read: buffer = null\n");
1578 return NANDC_RESULT_PARAM_INVALID;
1579 }
1580 while (i < num_pages) {
1581 ret = qpic_nand_read_page(start_page + i, buffer + flash.page_size * i,
1582 spareaddr);
1583 i++;
1584 if (ret == NANDC_RESULT_BAD_PAGE)
1585 qpic_nand_mark_badblock(start_page + i);
1586 if (ret) {
1587 dprintf(CRITICAL,
1588 "qpic_nand_read: reading page %d failed with %d err\n",
1589 start_page + i, ret);
1590 return ret;
1591 }
1592 }
1593 return NANDC_RESULT_SUCCESS;
1594}
1595
1596/**
1597 * qpic_nand_write() - read data
1598 * @start_page: number of page to begin writing to
1599 * @num_pages: number of pages to write
1600 * @buffer: buffer to be written
1601 * @write_extra_bytes: true if spare data (ox 0xff) to be written
1602 *
1603 * This function writes @num_pages starting from @start_page. Note that it's
1604 * in the caller responsibility to make sure the written pages are all from
1605 * same partition.
1606 *
1607 * Returns nand_result_t
1608 */
1609nand_result_t qpic_nand_write(uint32_t start_page, uint32_t num_pages,
1610 unsigned char* buffer, unsigned write_extra_bytes)
1611{
1612 int i = 0, ret = NANDC_RESULT_SUCCESS;
1613 uint32_t *spare = (unsigned *)flash_spare_bytes;
1614 uint32_t wsize;
1615 uint32_t spare_byte_count = 0;
1616
1617 if (!buffer) {
1618 dprintf(CRITICAL, "qpic_nand_write: buffer = null\n");
1619 return NANDC_RESULT_PARAM_INVALID;
1620 }
1621 spare_byte_count = ((flash.cw_size * flash.cws_per_page)- flash.page_size);
1622
1623 if (write_extra_bytes)
1624 wsize = flash.page_size + spare_byte_count;
1625 else
1626 wsize = flash.page_size;
1627
1628 memset(spare, 0xff, (spare_byte_count / flash.cws_per_page));
1629
1630 for (i = 0; i < (int)num_pages; i++) {
1631 memcpy(rdwr_buf, buffer, flash.page_size);
1632 if (write_extra_bytes) {
1633 memcpy(rdwr_buf + flash.page_size,
1634 buffer + flash.page_size, spare_byte_count);
1635 ret = qpic_nand_write_page(start_page + i,
1636 NAND_CFG, rdwr_buf, rdwr_buf + flash.page_size);
1637 } else {
1638 ret = qpic_nand_write_page(start_page + i,
1639 NAND_CFG, rdwr_buf, spare);
1640 }
1641 if (ret) {
1642 dprintf(CRITICAL,
1643 "flash_write: write failure @ page %d, block %d\n",
1644 start_page + i,
1645 (start_page + i) / flash.num_pages_per_blk);
1646 if (ret == NANDC_RESULT_BAD_PAGE)
1647 qpic_nand_mark_badblock(start_page + i);
1648 goto out;
1649 }
1650 buffer += wsize;
1651 }
1652out:
1653 return ret;
1654}
1655
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001656/* Function to read a flash partition.
1657 * ptn : Partition to read.
1658 * extra_per_page : Spare data to be read.
1659 * offset : Num of bytes offset into the partition.
1660 * data : Buffer to read the data into.
1661 * bytes : Num of bytes to be read.
1662 */
1663 /* TODO: call this func read_partition. */
1664int
1665flash_read_ext(struct ptentry *ptn,
1666 unsigned extra_per_page,
1667 unsigned offset,
1668 void *data,
1669 unsigned bytes)
1670{
1671 uint32_t page =
1672 (ptn->start * flash.num_pages_per_blk) + (offset / flash.page_size);
1673 uint32_t lastpage = (ptn->start + ptn->length) * flash.num_pages_per_blk;
1674 uint32_t count =
1675 (bytes + flash.page_size - 1 + extra_per_page) / (flash.page_size +
1676 extra_per_page);
1677 uint32_t *spare = (unsigned *)flash_spare_bytes;
1678 uint32_t errors = 0;
1679 unsigned char *image = data;
1680 int result = 0;
1681 uint32_t current_block =
1682 (page - (page & flash.num_pages_per_blk_mask)) / flash.num_pages_per_blk;
1683 uint32_t start_block = ptn->start;
1684 uint32_t start_block_count = 0;
1685 uint32_t isbad = 0;
Deepa Dinamani2f7006c2013-08-19 11:59:38 -07001686 uint32_t current_page;
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001687
1688 /* Verify first byte is at page boundary. */
1689 if (offset & (flash.page_size - 1))
1690 {
1691 dprintf(CRITICAL, "Read request start not at page boundary: %d\n",
1692 offset);
1693 return NANDC_RESULT_PARAM_INVALID;
1694 }
1695
Deepa Dinamani2f7006c2013-08-19 11:59:38 -07001696 current_page = start_block * flash.num_pages_per_blk;
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001697 /* Adjust page offset based on number of bad blocks from start to current page */
1698 if (start_block < current_block)
1699 {
1700 start_block_count = (current_block - start_block);
1701 while (start_block_count
1702 && (start_block < (ptn->start + ptn->length)))
1703 {
Deepa Dinamani2f7006c2013-08-19 11:59:38 -07001704 isbad = qpic_nand_block_isbad(current_page);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001705 if (isbad)
1706 page += flash.num_pages_per_blk;
1707 else
1708 start_block_count--;
1709 start_block++;
Deepa Dinamani2f7006c2013-08-19 11:59:38 -07001710 current_page += flash.num_pages_per_blk;
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001711 }
1712 }
1713
1714 while ((page < lastpage) && !start_block_count)
1715 {
1716 if (count == 0)
1717 {
Deepa Dinamani52aca8d2013-02-05 11:41:41 -08001718 dprintf(SPEW, "flash_read_image: success (%d errors)\n",
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001719 errors);
1720 return NANDC_RESULT_SUCCESS;
1721 }
1722
Sundarajan Srinivasan29d927c2014-02-10 14:11:24 -08001723#if CONTIGUOUS_MEMORY
1724 result = qpic_nand_read_page(page, image, (unsigned char *) spare);
1725#else
1726 result = qpic_nand_read_page(page, rdwr_buf, (unsigned char *) spare);
1727#endif
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001728 if (result == NANDC_RESULT_BAD_PAGE)
1729 {
1730 /* bad page, go to next page. */
1731 page++;
1732 errors++;
1733 continue;
1734 }
1735 else if (result == NANDC_RESULT_BAD_BLOCK)
1736 {
1737 /* bad block, go to next block same offset. */
1738 page += flash.num_pages_per_blk;
1739 errors++;
1740 continue;
1741 }
1742
Sundarajan Srinivasan29d927c2014-02-10 14:11:24 -08001743#ifndef CONTIGUOUS_MEMORY
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001744 /* Copy the read page into correct location. */
1745 memcpy(image, rdwr_buf, flash.page_size);
Sundarajan Srinivasan29d927c2014-02-10 14:11:24 -08001746#endif
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001747 page++;
1748 image += flash.page_size;
1749 /* Copy spare bytes to image */
Sundarajan Srinivasan29d927c2014-02-10 14:11:24 -08001750 if(extra_per_page)
1751 {
1752 memcpy(image, spare, extra_per_page);
1753 image += extra_per_page;
1754 }
1755
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001756 count -= 1;
1757 }
1758
1759 /* could not find enough valid pages before we hit the end */
1760 dprintf(CRITICAL, "flash_read_image: failed (%d errors)\n", errors);
1761 return NANDC_RESULT_FAILURE;
1762}
1763
1764int
1765flash_erase(struct ptentry *ptn)
1766{
Deepa Dinamani2467bbb2012-10-02 13:59:58 -07001767 int ret = 0;
1768
1769 ret = qpic_nand_blk_erase(ptn->start * flash.num_pages_per_blk);
1770
1771 if (ret)
1772 dprintf(CRITICAL, "Erase operation failed \n");
1773
1774 return ret;
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001775}
Deepa Dinamani2467bbb2012-10-02 13:59:58 -07001776
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001777int
1778flash_ecc_bch_enabled()
1779{
1780 return (flash.ecc_width == NAND_WITH_4_BIT_ECC)? 0 : 1;
1781}
1782
1783int
1784flash_write(struct ptentry *ptn,
Deepa Dinamanic13d5942013-04-30 15:48:53 -07001785 unsigned write_extra_bytes,
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001786 const void *data,
1787 unsigned bytes)
1788{
1789 uint32_t page = ptn->start * flash.num_pages_per_blk;
1790 uint32_t lastpage = (ptn->start + ptn->length) * flash.num_pages_per_blk;
1791 uint32_t *spare = (unsigned *)flash_spare_bytes;
1792 const unsigned char *image = data;
Deepa Dinamanic13d5942013-04-30 15:48:53 -07001793 uint32_t wsize;
Sundarajan Srinivasan223d7002014-02-11 19:48:11 -08001794 uint32_t spare_byte_count = 0;
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001795 int r;
1796
Sundarajan Srinivasan223d7002014-02-11 19:48:11 -08001797 spare_byte_count = ((flash.cw_size * flash.cws_per_page)- flash.page_size);
1798
Deepa Dinamanic13d5942013-04-30 15:48:53 -07001799 if(write_extra_bytes)
Sundarajan Srinivasan223d7002014-02-11 19:48:11 -08001800 wsize = flash.page_size + spare_byte_count;
Deepa Dinamanic13d5942013-04-30 15:48:53 -07001801 else
1802 wsize = flash.page_size;
1803
Sundarajan Srinivasan223d7002014-02-11 19:48:11 -08001804 memset(spare, 0xff, (spare_byte_count / flash.cws_per_page));
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001805
1806 while (bytes > 0)
1807 {
1808 if (bytes < wsize)
1809 {
1810 dprintf(CRITICAL,
1811 "flash_write_image: image undersized (%d < %d)\n",
1812 bytes,
1813 wsize);
1814 return -1;
1815 }
1816
1817 if (page >= lastpage)
1818 {
1819 dprintf(CRITICAL, "flash_write_image: out of space\n");
1820 return -1;
1821 }
1822
1823 if ((page & flash.num_pages_per_blk_mask) == 0)
1824 {
Deepa Dinamani2467bbb2012-10-02 13:59:58 -07001825 if (qpic_nand_blk_erase(page))
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001826 {
1827 dprintf(INFO,
1828 "flash_write_image: bad block @ %d\n",
1829 page / flash.num_pages_per_blk);
1830
1831 page += flash.num_pages_per_blk;
1832 continue;
1833 }
1834 }
1835
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001836 memcpy(rdwr_buf, image, flash.page_size);
1837
Deepa Dinamanic13d5942013-04-30 15:48:53 -07001838 if (write_extra_bytes)
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001839 {
Sundarajan Srinivasan223d7002014-02-11 19:48:11 -08001840 memcpy(rdwr_buf + flash.page_size, image + flash.page_size, spare_byte_count);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001841 r = qpic_nand_write_page(page,
1842 NAND_CFG,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001843 rdwr_buf,
1844 rdwr_buf + flash.page_size);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001845 }
1846 else
1847 {
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001848 r = qpic_nand_write_page(page, NAND_CFG, rdwr_buf, spare);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001849 }
1850
1851 if (r)
1852 {
1853 dprintf(INFO,
1854 "flash_write_image: write failure @ page %d (src %d)\n",
1855 page,
1856 image - (const unsigned char *)data);
1857
1858 image -= (page & flash.num_pages_per_blk_mask) * wsize;
1859 bytes += (page & flash.num_pages_per_blk_mask) * wsize;
1860 page &= ~flash.num_pages_per_blk_mask;
1861 if (qpic_nand_blk_erase(page))
1862 {
1863 dprintf(INFO,
1864 "flash_write_image: erase failure @ page %d\n",
1865 page);
1866 }
1867
1868 qpic_nand_mark_badblock(page);
1869
1870 dprintf(INFO,
1871 "flash_write_image: restart write @ page %d (src %d)\n",
1872 page, image - (const unsigned char *)data);
1873
1874 page += flash.num_pages_per_blk;
1875 continue;
1876 }
1877 page++;
1878 image += wsize;
1879 bytes -= wsize;
1880 }
1881
1882 /* erase any remaining pages in the partition */
1883 page = (page + flash.num_pages_per_blk_mask) & (~flash.num_pages_per_blk_mask);
1884
1885 while (page < lastpage)
1886 {
1887 if (qpic_nand_blk_erase(page))
1888 {
1889 dprintf(INFO, "flash_write_image: bad block @ %d\n",
1890 page / flash.num_pages_per_blk);
1891 }
1892 page += flash.num_pages_per_blk;
1893 }
1894
1895 dprintf(INFO, "flash_write_image: success\n");
1896 return 0;
1897}
Smita Ghoshf5431c62014-09-18 14:11:14 -07001898
1899uint32_t nand_device_base()
1900{
1901 return nand_base;
1902}