blob: ae1cba009c74c9671a1c10bdbb1390eef5083b53 [file] [log] [blame]
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001/*
2 * Copyright (c) 2008, Google Inc.
3 * All rights reserved.
Tanya Brokhman646eedb2015-01-06 23:09:54 +02004 * Copyright (c) 2009-2015, The Linux Foundation. All rights reserved.
Deepa Dinamanie4573be2012-08-03 16:32:29 -07005 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in
12 * the documentation and/or other materials provided with the
13 * distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29#include <qpic_nand.h>
30#include <bam.h>
31#include <dev/flash.h>
32#include <lib/ptable.h>
33#include <debug.h>
34#include <string.h>
35#include <malloc.h>
Sridhar Parasuramfb0d9c82015-02-02 15:23:13 -080036#include <bits.h>
Deepa Dinamanie4573be2012-08-03 16:32:29 -070037#include <sys/types.h>
Deepa Dinamani0bf2f442012-10-19 11:41:06 -070038#include <platform.h>
Amol Jadib726c3b2012-09-13 13:51:23 -070039#include <platform/clock.h>
Smita Ghoshf5431c62014-09-18 14:11:14 -070040#include <platform/iomap.h>
Deepa Dinamanie4573be2012-08-03 16:32:29 -070041
42static uint32_t nand_base;
43static struct ptable *flash_ptable;
44static struct flash_info flash;
45static unsigned char *flash_spare_bytes;
46static uint32_t cfg0;
47static uint32_t cfg1;
48static uint32_t cfg0_raw;
49static uint32_t cfg1_raw;
50static uint32_t ecc_bch_cfg;
51
Sridhar Parasuramf5188d82014-11-17 15:39:55 -080052struct cmd_element ce_array[100] __attribute__ ((aligned(16)));
53struct cmd_element ce_read_array[20] __attribute__ ((aligned(16)));
Deepa Dinamanie4573be2012-08-03 16:32:29 -070054
55#define QPIC_BAM_DATA_FIFO_SIZE 64
56#define QPIC_BAM_CMD_FIFO_SIZE 64
57
58static struct bam_desc cmd_desc_fifo[QPIC_BAM_CMD_FIFO_SIZE] __attribute__ ((aligned(BAM_DESC_SIZE)));
59static struct bam_desc data_desc_fifo[QPIC_BAM_DATA_FIFO_SIZE] __attribute__ ((aligned(BAM_DESC_SIZE)));
60
61static struct bam_instance bam;
62static uint8_t *bbtbl;
63
Deepa Dinamani0bf2f442012-10-19 11:41:06 -070064static uint8_t* rdwr_buf;
65
Deepa Dinamanie4573be2012-08-03 16:32:29 -070066static struct flash_id supported_flash[] = {
Sridhar Parasuramfb0d9c82015-02-02 15:23:13 -080067 /* Flash ID Flash ID2 ID Mask ID Mask2 Density(MB) Wid Pgsz Blksz oobsz 8-bit ECCf */
68 {0x1590AC2C, 0x56, 0xFFFFFFFF, 0xFF, 0x20000000, 0, 2048, 0x00020000, 0x40, 0},
69 {0x1590AC2C, 0x57, 0xFFFFFFFF, 0xFF, 0x20000000, 0, 2048, 0x00020000, 0x40, 1},
70 {0x1590AA2C, 0x06, 0xFFFFFFFF, 0x0, 0x10000000, 0, 2048, 0x00020000, 0xE0, 1},
71 {0x2690AC2C, 0x54, 0xFFFFFFFF, 0x0, 0x20000000, 0, 4096, 0x00040000, 0xE0, 1},
72 {0x1590ACAD, 0, 0xFFFFFFFF, 0x0, 0x20000000, 0, 2048, 0x00020000, 0x80, 0},
73 {0x9590DC2C, 0x56, 0xFFFFFFFF, 0x0, 0x10000000, 0, 2048, 0x00020000, 0x40, 0},
74 {0x1590aa98, 0x76, 0xFFFFFFFF, 0x0, 0x10000000, 0, 2048, 0x00020000, 0x80, 1},
Deepa Dinamanie4573be2012-08-03 16:32:29 -070075 /* Note: Width flag is 0 for 8 bit Flash and 1 for 16 bit flash */
Deepa Dinamanie4573be2012-08-03 16:32:29 -070076};
77
Tanya Brokhman72b44dc2015-01-07 10:20:05 +020078static int qpic_nand_mark_badblock(uint32_t page);
79
Deepa Dinamanie4573be2012-08-03 16:32:29 -070080static void
81qpic_nand_wait_for_cmd_exec(uint32_t num_desc)
82{
83 /* Create a read/write event to notify the periperal of the added desc. */
84 bam_sys_gen_event(&bam, CMD_PIPE_INDEX, num_desc);
85
86 /* Wait for the descriptors to be processed */
87 bam_wait_for_interrupt(&bam, CMD_PIPE_INDEX, P_PRCSD_DESC_EN_MASK);
88
89 /* Read offset update for the circular FIFO */
90 bam_read_offset_update(&bam, CMD_PIPE_INDEX);
91}
92
93static void
94qpic_nand_wait_for_data(uint32_t pipe_num)
95{
96 /* Wait for the descriptors to be processed */
97 bam_wait_for_interrupt(&bam, pipe_num, P_PRCSD_DESC_EN_MASK);
98
99 /* Read offset update for the circular FIFO */
100 bam_read_offset_update(&bam, pipe_num);
101}
102
103static uint32_t
104qpic_nand_read_reg(uint32_t reg_addr,
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800105 uint8_t flags)
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700106{
107 uint32_t val;
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800108 struct cmd_element *cmd_list_read_ptr = ce_read_array;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700109
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800110 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 -0700111
112 /* Enqueue the desc for the above command */
113 bam_add_one_desc(&bam,
114 CMD_PIPE_INDEX,
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800115 (unsigned char*)PA((addr_t)cmd_list_read_ptr),
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700116 BAM_CE_SIZE,
117 BAM_DESC_CMD_FLAG| BAM_DESC_INT_FLAG | flags);
118
119 qpic_nand_wait_for_cmd_exec(1);
120
121 return val;
122}
123
Deepa Dinamani19530062012-10-03 14:43:05 -0700124/* Assume the BAM is in a locked state. */
125void
sundarajan srinivasan7ced6482013-03-21 16:01:18 -0700126qpic_nand_erased_status_reset(struct cmd_element *cmd_list_ptr, uint8_t flags)
Deepa Dinamani19530062012-10-03 14:43:05 -0700127{
128 uint32_t val = 0;
129
130 /* Reset the Erased Codeword/Page detection controller. */
131 val = NAND_ERASED_CW_DETECT_CFG_RESET_CTRL;
132
133 bam_add_cmd_element(cmd_list_ptr, NAND_ERASED_CW_DETECT_CFG, val, CE_WRITE_TYPE);
134
135 /* Enqueue the desc for the above command */
136 bam_add_one_desc(&bam,
137 CMD_PIPE_INDEX,
138 (unsigned char*)cmd_list_ptr,
139 BAM_CE_SIZE,
sundarajan srinivasan7ced6482013-03-21 16:01:18 -0700140 BAM_DESC_CMD_FLAG | BAM_DESC_INT_FLAG | flags);
Deepa Dinamani19530062012-10-03 14:43:05 -0700141
142 qpic_nand_wait_for_cmd_exec(1);
143
144 /* Enable the Erased Codeword/Page detection
145 * controller to check the data as it arrives.
146 * Also disable ECC reporting for an erased CW.
147 */
148 val = NAND_ERASED_CW_DETECT_CFG_ACTIVATE_CTRL | NAND_ERASED_CW_DETECT_ERASED_CW_ECC_MASK;
149
150 bam_add_cmd_element(cmd_list_ptr, NAND_ERASED_CW_DETECT_CFG, val, CE_WRITE_TYPE);
151
152 /* Enqueue the desc for the above command */
153 bam_add_one_desc(&bam,
154 CMD_PIPE_INDEX,
155 (unsigned char*)cmd_list_ptr,
156 BAM_CE_SIZE,
157 BAM_DESC_CMD_FLAG | BAM_DESC_INT_FLAG);
158
159 qpic_nand_wait_for_cmd_exec(1);
160}
161
162static nand_result_t
163qpic_nand_check_status(uint32_t status)
164{
165 uint32_t erase_sts;
166
167 /* Check for errors */
168 if (status & NAND_FLASH_ERR)
169 {
170 /* Check if this is an ECC error on an erased page. */
171 if (status & NAND_FLASH_OP_ERR)
172 {
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800173 erase_sts = qpic_nand_read_reg(NAND_ERASED_CW_DETECT_STATUS, 0);
Deepa Dinamani19530062012-10-03 14:43:05 -0700174 if ((erase_sts & (1 << NAND_ERASED_CW_DETECT_STATUS_PAGE_ALL_ERASED)))
175 {
176 /* Mask the OP ERROR. */
177 status &= ~NAND_FLASH_OP_ERR;
sundarajan srinivasan7ced6482013-03-21 16:01:18 -0700178 qpic_nand_erased_status_reset(ce_array, 0);
Deepa Dinamani19530062012-10-03 14:43:05 -0700179 }
180 }
181
182 /* ECC error flagged on an erased page read.
183 * Ignore and return success.
184 */
185 if (!(status & NAND_FLASH_ERR))
186 return NANDC_RESULT_SUCCESS;
187
188 dprintf(CRITICAL, "Nand Flash error. Status = %d\n", status);
189
190 if (status & NAND_FLASH_TIMEOUT_ERR)
191 return NANDC_RESULT_TIMEOUT;
192 else
193 return NANDC_RESULT_FAILURE;
194 }
195
196 return NANDC_RESULT_SUCCESS;
197}
198
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700199static uint32_t
200qpic_nand_fetch_id(struct flash_info *flash)
201{
202 struct cmd_element *cmd_list_ptr = ce_array;
203 struct cmd_element *cmd_list_ptr_start = ce_array;
204 int num_desc = 0;
205 uint32_t status;
Sridhar Parasuramfb0d9c82015-02-02 15:23:13 -0800206 uint32_t id, id2;
207 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 -0700208 uint32_t exec_cmd = 1;
209 int nand_ret = NANDC_RESULT_SUCCESS;
210
211 /* Issue the Fetch id command to the NANDc */
212 bam_add_cmd_element(cmd_list_ptr, NAND_FLASH_CMD, (uint32_t)flash_cmd, CE_WRITE_TYPE);
213 cmd_list_ptr++;
214
215 /* Execute the cmd */
216 bam_add_cmd_element(cmd_list_ptr, NAND_EXEC_CMD, (uint32_t)exec_cmd, CE_WRITE_TYPE);
217 cmd_list_ptr++;
218
219 /* Prepare the cmd desc for the above commands */
220 bam_add_one_desc(&bam,
221 CMD_PIPE_INDEX,
222 (unsigned char*)cmd_list_ptr_start,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -0700223 PA((uint32_t)cmd_list_ptr - (uint32_t)cmd_list_ptr_start),
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700224 BAM_DESC_LOCK_FLAG | BAM_DESC_INT_FLAG |
225 BAM_DESC_NWD_FLAG | BAM_DESC_CMD_FLAG);
226
227 /* Keep track of the number of desc added. */
228 num_desc++;
229 qpic_nand_wait_for_cmd_exec(num_desc);
230
231 cmd_list_ptr_start = ce_array;
232 cmd_list_ptr = ce_array;
233
234 /* Read the status register */
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800235 status = qpic_nand_read_reg(NAND_FLASH_STATUS, 0);
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700236
237 /* Check for errors */
238 nand_ret = qpic_nand_check_status(status);
239 if (nand_ret)
240 {
241 dprintf( CRITICAL, "Read ID cmd status failed\n");
242 goto qpic_nand_fetch_id_err;
243 }
244
245 /* Read the id */
Sridhar Parasuramfb0d9c82015-02-02 15:23:13 -0800246 id = qpic_nand_read_reg(NAND_READ_ID, 0);
247 id2 = qpic_nand_read_reg(NAND_READ_ID2, BAM_DESC_UNLOCK_FLAG);
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700248
249 flash->id = id;
Sridhar Parasuramfb0d9c82015-02-02 15:23:13 -0800250 flash->id2 = id2;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700251 flash->vendor = id & 0xff;
252 flash->device = (id >> 8) & 0xff;
253 flash->dev_cfg = (id >> 24) & 0xFF;
254 flash->widebus = 0;
255 flash->widebus &= (id >> 24) & 0xFF;
256 flash->widebus = flash->widebus? 1: 0;
257
258qpic_nand_fetch_id_err:
259 return nand_ret;
260}
261
262static int
Deepa Dinamanie9ded132012-11-27 15:03:38 -0800263qpic_bam_init(struct qpic_nand_init_config *config)
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700264{
265 uint32_t bam_ret = NANDC_RESULT_SUCCESS;
266
Deepa Dinamanie9ded132012-11-27 15:03:38 -0800267 bam.base = config->bam_base;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700268 /* Set Read pipe params. */
Deepa Dinamanie9ded132012-11-27 15:03:38 -0800269 bam.pipe[DATA_PRODUCER_PIPE_INDEX].pipe_num = config->pipes.read_pipe;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700270 /* System consumer */
271 bam.pipe[DATA_PRODUCER_PIPE_INDEX].trans_type = BAM2SYS;
272 bam.pipe[DATA_PRODUCER_PIPE_INDEX].fifo.size = QPIC_BAM_DATA_FIFO_SIZE;
273 bam.pipe[DATA_PRODUCER_PIPE_INDEX].fifo.head = data_desc_fifo;
Deepa Dinamani536d3f82013-07-09 13:05:56 -0700274 bam.pipe[DATA_PRODUCER_PIPE_INDEX].lock_grp = config->pipes.read_pipe_grp;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700275
276 /* Set Write pipe params. */
Deepa Dinamanie9ded132012-11-27 15:03:38 -0800277 bam.pipe[DATA_CONSUMER_PIPE_INDEX].pipe_num = config->pipes.write_pipe;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700278 /* System producer */
279 bam.pipe[DATA_CONSUMER_PIPE_INDEX].trans_type = SYS2BAM;
280 bam.pipe[DATA_CONSUMER_PIPE_INDEX].fifo.size = QPIC_BAM_DATA_FIFO_SIZE;
281 bam.pipe[DATA_CONSUMER_PIPE_INDEX].fifo.head = data_desc_fifo;
Deepa Dinamani536d3f82013-07-09 13:05:56 -0700282 bam.pipe[DATA_CONSUMER_PIPE_INDEX].lock_grp = config->pipes.write_pipe_grp;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700283
284 /* Set Cmd pipe params. */
Deepa Dinamanie9ded132012-11-27 15:03:38 -0800285 bam.pipe[CMD_PIPE_INDEX].pipe_num = config->pipes.cmd_pipe;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700286 /* System consumer */
Sundarajan Srinivasan357c35a2013-07-23 17:00:54 -0700287 bam.pipe[CMD_PIPE_INDEX].trans_type = SYS2BAM;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700288 bam.pipe[CMD_PIPE_INDEX].fifo.size = QPIC_BAM_CMD_FIFO_SIZE;
289 bam.pipe[CMD_PIPE_INDEX].fifo.head = cmd_desc_fifo;
Deepa Dinamani536d3f82013-07-09 13:05:56 -0700290 bam.pipe[CMD_PIPE_INDEX].lock_grp = config->pipes.cmd_pipe_grp;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700291
292 /* Programs the threshold for BAM transfer
293 * When this threshold is reached, BAM signals the peripheral via the pipe_bytes_available
294 * interface.
295 * The peripheral is signalled with this notification in the following cases:
296 * a. It has accumulated all the descriptors.
297 * b. It has accumulated more than threshold bytes.
298 * c. It has reached EOT (End Of Transfer).
299 * Note: this value needs to be set by the h/w folks and is specific for each peripheral.
300 */
301 bam.threshold = 32;
302
Deepa Dinamanie9ded132012-11-27 15:03:38 -0800303 /* Set the EE. */
304 bam.ee = config->ee;
305
306 /* Set the max desc length for this BAM. */
307 bam.max_desc_len = config->max_desc_len;
308
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700309 /* BAM Init. */
310 bam_init(&bam);
311
312 /* Initialize BAM QPIC read pipe */
313 bam_sys_pipe_init(&bam, DATA_PRODUCER_PIPE_INDEX);
314
315 /* Init read fifo */
316 bam_ret = bam_pipe_fifo_init(&bam, bam.pipe[DATA_PRODUCER_PIPE_INDEX].pipe_num);
317
318 if (bam_ret)
319 {
320 dprintf(CRITICAL, "QPIC:NANDc BAM Read FIFO init error\n");
321 bam_ret = NANDC_RESULT_FAILURE;
322 goto qpic_nand_bam_init_error;
323 }
324
325 /* Initialize BAM QPIC write pipe */
326 bam_sys_pipe_init(&bam, DATA_CONSUMER_PIPE_INDEX);
327
328 /* Init write fifo. Use the same fifo as read fifo. */
329 bam_ret = bam_pipe_fifo_init(&bam, bam.pipe[DATA_CONSUMER_PIPE_INDEX].pipe_num);
330
331 if (bam_ret)
332 {
333 dprintf(CRITICAL, "QPIC: NANDc: BAM Write FIFO init error\n");
334 bam_ret = NANDC_RESULT_FAILURE;
335 goto qpic_nand_bam_init_error;
336 }
337
338 /* Initialize BAM QPIC cmd pipe */
339 bam_sys_pipe_init(&bam, CMD_PIPE_INDEX);
340
341 /* Init cmd fifo */
342 bam_ret = bam_pipe_fifo_init(&bam, bam.pipe[CMD_PIPE_INDEX].pipe_num);
343
344 if (bam_ret)
345 {
346 dprintf(CRITICAL, "QPIC:NANDc BAM CMD FIFO init error\n");
347 bam_ret = NANDC_RESULT_FAILURE;
348 goto qpic_nand_bam_init_error;
349 }
350
351qpic_nand_bam_init_error:
352return bam_ret;
353}
354
355/* Adds command elements for addr and cfg register writes.
356 * cfg: Defines the configuration for the flash cmd.
357 * start: Address where the command elements are added.
358 *
359 * Returns the address where the next cmd element can be added.
360 */
361static struct cmd_element*
362qpic_nand_add_addr_n_cfg_ce(struct cfg_params *cfg,
363 struct cmd_element *start)
364{
365 struct cmd_element *cmd_list_ptr = start;
366
367 bam_add_cmd_element(cmd_list_ptr, NAND_ADDR0, (uint32_t)cfg->addr0, CE_WRITE_TYPE);
368 cmd_list_ptr++;
369 bam_add_cmd_element(cmd_list_ptr, NAND_ADDR1, (uint32_t)cfg->addr1, CE_WRITE_TYPE);
370 cmd_list_ptr++;
371 bam_add_cmd_element(cmd_list_ptr, NAND_DEV0_CFG0, (uint32_t)cfg->cfg0, CE_WRITE_TYPE);
372 cmd_list_ptr++;
373 bam_add_cmd_element(cmd_list_ptr, NAND_DEV0_CFG1, (uint32_t)cfg->cfg1, CE_WRITE_TYPE);
374 cmd_list_ptr++;
375
376 return cmd_list_ptr;
377}
378
379
380static struct cmd_element*
381qpic_nand_add_onfi_probe_ce(struct onfi_probe_params *params,
382 struct cmd_element *start)
383{
384 struct cmd_element *cmd_list_ptr = start;
385
386 cmd_list_ptr = qpic_nand_add_addr_n_cfg_ce(&params->cfg, cmd_list_ptr);
387
388 bam_add_cmd_element(cmd_list_ptr, NAND_DEV_CMD1, (uint32_t)params->dev_cmd1, CE_WRITE_TYPE);
389 cmd_list_ptr++;
390 bam_add_cmd_element(cmd_list_ptr, NAND_DEV_CMD_VLD, (uint32_t)params->vld, CE_WRITE_TYPE);
391 cmd_list_ptr++;
392 bam_add_cmd_element(cmd_list_ptr, NAND_READ_LOCATION_n(0), (uint32_t)params->cfg.addr_loc_0, CE_WRITE_TYPE);
393 cmd_list_ptr++;
394 bam_add_cmd_element(cmd_list_ptr, NAND_FLASH_CMD, (uint32_t)params->cfg.cmd, CE_WRITE_TYPE);
395 cmd_list_ptr++;
396 bam_add_cmd_element(cmd_list_ptr, NAND_EXEC_CMD, (uint32_t)params->cfg.exec, CE_WRITE_TYPE);
397 cmd_list_ptr++;
398
399 return cmd_list_ptr;
400}
401
402static int
403onfi_probe_cmd_exec(struct onfi_probe_params *params,
404 unsigned char* data_ptr,
405 int data_len)
406{
407 struct cmd_element *cmd_list_ptr = ce_array;
408 struct cmd_element *cmd_list_ptr_start = ce_array;
409 int num_desc = 0;
410 uint32_t status = 0;
411 int nand_ret = NANDC_RESULT_SUCCESS;
412 uint8_t desc_flags = BAM_DESC_NWD_FLAG | BAM_DESC_CMD_FLAG
413 | BAM_DESC_LOCK_FLAG | BAM_DESC_INT_FLAG;
414
415 params->cfg.addr_loc_0 = 0;
416 params->cfg.addr_loc_0 |= NAND_RD_LOC_LAST_BIT(1);
417 params->cfg.addr_loc_0 |= NAND_RD_LOC_OFFSET(0);
418 params->cfg.addr_loc_0 |= NAND_RD_LOC_SIZE(data_len);
419
420 cmd_list_ptr = qpic_nand_add_onfi_probe_ce(params, cmd_list_ptr);
421
422 /* Enqueue the desc for the above commands */
423 bam_add_one_desc(&bam,
424 CMD_PIPE_INDEX,
425 (unsigned char*)cmd_list_ptr_start,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -0700426 PA((addr_t)(uint32_t)cmd_list_ptr - (uint32_t)cmd_list_ptr_start),
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700427 desc_flags);
428
429 cmd_list_ptr_start = cmd_list_ptr;
430 num_desc++;
431
432 /* Add Data desc */
433 bam_add_desc(&bam,
434 DATA_PRODUCER_PIPE_INDEX,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -0700435 (unsigned char *)PA((addr_t)data_ptr),
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700436 data_len,
437 BAM_DESC_INT_FLAG);
438
439 /* Wait for the commands to be executed */
440 qpic_nand_wait_for_cmd_exec(num_desc);
441
442 /* Read buffer status and check for errors. */
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800443 status = qpic_nand_read_reg(NAND_FLASH_STATUS, 0);
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700444
445 if (qpic_nand_check_status(status))
446 {
447 nand_ret = NANDC_RESULT_FAILURE;
448 goto onfi_probe_exec_err;
449 }
450
451 /* Wait for data to be available */
452 qpic_nand_wait_for_data(DATA_PRODUCER_PIPE_INDEX);
453
454 /* Check for errors */
455 nand_ret = qpic_nand_check_status(status);
456
457onfi_probe_exec_err:
458 return nand_ret;
459}
460
461/* TODO: check why both vld and cmd need to be written. */
462void
463qpic_nand_onfi_probe_cleanup(uint32_t vld, uint32_t dev_cmd1)
464{
465 struct cmd_element *cmd_list_ptr = ce_array;
466 struct cmd_element *cmd_list_ptr_start = ce_array;
467
468 bam_add_cmd_element(cmd_list_ptr, NAND_DEV_CMD1, dev_cmd1, CE_WRITE_TYPE);
469 cmd_list_ptr++;
470 bam_add_cmd_element(cmd_list_ptr, NAND_DEV_CMD_VLD, vld, CE_WRITE_TYPE);
471 cmd_list_ptr++;
472
473 /* Enqueue the desc for the above commands */
474 bam_add_one_desc(&bam,
475 CMD_PIPE_INDEX,
476 (unsigned char*)cmd_list_ptr_start,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -0700477 PA((uint32_t)cmd_list_ptr - (uint32_t)cmd_list_ptr_start),
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700478 BAM_DESC_UNLOCK_FLAG | BAM_DESC_CMD_FLAG| BAM_DESC_INT_FLAG);
479
480 qpic_nand_wait_for_cmd_exec(1);
481}
482
483static int
484qpic_nand_onfi_save_params(struct onfi_param_page *param_page, struct flash_info *flash)
485{
486 int onfi_ret = NANDC_RESULT_SUCCESS;
487 uint32_t ecc_bits;
488
489 onfi_ret = qpic_nand_fetch_id(flash);
490
491 if (onfi_ret)
492 {
493 dprintf(CRITICAL, "Fetch ID cmd failed\n");
494 goto onfi_save_params_err;
495 }
496
497 flash->page_size = param_page->data_per_pg;
498 flash->block_size = param_page->pgs_per_blk * flash->page_size;
499 flash->num_blocks = param_page->blks_per_LUN;
500 flash->widebus = param_page->feature_supported & 0x1;
501 flash->density = param_page->blks_per_LUN * flash->blksize;
502 flash->spare_size = param_page->spare_per_pg;
503 ecc_bits = param_page->num_bits_ecc_correctability;
504 flash->num_pages_per_blk = param_page->pgs_per_blk;
505 flash->num_pages_per_blk_mask = param_page->pgs_per_blk - 1;
506
507 if (ecc_bits >= 8)
508 flash->ecc_width = NAND_WITH_8_BIT_ECC;
509 else
510 flash->ecc_width = NAND_WITH_4_BIT_ECC;
511
512 onfi_save_params_err:
513 return onfi_ret;
514}
515
516static void
517qpic_nand_save_config(struct flash_info *flash)
518{
519
520 /* Save Configurations */
521 flash->cws_per_page = flash->page_size >> NAND_CW_DIV_RIGHT_SHIFT;
522
Deepa Dinamani16663a62013-02-07 16:25:59 -0800523 /* Verify that we have enough buffer to handle all the cws in a page. */
524 ASSERT(flash->cws_per_page <= QPIC_NAND_MAX_CWS_IN_PAGE);
525
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700526 /* Codeword Size = UD_SIZE_BYTES + ECC_PARITY_SIZE_BYTES
527 * + SPARE_SIZE_BYTES + Bad Block size
528 */
529 if (flash->ecc_width & NAND_WITH_8_BIT_ECC)
530 {
531 flash->cw_size = NAND_CW_SIZE_8_BIT_ECC;
532 ecc_bch_cfg |= (1 << NAND_DEV0_ECC_MODE_SHIFT); /* Use 8-bit ecc */
533
534 if (flash->widebus)
535 {
536 cfg0 |= (0 << NAND_DEV0_CFG0_SPARE_SZ_BYTES_SHIFT); /* spare size bytes in each CW */
537 ecc_bch_cfg |= (14 << NAND_DEV0_ECC_PARITY_SZ_BYTES_SHIFT); /* parity bytes in each CW */
538 }
539 else
540 {
541 cfg0 |= (2 << NAND_DEV0_CFG0_SPARE_SZ_BYTES_SHIFT); /* spare size bytes in each CW */
542 ecc_bch_cfg |= (13 << NAND_DEV0_ECC_PARITY_SZ_BYTES_SHIFT); /* parity bytes in each CW */
543 }
544 }
545 else
546 {
547 flash->cw_size = NAND_CW_SIZE_4_BIT_ECC;
548
549 if (flash->widebus)
550 {
551 cfg0 |= (2 << NAND_DEV0_CFG0_SPARE_SZ_BYTES_SHIFT); /* spare size bytes in each CW */
552 ecc_bch_cfg |= (8 << NAND_DEV0_ECC_PARITY_SZ_BYTES_SHIFT); /* parity bytes in each CW */
553 }
554 else
555 {
556 cfg0 |= (4 << NAND_DEV0_CFG0_SPARE_SZ_BYTES_SHIFT); /* spare size bytes in each CW */
557 ecc_bch_cfg |= (7 << NAND_DEV0_ECC_PARITY_SZ_BYTES_SHIFT); /* parity bytes in each CW */
558 }
559 }
560
561 /* BAD_BLOCK_BYTE_NUM = Page Size -
562 * (CW_PER_PAGE * Codeword Size) + 1
563 * Note: Set CW_PER_PAGE to 1 less than the actual number.
564 */
565 flash->bad_blk_loc = flash->page_size - flash->cw_size * (flash->cws_per_page - 1) + 1;
566
567 cfg0 |= ((flash->cws_per_page - 1) << NAND_DEV0_CFG0_CW_PER_PAGE_SHIFT) /* 4/8 cw/pg for 2/4k */
568 |(DATA_BYTES_IN_IMG_PER_CW << NAND_DEV0_CFG0_UD_SIZE_BYTES_SHIFT) /* 516 user data bytes */
569 |(5 << NAND_DEV0_CFG0_ADDR_CYCLE_SHIFT) /* 5 address cycles */
570 |(0 << NAND_DEV0_CFG0_DIS_STS_AFTER_WR_SHIFT);/* Send read status cmd after each write. */
571
572 cfg1 |= (7 << NAND_DEV0_CFG1_RECOVERY_CYCLES_SHIFT) /* 8 recovery cycles */
573 |(0 << NAND_DEV0_CFG1_CS_ACTIVE_BSY_SHIFT) /* Allow CS deassertion */
574 |(flash->bad_blk_loc << NAND_DEV0_CFG1_BAD_BLK_BYTE_NUM_SHIFT)/* Bad block marker location */
575 |(0 << NAND_DEV0_CFG1_BAD_BLK_IN_SPARE_SHIFT) /* Bad block in user data area */
576 |(2 << NAND_DEV0_CFG1_WR_RD_BSY_GAP_SHIFT) /* 8 cycle tWB/tRB */
577 |(flash->widebus << NAND_DEV0_CFG1_WIDE_BUS_SHIFT); /* preserve wide flash flag */
578
579 cfg0_raw = ((flash->cws_per_page- 1) << NAND_DEV0_CFG0_CW_PER_PAGE_SHIFT)
580 |(5 << NAND_DEV0_CFG0_ADDR_CYCLE_SHIFT)
581 |(516 << NAND_DEV0_CFG0_UD_SIZE_BYTES_SHIFT) //figure out the size of cw
582 | (1 << NAND_DEV0_CFG0_DIS_STS_AFTER_WR_SHIFT);
583
584 cfg1_raw = (7 << NAND_DEV0_CFG1_RECOVERY_CYCLES_SHIFT)
585 | (0 << NAND_DEV0_CFG1_CS_ACTIVE_BSY_SHIFT)
586 | (17 << NAND_DEV0_CFG1_BAD_BLK_BYTE_NUM_SHIFT)
587 | (1 << NAND_DEV0_CFG1_BAD_BLK_IN_SPARE_SHIFT)
588 | (2 << NAND_DEV0_CFG1_WR_RD_BSY_GAP_SHIFT)
589 | (flash->widebus << NAND_DEV0_CFG1_WIDE_BUS_SHIFT)
590 |1 ; /* to disable reed solomon ecc..this feild is now read only. */
591
592 ecc_bch_cfg |= (0 << NAND_DEV0_ECC_DISABLE_SHIFT) /* Enable ECC */
593 | (0 << NAND_DEV0_ECC_SW_RESET_SHIFT) /* Put ECC core in op mode */
594 | (DATA_BYTES_IN_IMG_PER_CW << NAND_DEV0_ECC_NUM_DATA_BYTES)
595 | (1 << NAND_DEV0_ECC_FORCE_CLK_OPEN_SHIFT); /* Enable all clocks */
596}
597
598/* Onfi probe should issue the following commands to the flash device:
599 * 1. Read ID - with addr ONFI_READ_ID_ADDR.
600 * This returns the ONFI ASCII string indicating support for ONFI.
601 * 2. Read Prameter Page - with addr ONFI_READ_PARAM_PAGE_ADDR.
602 * This returns the params for the device.
603 * Each command inturn issues commands- ADDR0, ADDR1, chip_select,
604 * cfg0, cfg1, cmd_vld, dev_cmd1, read_loc0, flash, exec.
605 */
606static int
607qpic_nand_onfi_probe(struct flash_info *flash)
608{
609 struct onfi_probe_params params;
610 uint32_t vld;
611 uint32_t dev_cmd1;
612 unsigned char *buffer;
613 unsigned char onfi_str[4];
614 uint32_t *id;
615 struct onfi_param_page *param_page;
616 int onfi_ret = NANDC_RESULT_SUCCESS;
617
618 /* Allocate memory required to read the onfi param page */
619 buffer = (unsigned char*) malloc(ONFI_READ_PARAM_PAGE_BUFFER_SIZE);
Maria Yu71909742014-07-04 17:30:00 +0800620 ASSERT(buffer != NULL);
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700621
622 /* Read the vld and dev_cmd1 registers before modifying */
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800623 vld = qpic_nand_read_reg(NAND_DEV_CMD_VLD, 0);
624 dev_cmd1 = qpic_nand_read_reg(NAND_DEV_CMD1, 0);
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700625
626 /* Initialize flash cmd */
627 params.cfg.cmd = NAND_CMD_PAGE_READ;
628 params.cfg.exec = 1;
629
630 /* Execute Read ID cmd */
631
632 /* Initialize the config */
633 params.cfg.cfg0 = NAND_CFG0_RAW_ONFI_ID;
634 params.cfg.cfg1 = NAND_CFG1_RAW_ONFI_ID;
635
636 /* Initialize the cmd and vld */
637 params.dev_cmd1 = (dev_cmd1 & 0xFFFFFF00) | ONFI_READ_ID_CMD;
638 params.vld = vld & 0xFFFFFFFE;
639
640 /* Initialize the address
641 * addr1 is not used bcos of the cfg.
642 */
643 params.cfg.addr0 = ONFI_READ_ID_ADDR;
644 params.cfg.addr1 = 0;
645
646 /* Lock the pipe and execute the cmd. */
647 onfi_ret = onfi_probe_cmd_exec(&params, onfi_str, ONFI_READ_ID_BUFFER_SIZE);
648 if (onfi_ret)
649 {
650 dprintf(CRITICAL, "ONFI Read id cmd failed\n");
651 goto qpic_nand_onfi_probe_err;
652 }
653
654 /* Write back vld and cmd and unlock the pipe. */
655 qpic_nand_onfi_probe_cleanup(vld, dev_cmd1);
656
657 /* Check for onfi string */
658 id = (uint32_t*)onfi_str;
659 if (*id != ONFI_SIGNATURE)
660 {
661 dprintf(CRITICAL, "Not an ONFI device\n");
662 /* Not an onfi device. Return error. */
663 onfi_ret = NANDC_RESULT_DEV_NOT_SUPPORTED;
664 goto qpic_nand_onfi_probe_err;
665 }
666
667 dprintf(INFO, "ONFI device found\n");
668 /* Now read the param page */
669 /* Initialize the config */
670 params.cfg.cfg0 = NAND_CFG0_RAW_ONFI_PARAM_PAGE;
671 params.cfg.cfg1 = NAND_CFG1_RAW_ONFI_PARAM_PAGE;
672
673 /* Initialize the cmd and vld */
674 params.dev_cmd1 = (dev_cmd1 & 0xFFFFFF00) | ONFI_READ_PARAM_PAGE_CMD;
675 params.vld = vld & 0xFFFFFFFE;
676
677 /* Initialize the address
678 * addr1 is not used bcos of the cfg.
679 */
680 params.cfg.addr0 = ONFI_READ_PARAM_PAGE_ADDR;
681 params.cfg.addr1 = 0;
682
683 /* Lock the pipe and execute the cmd. */
684 onfi_ret = onfi_probe_cmd_exec(&params, buffer, ONFI_READ_PARAM_PAGE_BUFFER_SIZE);
685 if (onfi_ret)
686 {
687 dprintf(CRITICAL, "ONFI Read param page failed\n");
688 goto qpic_nand_onfi_probe_err;
689 }
690
691 /* Write back vld and cmd and unlock the pipe. */
692 qpic_nand_onfi_probe_cleanup(vld, dev_cmd1);
693
694 /* Verify the integrity of the returned page */
695 param_page = (struct onfi_param_page*)buffer;
696
697 /* TODO: Add CRC check to validate the param page. */
698
699 /* Save the parameter values */
700 onfi_ret = qpic_nand_onfi_save_params(param_page, flash);
701
702qpic_nand_onfi_probe_err:
703 if (onfi_ret)
704 dprintf(CRITICAL, "ONFI probe failed\n");
705
706 free(buffer);
707
708 return onfi_ret;
709}
710
711/* Enquues a desc for a flash cmd with NWD flag set:
712 * cfg: Defines the configuration for the flash cmd.
713 * start: Address where the command elements are added.
714 *
715 * Returns the address where the next cmd element can be added.
716 */
717struct cmd_element*
718qpic_nand_add_cmd_ce(struct cfg_params *cfg,
719 struct cmd_element *start)
720{
721 struct cmd_element *cmd_list_ptr;
722
723 cmd_list_ptr = qpic_nand_add_addr_n_cfg_ce(cfg, start);
724
725 bam_add_cmd_element(cmd_list_ptr, NAND_FLASH_CMD, (uint32_t)cfg->cmd, CE_WRITE_TYPE);
726 cmd_list_ptr++;
727
728 bam_add_cmd_element(cmd_list_ptr, NAND_EXEC_CMD, (uint32_t)cfg->exec, CE_WRITE_TYPE);
729 cmd_list_ptr++;
730
731 return cmd_list_ptr;
732}
733
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800734/* Reads nand_flash_status */
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700735struct cmd_element*
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800736qpic_nand_add_read_ce(struct cmd_element *start, uint32_t *flash_status_read)
737{
738 struct cmd_element *cmd_list_ptr = start;
739
740 bam_add_cmd_element(cmd_list_ptr, NAND_FLASH_STATUS, (uint32_t)PA((addr_t)flash_status_read), CE_READ_TYPE);
741 cmd_list_ptr++;
742
743 return cmd_list_ptr;
744}
745
746/* Resets nand_flash_status and nand_read_status */
747struct cmd_element*
748qpic_nand_reset_status_ce(struct cmd_element *start, uint32_t read_status)
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700749{
750 struct cmd_element *cmd_list_ptr = start;
751 uint32_t flash_status_reset;
752 uint32_t read_status_reset;
753
754 /* Read and reset the status registers. */
755 flash_status_reset = NAND_FLASH_STATUS_RESET;
756 read_status_reset = NAND_READ_STATUS_RESET;
757
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700758 bam_add_cmd_element(cmd_list_ptr, NAND_FLASH_STATUS, (uint32_t)flash_status_reset, CE_WRITE_TYPE);
759 cmd_list_ptr++;
760
761 if (read_status)
762 {
763 bam_add_cmd_element(cmd_list_ptr, NAND_READ_STATUS, (uint32_t)read_status_reset, CE_WRITE_TYPE);
764 cmd_list_ptr++;
765 }
766
767 return cmd_list_ptr;
768}
769
770struct cmd_element*
771qpic_nand_add_isbad_cmd_ce(struct cfg_params *cfg,
772 struct cmd_element *start)
773{
774 struct cmd_element *cmd_list_ptr = start;
775
776 bam_add_cmd_element(cmd_list_ptr, NAND_DEV0_ECC_CFG, (uint32_t)cfg->ecc_cfg, CE_WRITE_TYPE);
777 cmd_list_ptr++;
778
779 bam_add_cmd_element(cmd_list_ptr, NAND_READ_LOCATION_n(0), (uint32_t)cfg->addr_loc_0, CE_WRITE_TYPE);
780 cmd_list_ptr++;
781
782 cmd_list_ptr = qpic_nand_add_cmd_ce(cfg, cmd_list_ptr);
783
784 return cmd_list_ptr;
785}
786
787static int
788qpic_nand_block_isbad_exec(struct cfg_params *params,
789 uint8_t *bad_block)
790{
791
792 struct cmd_element *cmd_list_ptr = ce_array;
793 struct cmd_element *cmd_list_ptr_start = ce_array;
794 uint8_t desc_flags = BAM_DESC_NWD_FLAG | BAM_DESC_CMD_FLAG
795 | BAM_DESC_LOCK_FLAG | BAM_DESC_INT_FLAG;
796 int num_desc = 0;
797 uint32_t status = 0;
798 int nand_ret = NANDC_RESULT_SUCCESS;
799
800 cmd_list_ptr = qpic_nand_add_isbad_cmd_ce(params, cmd_list_ptr);
801
802 /* Enqueue the desc for the above commands */
803 bam_add_one_desc(&bam,
804 CMD_PIPE_INDEX,
805 (unsigned char*)cmd_list_ptr_start,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -0700806 PA((uint32_t)cmd_list_ptr - (uint32_t)cmd_list_ptr_start),
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700807 desc_flags);
808
809 num_desc++;
810
811 /* Add Data desc */
812 bam_add_desc(&bam,
813 DATA_PRODUCER_PIPE_INDEX,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -0700814 (unsigned char *)PA((addr_t)bad_block),
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700815 4,
816 BAM_DESC_INT_FLAG);
817
818 qpic_nand_wait_for_cmd_exec(num_desc);
819
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800820 status = qpic_nand_read_reg(NAND_FLASH_STATUS, 0);
Deepa Dinamani19530062012-10-03 14:43:05 -0700821
822 nand_ret = qpic_nand_check_status(status);
823
824 /* Dummy read to unlock pipe. */
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800825 status = qpic_nand_read_reg(NAND_FLASH_STATUS, BAM_DESC_UNLOCK_FLAG);
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700826
Deepa Dinamani19530062012-10-03 14:43:05 -0700827 if (nand_ret)
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700828 return NANDC_RESULT_FAILURE;
829
830 qpic_nand_wait_for_data(DATA_PRODUCER_PIPE_INDEX);
831
832 return nand_ret;
833}
834
Tanya Brokhman72b44dc2015-01-07 10:20:05 +0200835/**
836 * qpic_nand_block_isbad() - Checks is given block is bad
837 * @page - number of page the block starts at
838 *
839 * Returns nand_result_t
840 */
841nand_result_t qpic_nand_block_isbad(unsigned page)
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700842{
843 unsigned cwperpage;
844 struct cfg_params params;
845 uint8_t bad_block[4];
846 unsigned nand_ret = NANDC_RESULT_SUCCESS;
Deepa Dinamanidc1381e2012-11-15 14:53:24 -0800847 uint32_t blk = page / flash.num_pages_per_blk;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700848
Deepa Dinamanidc1381e2012-11-15 14:53:24 -0800849 if (bbtbl[blk] == NAND_BAD_BLK_VALUE_IS_GOOD)
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700850 return NANDC_RESULT_SUCCESS;
Deepa Dinamanidc1381e2012-11-15 14:53:24 -0800851 else if (bbtbl[blk] == NAND_BAD_BLK_VALUE_IS_BAD)
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700852 return NANDC_RESULT_BAD_BLOCK;
853 else
854 {
855 /* Read the bad block value from the flash.
856 * Bad block value is stored in the first page of the block.
857 */
858 /* Read the first page in the block. */
859 cwperpage = flash.cws_per_page;
860
861 /* Read page cmd */
Deepa Dinamanidc1381e2012-11-15 14:53:24 -0800862 params.cmd = NAND_CMD_PAGE_READ_ECC;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700863 /* Clear the CW per page bits */
864 params.cfg0 = cfg0_raw & ~(7U << NAND_DEV0_CFG0_CW_PER_PAGE_SHIFT);
865 params.cfg1 = cfg1_raw;
Deepa Dinamanidc1381e2012-11-15 14:53:24 -0800866 /* addr0 - Write column addr + few bits in row addr upto 32 bits. */
867 params.addr0 = (page << 16) | (USER_DATA_BYTES_PER_CW * cwperpage);
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700868
869 /* addr1 - Write rest of row addr.
870 * This will be all 0s.
871 */
Deepa Dinamanidc1381e2012-11-15 14:53:24 -0800872 params.addr1 = (page >> 16) & 0xff;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700873 params.addr_loc_0 = NAND_RD_LOC_OFFSET(0);
874 params.addr_loc_0 |= NAND_RD_LOC_LAST_BIT(1);
875 params.addr_loc_0 |= NAND_RD_LOC_SIZE(4); /* Read 4 bytes */
Deepa Dinamanidc1381e2012-11-15 14:53:24 -0800876 params.ecc_cfg = ecc_bch_cfg | 0x1; /* Disable ECC */
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700877 params.exec = 1;
878
879 if (qpic_nand_block_isbad_exec(&params, bad_block))
880 {
881 dprintf(CRITICAL,
882 "Could not read bad block value\n");
883 return NANDC_RESULT_FAILURE;
884 }
885
886 if (flash.widebus)
887 {
888 if (bad_block[0] != 0xFF && bad_block[1] != 0xFF)
889 {
Deepa Dinamanidc1381e2012-11-15 14:53:24 -0800890 bbtbl[blk] = NAND_BAD_BLK_VALUE_IS_BAD;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700891 nand_ret = NANDC_RESULT_BAD_BLOCK;
892 }
893 }
894 else if (bad_block[0] != 0xFF)
895 {
Deepa Dinamanidc1381e2012-11-15 14:53:24 -0800896 bbtbl[blk] = NAND_BAD_BLK_VALUE_IS_BAD;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700897 nand_ret = NANDC_RESULT_BAD_BLOCK;
898 }
899 else
Deepa Dinamanidc1381e2012-11-15 14:53:24 -0800900 bbtbl[blk] = NAND_BAD_BLK_VALUE_IS_GOOD;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700901
902 return nand_ret;
903 }
904}
905
906/* Function to erase a block on the nand.
907 * page: Starting page address for the block.
908 */
Tanya Brokhman72b44dc2015-01-07 10:20:05 +0200909nand_result_t qpic_nand_blk_erase(uint32_t page)
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700910{
911 struct cfg_params cfg;
912 struct cmd_element *cmd_list_ptr = ce_array;
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800913 struct cmd_element *cmd_list_read_ptr = ce_read_array;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700914 struct cmd_element *cmd_list_ptr_start = ce_array;
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800915 struct cmd_element *cmd_list_read_ptr_start = ce_read_array;
Veera Sundaram Sankaran00181512014-12-09 11:23:39 -0800916 uint32_t status;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700917 int num_desc = 0;
918 uint32_t blk_addr = page / flash.num_pages_per_blk;
919
920 /* Erase only if the block is not bad */
Deepa Dinamanidc1381e2012-11-15 14:53:24 -0800921 if (qpic_nand_block_isbad(page))
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700922 {
923 dprintf(CRITICAL,
924 "NAND Erase error: Block address belongs to bad block: %d\n",
925 blk_addr);
926 return NANDC_RESULT_FAILURE;
927 }
928
929 /* Fill in params for the erase flash cmd */
930 cfg.addr0 = page;
931 cfg.addr1 = 0;
932 /* Clear CW_PER_PAGE in cfg0 */
933 cfg.cfg0 = cfg0 & ~(7U << NAND_DEV0_CFG0_CW_PER_PAGE_SHIFT);
934 cfg.cfg1 = cfg1;
935 cfg.cmd = NAND_CMD_BLOCK_ERASE;
936 cfg.exec = 1;
937
938 cmd_list_ptr = qpic_nand_add_cmd_ce(&cfg, cmd_list_ptr);
939
940 /* Enqueue the desc for the above commands */
941 bam_add_one_desc(&bam,
942 CMD_PIPE_INDEX,
943 (unsigned char*)cmd_list_ptr_start,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -0700944 PA((uint32_t)cmd_list_ptr - (uint32_t)cmd_list_ptr_start),
Deepa Dinamani2467bbb2012-10-02 13:59:58 -0700945 BAM_DESC_NWD_FLAG | BAM_DESC_CMD_FLAG | BAM_DESC_INT_FLAG | BAM_DESC_LOCK_FLAG);
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700946
947 cmd_list_ptr_start = cmd_list_ptr;
948 num_desc++;
949
950 qpic_nand_wait_for_cmd_exec(num_desc);
951
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800952 status = qpic_nand_read_reg(NAND_FLASH_STATUS, 0);
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700953
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700954 cmd_list_ptr_start = cmd_list_ptr;
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800955 cmd_list_read_ptr_start = cmd_list_read_ptr;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700956
957 /* QPIC controller automatically sends
958 * GET_STATUS cmd to the nand card because
959 * of the configuration programmed.
960 * Read the result of GET_STATUS cmd.
961 */
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800962 cmd_list_read_ptr = qpic_nand_add_read_ce(cmd_list_read_ptr, &status);
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700963
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800964 /* Enqueue the desc for the NAND_FLASH_STATUS read command */
965 bam_add_one_desc(&bam,
966 CMD_PIPE_INDEX,
967 (unsigned char*)cmd_list_read_ptr_start,
968 PA((uint32_t)cmd_list_read_ptr - (uint32_t)cmd_list_read_ptr_start),
969 BAM_DESC_CMD_FLAG) ;
970
971 cmd_list_ptr = qpic_nand_reset_status_ce(cmd_list_ptr, 1);
972
973 /* Enqueue the desc for NAND_FLASH_STATUS and NAND_READ_STATUS write commands */
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700974 bam_add_one_desc(&bam,
975 CMD_PIPE_INDEX,
976 (unsigned char*)cmd_list_ptr_start,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -0700977 PA((uint32_t)cmd_list_ptr - (uint32_t)cmd_list_ptr_start),
Deepa Dinamani19530062012-10-03 14:43:05 -0700978 BAM_DESC_INT_FLAG | BAM_DESC_CMD_FLAG) ;
Sridhar Parasuramf5188d82014-11-17 15:39:55 -0800979 num_desc = 2;
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700980 qpic_nand_wait_for_cmd_exec(num_desc);
981
Deepa Dinamani19530062012-10-03 14:43:05 -0700982 status = qpic_nand_check_status(status);
983
984 /* Dummy read to unlock pipe. */
Veera Sundaram Sankaran00181512014-12-09 11:23:39 -0800985 qpic_nand_read_reg(NAND_FLASH_STATUS, BAM_DESC_UNLOCK_FLAG);
Deepa Dinamani19530062012-10-03 14:43:05 -0700986
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700987 /* Check for status errors*/
Deepa Dinamani19530062012-10-03 14:43:05 -0700988 if (status)
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700989 {
990 dprintf(CRITICAL,
991 "NAND Erase error: Block address belongs to bad block: %d\n",
992 blk_addr);
Tanya Brokhman72b44dc2015-01-07 10:20:05 +0200993 qpic_nand_mark_badblock(page);
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700994 return NANDC_RESULT_FAILURE;
995 }
996
997 /* Check for PROG_ERASE_OP_RESULT bit for the result of erase operation. */
Deepa Dinamani2467bbb2012-10-02 13:59:58 -0700998 if (!(status & PROG_ERASE_OP_RESULT))
Deepa Dinamanie4573be2012-08-03 16:32:29 -0700999 return NANDC_RESULT_SUCCESS;
1000
Tanya Brokhman72b44dc2015-01-07 10:20:05 +02001001 qpic_nand_mark_badblock(page);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001002 return NANDC_RESULT_FAILURE;
1003}
1004
1005/* Return num of desc added. */
Deepa Dinamani19530062012-10-03 14:43:05 -07001006static void
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001007qpic_nand_add_wr_page_cws_cmd_desc(struct cfg_params *cfg,
1008 uint32_t status[],
1009 enum nand_cfg_value cfg_mode)
1010{
1011 struct cmd_element *cmd_list_ptr = ce_array;
Sridhar Parasuramf5188d82014-11-17 15:39:55 -08001012 struct cmd_element *cmd_list_read_ptr = ce_read_array;
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001013 struct cmd_element *cmd_list_ptr_start = ce_array;
Sridhar Parasuramf5188d82014-11-17 15:39:55 -08001014 struct cmd_element *cmd_list_read_ptr_start = ce_read_array;
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001015 uint32_t ecc;
1016 int num_desc = 0;
1017 int int_flag = 0;
1018
1019 if (cfg_mode == NAND_CFG)
1020 ecc = ecc_bch_cfg;
1021 else
Deepa Dinamanidc1381e2012-11-15 14:53:24 -08001022 ecc = ecc_bch_cfg | 0x1; /* Disable ECC */
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001023
1024 /* Add ECC configuration */
1025 bam_add_cmd_element(cmd_list_ptr, NAND_DEV0_ECC_CFG,
1026 (uint32_t)ecc, CE_WRITE_TYPE);
1027 cmd_list_ptr++;
1028 cmd_list_ptr = qpic_nand_add_addr_n_cfg_ce(cfg, cmd_list_ptr);
1029
1030 bam_add_cmd_element(cmd_list_ptr, NAND_FLASH_CMD,
1031 (uint32_t)cfg->cmd, CE_WRITE_TYPE);
1032 cmd_list_ptr++;
1033
1034 /* Enqueue the desc for the above commands */
1035 bam_add_one_desc(&bam,
1036 CMD_PIPE_INDEX,
1037 (unsigned char*)cmd_list_ptr_start,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001038 PA((uint32_t)cmd_list_ptr - (uint32_t)cmd_list_ptr_start),
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001039 BAM_DESC_CMD_FLAG | BAM_DESC_LOCK_FLAG);
1040
1041 num_desc++;
1042
1043 /* Add CE for all the CWs */
1044 for (unsigned i = 0; i < flash.cws_per_page; i++)
1045 {
1046 cmd_list_ptr_start = cmd_list_ptr;
Deepa Dinamani19530062012-10-03 14:43:05 -07001047 int_flag = BAM_DESC_INT_FLAG;
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001048
1049 bam_add_cmd_element(cmd_list_ptr, NAND_EXEC_CMD, (uint32_t)cfg->exec, CE_WRITE_TYPE);
1050 cmd_list_ptr++;
1051
1052 /* Enqueue the desc for the above commands */
1053 bam_add_one_desc(&bam,
1054 CMD_PIPE_INDEX,
1055 (unsigned char*)cmd_list_ptr_start,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001056 PA((uint32_t)cmd_list_ptr - (uint32_t)cmd_list_ptr_start),
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001057 BAM_DESC_NWD_FLAG | BAM_DESC_CMD_FLAG);
1058
1059 num_desc++;
1060 cmd_list_ptr_start = cmd_list_ptr;
Sridhar Parasuramf5188d82014-11-17 15:39:55 -08001061 cmd_list_read_ptr_start = cmd_list_read_ptr;
1062
1063 cmd_list_read_ptr = qpic_nand_add_read_ce(cmd_list_read_ptr_start, &status[i]);
1064 /* Enqueue the desc for the NAND_FLASH_STATUS read command */
1065 bam_add_one_desc(&bam,
1066 CMD_PIPE_INDEX,
1067 (unsigned char*)cmd_list_read_ptr_start,
1068 PA((uint32_t)cmd_list_read_ptr - (uint32_t)cmd_list_read_ptr_start),
1069 BAM_DESC_CMD_FLAG);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001070
1071 /* Set interrupt bit only for the last CW */
1072 if (i == flash.cws_per_page - 1)
Sridhar Parasuramf5188d82014-11-17 15:39:55 -08001073 cmd_list_ptr = qpic_nand_reset_status_ce(cmd_list_ptr, 1);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001074 else
Sridhar Parasuramf5188d82014-11-17 15:39:55 -08001075 cmd_list_ptr = qpic_nand_reset_status_ce(cmd_list_ptr, 0);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001076
Sridhar Parasuramf5188d82014-11-17 15:39:55 -08001077 /* Enqueue the desc for NAND_FLASH_STATUS and NAND_READ_STATUS write commands */
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001078 bam_add_one_desc(&bam,
1079 CMD_PIPE_INDEX,
1080 (unsigned char*)cmd_list_ptr_start,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001081 PA((uint32_t)cmd_list_ptr - (uint32_t)cmd_list_ptr_start),
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001082 int_flag | BAM_DESC_CMD_FLAG);
Sridhar Parasuramf5188d82014-11-17 15:39:55 -08001083 num_desc += 2;
Deepa Dinamani19530062012-10-03 14:43:05 -07001084
1085 qpic_nand_wait_for_cmd_exec(num_desc);
1086
1087 status[i] = qpic_nand_check_status(status[i]);
1088
1089 num_desc = 0;
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001090 }
Deepa Dinamani19530062012-10-03 14:43:05 -07001091 return;
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001092}
1093
1094void
1095qpic_add_wr_page_cws_data_desc(const void *buffer,
1096 enum nand_cfg_value cfg_mode,
1097 const void *spareaddr)
1098{
1099 int len;
1100 int flags;
1101 uint32_t start;
1102 unsigned num_desc = 0;
1103
1104 for( unsigned i = 0; i < flash.cws_per_page; i++)
1105 {
1106 flags = 0;
1107
1108 /* Set the interrupt flag on the last CW write for the page. */
1109 if( i == flash.cws_per_page - 1)
1110 flags |= BAM_DESC_INT_FLAG;
1111
1112 if (cfg_mode != NAND_CFG_RAW)
1113 {
1114 start = (uint32_t)buffer + i * DATA_BYTES_IN_IMG_PER_CW;
1115
1116 if (i < (flash.cws_per_page - 1))
1117 {
1118 len = DATA_BYTES_IN_IMG_PER_CW;
1119 flags |= BAM_DESC_EOT_FLAG;
1120 }
1121 else
1122 {
1123 /* Allow space for spare bytes in the last page */
1124 len = USER_DATA_BYTES_PER_CW - ((flash.cws_per_page - 1) << 2);
1125 flags = 0;
1126 }
1127 }
1128 else
1129 {
1130 start = (uint32_t)buffer;
1131 len = flash.cw_size;
1132 flags |= BAM_DESC_EOT_FLAG;
1133 }
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001134 bam_add_one_desc(&bam, DATA_CONSUMER_PIPE_INDEX, (unsigned char*)PA(start), len, flags);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001135 num_desc++;
1136
1137 if ((i == (flash.cws_per_page - 1)) && (cfg_mode == NAND_CFG))
1138 {
1139 /* write extra data */
1140 start = (uint32_t)spareaddr;
1141 len = (flash.cws_per_page << 2);
1142 flags = BAM_DESC_EOT_FLAG | BAM_DESC_INT_FLAG;
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001143 bam_add_one_desc(&bam, DATA_CONSUMER_PIPE_INDEX, (unsigned char*)PA(start), len, flags);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001144 num_desc++;
1145 }
1146 }
1147
1148 bam_sys_gen_event(&bam, DATA_CONSUMER_PIPE_INDEX, num_desc);
1149}
1150
1151static nand_result_t
1152qpic_nand_write_page(uint32_t pg_addr,
1153 enum nand_cfg_value cfg_mode,
1154 const void* buffer,
1155 const void* spareaddr)
1156{
1157 struct cfg_params cfg;
Deepa Dinamani16663a62013-02-07 16:25:59 -08001158 uint32_t status[QPIC_NAND_MAX_CWS_IN_PAGE];
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001159 int nand_ret = NANDC_RESULT_SUCCESS;
1160
1161 if (cfg_mode == NAND_CFG_RAW)
1162 {
1163 cfg.cfg0 = cfg0_raw;
1164 cfg.cfg1 = cfg1_raw;
1165 }
1166 else
1167 {
1168 cfg.cfg0 = cfg0;
1169 cfg.cfg1 = cfg1;
1170 }
1171
1172 cfg.cmd = NAND_CMD_PRG_PAGE;
1173 cfg.exec = 1;
1174
1175 cfg.addr0 = pg_addr << 16;
1176 cfg.addr1 = (pg_addr >> 16) & 0xff;
1177
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001178 qpic_add_wr_page_cws_data_desc(buffer, cfg_mode, spareaddr);
1179
Deepa Dinamani19530062012-10-03 14:43:05 -07001180 qpic_nand_add_wr_page_cws_cmd_desc(&cfg, status, cfg_mode);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001181
1182 /* Check for errors */
1183 for(unsigned i = 0; i < flash.cws_per_page; i++)
1184 {
1185 nand_ret = qpic_nand_check_status(status[i]);
1186 if (nand_ret)
1187 {
1188 dprintf(CRITICAL,
1189 "Failed to write CW %d for page: %d\n",
1190 i, pg_addr);
1191 break;
1192 }
1193 }
1194
1195 /* Wait for data to be available */
1196 qpic_nand_wait_for_data(DATA_CONSUMER_PIPE_INDEX);
1197
1198 return nand_ret;
1199}
1200
1201static int
1202qpic_nand_mark_badblock(uint32_t page)
1203{
1204 char empty_buf[NAND_CW_SIZE_8_BIT_ECC];
1205
1206 memset(empty_buf, 0, NAND_CW_SIZE_8_BIT_ECC);
1207
1208 /* Going to first page of the block */
1209 if (page & flash.num_pages_per_blk_mask)
1210 page = page - (page & flash.num_pages_per_blk_mask);
1211
1212 return qpic_nand_write_page(page, NAND_CFG_RAW, empty_buf, 0);
1213}
1214
1215static void
1216qpic_nand_non_onfi_probe(struct flash_info *flash)
1217{
1218 int dev_found = 0;
1219 unsigned index;
1220 uint32_t ecc_bits;
1221
1222 /* Read the nand id. */
1223 qpic_nand_fetch_id(flash);
1224
1225 /* Check if we support the device */
Deepa Dinamani649a94a2013-03-07 14:37:31 -08001226 for (index = 0; index < (ARRAY_SIZE(supported_flash)); index++)
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001227 {
Sridhar Parasuramfb0d9c82015-02-02 15:23:13 -08001228 if (((flash->id & supported_flash[index].mask) ==
1229 (supported_flash[index].flash_id & (supported_flash[index].mask))) &&
1230 ((flash->id2 & supported_flash[index].mask2) ==
1231 (supported_flash[index].flash_id2 & (supported_flash[index].mask2))))
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001232 {
1233 dev_found = 1;
1234 break;
1235 }
1236 }
1237
1238 if (dev_found)
1239 {
1240 flash->page_size = supported_flash[index].pagesize;
1241 flash->block_size = supported_flash[index].blksize;
1242 flash->spare_size = supported_flash[index].oobsize;
1243 ecc_bits = supported_flash[index].ecc_8_bits;
1244
1245 /* Make sure that the block size and page size are defined. */
1246 ASSERT(flash->block_size);
1247 ASSERT(flash->page_size);
1248
1249 flash->num_blocks = supported_flash[index].density;
1250 flash->num_blocks /= (flash->block_size);
1251 flash->num_pages_per_blk = flash->block_size / flash->page_size;
1252 flash->num_pages_per_blk_mask = flash->num_pages_per_blk - 1;
1253
1254 /* Look for 8bit BCH ECC Nand, TODO: ECC Correctability >= 8 */
1255 if (ecc_bits)
1256 flash->ecc_width = NAND_WITH_8_BIT_ECC;
1257 else
1258 flash->ecc_width = NAND_WITH_4_BIT_ECC;
1259
1260 flash->density = supported_flash[index].density;
1261 flash->widebus = supported_flash[index].widebus;
1262
1263 return;
1264 }
1265
1266 /* Flash device is not supported, print flash device info and halt */
1267 if (dev_found == 0)
1268 {
1269 dprintf(CRITICAL, "NAND device is not supported: nandid: 0x%x"
1270 "maker=0x%02x device=0x%02x\n",
1271 flash->id,
1272 flash->vendor,
1273 flash->device);
1274 ASSERT(0);
1275 }
1276
1277 dprintf(INFO, "nandid: 0x%x maker=0x%02x device=0x%02x page_size=%d\n",
1278 flash->id,
1279 flash->vendor,
1280 flash->device,
1281 flash->page_size);
1282
1283 dprintf(INFO, "spare_size=%d block_size=%d num_blocks=%d\n",
1284 flash->spare_size,
1285 flash->block_size,
1286 flash->num_blocks);
1287}
1288
1289void
1290qpic_nand_init(struct qpic_nand_init_config *config)
1291{
1292 uint32_t i;
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001293
1294 nand_base = config->nand_base;
1295
Deepa Dinamanie9ded132012-11-27 15:03:38 -08001296 qpic_bam_init(config);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001297
Deepa Dinamani649a94a2013-03-07 14:37:31 -08001298 qpic_nand_non_onfi_probe(&flash);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001299
1300 /* Save the RAW and read/write configs */
1301 qpic_nand_save_config(&flash);
1302
1303 flash_spare_bytes = (unsigned char *)malloc(flash.spare_size);
1304
1305 if (flash_spare_bytes == NULL)
1306 {
1307 dprintf(CRITICAL, "Failed to allocate memory for spare bytes\n");
1308 return;
1309 }
1310
1311 /* Create a bad block table */
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001312 bbtbl = (uint8_t *) malloc(sizeof(uint8_t) * flash.num_blocks);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001313
1314 if (bbtbl == NULL)
1315 {
1316 dprintf(CRITICAL, "Failed to allocate memory for bad block table\n");
1317 return;
1318 }
1319
1320 for (i = 0; i < flash.num_blocks; i++)
1321 bbtbl[i] = NAND_BAD_BLK_VALUE_NOT_READ;
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001322
1323 /* Set aside contiguous memory for reads/writes.
1324 * This is needed as the BAM transfers only work with
1325 * physically contiguous buffers.
1326 * We will copy any data to be written/ to be read from
1327 * nand to this buffer and this buffer will be submitted to BAM.
1328 */
1329 rdwr_buf = (uint8_t*) malloc(flash.page_size + flash.spare_size);
1330
1331 if (rdwr_buf == NULL)
1332 {
1333 dprintf(CRITICAL, "Failed to allocate memory for page reads or writes\n");
1334 return;
1335 }
1336
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001337}
1338
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -07001339unsigned
1340flash_page_size(void)
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001341{
1342 return flash.page_size;
1343}
1344
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -07001345unsigned
1346flash_block_size(void)
1347{
1348 return flash.block_size;
1349}
1350
Deepa Dinamani8e6b2432012-10-17 17:12:44 -07001351unsigned
1352flash_num_blocks(void)
1353{
1354 return flash.num_blocks;
1355}
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -07001356
Tanya Brokhman72b44dc2015-01-07 10:20:05 +02001357unsigned
1358flash_spare_size(void)
1359{
1360 return flash.spare_size;
1361}
1362
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -07001363struct ptable *
1364flash_get_ptable(void)
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001365{
1366 return flash_ptable;
1367}
1368
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -07001369void
Deepa Dinamani87feab82012-10-04 14:28:05 -07001370qpic_nand_uninit()
1371{
1372 bam_pipe_reset(&bam, DATA_PRODUCER_PIPE_INDEX);
1373 bam_pipe_reset(&bam, DATA_CONSUMER_PIPE_INDEX);
1374 bam_pipe_reset(&bam, CMD_PIPE_INDEX);
1375
1376}
1377void
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -07001378flash_set_ptable(struct ptable *new_ptable)
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001379{
1380 ASSERT(flash_ptable == NULL && new_ptable != NULL);
1381 flash_ptable = new_ptable;
1382}
1383
1384/* Note: No support for raw reads. */
1385static int
1386qpic_nand_read_page(uint32_t page, unsigned char* buffer, unsigned char* spareaddr)
1387{
1388 struct cfg_params params;
1389 uint32_t ecc;
Deepa Dinamani16663a62013-02-07 16:25:59 -08001390 uint32_t flash_sts[QPIC_NAND_MAX_CWS_IN_PAGE];
1391 uint32_t buffer_sts[QPIC_NAND_MAX_CWS_IN_PAGE];
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001392 uint32_t addr_loc_0;
1393 uint32_t addr_loc_1;
1394 struct cmd_element *cmd_list_ptr = ce_array;
1395 struct cmd_element *cmd_list_ptr_start = ce_array;
1396 uint32_t num_cmd_desc = 0;
1397 uint32_t num_data_desc = 0;
1398 uint32_t status;
1399 uint32_t i;
1400 int nand_ret = NANDC_RESULT_SUCCESS;
Sundarajan Srinivasan024bda52014-02-27 16:48:48 -08001401 uint8_t flags = 0;
1402 uint32_t *cmd_list_temp = NULL;
1403
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001404 /* UD bytes in last CW is 512 - cws_per_page *4.
1405 * Since each of the CW read earlier reads 4 spare bytes.
1406 */
1407 uint16_t ud_bytes_in_last_cw = USER_DATA_BYTES_PER_CW - ((flash.cws_per_page - 1) << 2);
1408 uint16_t oob_bytes = DATA_BYTES_IN_IMG_PER_CW - ud_bytes_in_last_cw;
1409
1410 params.addr0 = page << 16;
1411 params.addr1 = (page >> 16) & 0xff;
1412 params.cfg0 = cfg0;
1413 params.cfg1 = cfg1;
1414 params.cmd = NAND_CMD_PAGE_READ_ALL;
1415 params.exec = 1;
1416 ecc = ecc_bch_cfg;
1417
1418 /* Read all the Data bytes in the first 3 CWs. */
1419 addr_loc_0 = NAND_RD_LOC_OFFSET(0);
1420 addr_loc_0 |= NAND_RD_LOC_SIZE(DATA_BYTES_IN_IMG_PER_CW);
1421 addr_loc_0 |= NAND_RD_LOC_LAST_BIT(1);
1422
1423
1424 addr_loc_1 = NAND_RD_LOC_OFFSET(ud_bytes_in_last_cw);
1425 addr_loc_1 |= NAND_RD_LOC_SIZE(oob_bytes);
1426 addr_loc_1 |= NAND_RD_LOC_LAST_BIT(1);
1427
Deepa Dinamanidc1381e2012-11-15 14:53:24 -08001428 status = qpic_nand_block_isbad(page);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001429
1430 if (status)
1431 return status;
1432
sundarajan srinivasan7ced6482013-03-21 16:01:18 -07001433 /* Reset and Configure erased CW/page detection controller */
1434 qpic_nand_erased_status_reset(ce_array, BAM_DESC_LOCK_FLAG);
1435
Sundarajan Srinivasan024bda52014-02-27 16:48:48 -08001436 /* Queue up the command and data descriptors for all the codewords in a page
1437 * and do a single bam transfer at the end.*/
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001438 for (i = 0; i < flash.cws_per_page; i++)
1439 {
1440 num_cmd_desc = 0;
1441 num_data_desc = 0;
1442
1443 if (i == 0)
1444 {
1445 cmd_list_ptr = qpic_nand_add_addr_n_cfg_ce(&params, cmd_list_ptr);
1446
1447 bam_add_cmd_element(cmd_list_ptr, NAND_DEV0_ECC_CFG,(uint32_t)ecc, CE_WRITE_TYPE);
1448 cmd_list_ptr++;
1449 }
1450 else
1451 cmd_list_ptr_start = cmd_list_ptr;
1452
1453 bam_add_cmd_element(cmd_list_ptr, NAND_FLASH_CMD, (uint32_t)params.cmd, CE_WRITE_TYPE);
1454 cmd_list_ptr++;
1455
1456 if (i == flash.cws_per_page - 1)
1457 {
1458 addr_loc_0 = NAND_RD_LOC_OFFSET(0);
1459 addr_loc_0 |= NAND_RD_LOC_SIZE(ud_bytes_in_last_cw);
1460 addr_loc_0 |= NAND_RD_LOC_LAST_BIT(0);
1461
1462 /* Write addr loc 1 only for the last CW. */
1463 bam_add_cmd_element(cmd_list_ptr, NAND_READ_LOCATION_n(1), (uint32_t)addr_loc_1, CE_WRITE_TYPE);
1464 cmd_list_ptr++;
1465
1466 /* Add Data desc */
1467 bam_add_one_desc(&bam,
1468 DATA_PRODUCER_PIPE_INDEX,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001469 (unsigned char *)PA((addr_t)buffer),
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001470 ud_bytes_in_last_cw,
1471 0);
1472 num_data_desc++;
1473
1474 bam_add_one_desc(&bam,
1475 DATA_PRODUCER_PIPE_INDEX,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001476 (unsigned char *)PA((addr_t)spareaddr),
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001477 oob_bytes,
1478 BAM_DESC_INT_FLAG);
1479 num_data_desc++;
1480
1481 bam_sys_gen_event(&bam, DATA_PRODUCER_PIPE_INDEX, num_data_desc);
1482 }
1483 else
1484 {
1485 /* Add Data desc */
1486 bam_add_one_desc(&bam,
1487 DATA_PRODUCER_PIPE_INDEX,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001488 (unsigned char *)PA((addr_t)buffer),
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001489 DATA_BYTES_IN_IMG_PER_CW,
Sundarajan Srinivasan024bda52014-02-27 16:48:48 -08001490 0);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001491 num_data_desc++;
1492 bam_sys_gen_event(&bam, DATA_PRODUCER_PIPE_INDEX, num_data_desc);
1493 }
1494
1495 /* Write addr loc 0. */
1496 bam_add_cmd_element(cmd_list_ptr,
1497 NAND_READ_LOCATION_n(0),
1498 (uint32_t)addr_loc_0,
1499 CE_WRITE_TYPE);
1500
1501 cmd_list_ptr++;
1502 bam_add_cmd_element(cmd_list_ptr,
1503 NAND_EXEC_CMD,
1504 (uint32_t)params.exec,
1505 CE_WRITE_TYPE);
1506 cmd_list_ptr++;
1507
Sundarajan Srinivasan024bda52014-02-27 16:48:48 -08001508 /* Enqueue the desc for the above commands */
1509 bam_add_one_desc(&bam,
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001510 CMD_PIPE_INDEX,
1511 (unsigned char*)cmd_list_ptr_start,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001512 PA((uint32_t)cmd_list_ptr - (uint32_t)cmd_list_ptr_start),
Sundarajan Srinivasan024bda52014-02-27 16:48:48 -08001513 BAM_DESC_NWD_FLAG | BAM_DESC_CMD_FLAG);
1514 num_cmd_desc++;
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001515
Sundarajan Srinivasan024bda52014-02-27 16:48:48 -08001516 bam_add_cmd_element(cmd_list_ptr, NAND_FLASH_STATUS, (uint32_t)PA((addr_t)&(flash_sts[i])), CE_READ_TYPE);
1517
vijay kumar4f4405f2014-08-08 11:49:53 +05301518 cmd_list_temp = (uint32_t *)cmd_list_ptr;
Sundarajan Srinivasan024bda52014-02-27 16:48:48 -08001519
1520 cmd_list_ptr++;
1521
1522 bam_add_cmd_element(cmd_list_ptr, NAND_BUFFER_STATUS, (uint32_t)PA((addr_t)&(buffer_sts[i])), CE_READ_TYPE);
1523 cmd_list_ptr++;
1524
1525 if (i == flash.cws_per_page - 1)
1526 {
1527 flags = BAM_DESC_CMD_FLAG | BAM_DESC_UNLOCK_FLAG;
1528 }
1529 else
1530 flags = BAM_DESC_CMD_FLAG;
1531
1532 /* Enqueue the desc for the above command */
1533 bam_add_one_desc(&bam,
1534 CMD_PIPE_INDEX,
1535 (unsigned char*)PA((addr_t)cmd_list_temp),
1536 PA((uint32_t)cmd_list_ptr - (uint32_t)cmd_list_temp),
1537 flags);
1538 num_cmd_desc++;
1539
1540 buffer += DATA_BYTES_IN_IMG_PER_CW;
1541
1542 /* Notify BAM HW about the newly added descriptors */
1543 bam_sys_gen_event(&bam, CMD_PIPE_INDEX, num_cmd_desc);
1544 }
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001545
1546 qpic_nand_wait_for_data(DATA_PRODUCER_PIPE_INDEX);
1547
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001548 /* Check status */
1549 for (i = 0; i < flash.cws_per_page ; i ++)
Sundarajan Srinivasan024bda52014-02-27 16:48:48 -08001550 {
1551 flash_sts[i] = qpic_nand_check_status(flash_sts[i]);
Deepa Dinamani19530062012-10-03 14:43:05 -07001552 if (flash_sts[i])
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001553 {
1554 nand_ret = NANDC_RESULT_BAD_PAGE;
Sundarajan Srinivasan024bda52014-02-27 16:48:48 -08001555 dprintf(CRITICAL, "NAND page read failed. page: %x status %x\n", page, flash_sts[i]);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001556 goto qpic_nand_read_page_error;
1557 }
Sundarajan Srinivasan024bda52014-02-27 16:48:48 -08001558 }
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001559qpic_nand_read_page_error:
1560return nand_ret;
1561}
1562
Tanya Brokhman72b44dc2015-01-07 10:20:05 +02001563/**
1564 * qpic_nand_read() - read data
1565 * @start_page: number of page to begin reading from
1566 * @num_pages: number of pages to read
1567 * @buffer: buffer where to store the read data
1568 * @spareaddr: buffer where to store spare data.
1569 * If null, spare data wont be read
1570 *
1571 * This function reads @num_pages starting from @start_page and stores the
1572 * read data in buffer. Note that it's in the caller responsibility to make
1573 * sure the read pages are all from same partition.
1574 *
1575 * Returns nand_result_t
1576 */
1577nand_result_t qpic_nand_read(uint32_t start_page, uint32_t num_pages,
1578 unsigned char* buffer, unsigned char* spareaddr)
1579{
1580 unsigned i = 0, ret = 0;
1581
1582 if (!buffer) {
1583 dprintf(CRITICAL, "qpic_nand_read: buffer = null\n");
1584 return NANDC_RESULT_PARAM_INVALID;
1585 }
1586 while (i < num_pages) {
1587 ret = qpic_nand_read_page(start_page + i, buffer + flash.page_size * i,
1588 spareaddr);
1589 i++;
1590 if (ret == NANDC_RESULT_BAD_PAGE)
1591 qpic_nand_mark_badblock(start_page + i);
1592 if (ret) {
1593 dprintf(CRITICAL,
1594 "qpic_nand_read: reading page %d failed with %d err\n",
1595 start_page + i, ret);
1596 return ret;
1597 }
1598 }
1599 return NANDC_RESULT_SUCCESS;
1600}
1601
1602/**
1603 * qpic_nand_write() - read data
1604 * @start_page: number of page to begin writing to
1605 * @num_pages: number of pages to write
1606 * @buffer: buffer to be written
1607 * @write_extra_bytes: true if spare data (ox 0xff) to be written
1608 *
1609 * This function writes @num_pages starting from @start_page. Note that it's
1610 * in the caller responsibility to make sure the written pages are all from
1611 * same partition.
1612 *
1613 * Returns nand_result_t
1614 */
1615nand_result_t qpic_nand_write(uint32_t start_page, uint32_t num_pages,
1616 unsigned char* buffer, unsigned write_extra_bytes)
1617{
1618 int i = 0, ret = NANDC_RESULT_SUCCESS;
1619 uint32_t *spare = (unsigned *)flash_spare_bytes;
1620 uint32_t wsize;
1621 uint32_t spare_byte_count = 0;
1622
1623 if (!buffer) {
1624 dprintf(CRITICAL, "qpic_nand_write: buffer = null\n");
1625 return NANDC_RESULT_PARAM_INVALID;
1626 }
1627 spare_byte_count = ((flash.cw_size * flash.cws_per_page)- flash.page_size);
1628
1629 if (write_extra_bytes)
1630 wsize = flash.page_size + spare_byte_count;
1631 else
1632 wsize = flash.page_size;
1633
1634 memset(spare, 0xff, (spare_byte_count / flash.cws_per_page));
1635
1636 for (i = 0; i < (int)num_pages; i++) {
1637 memcpy(rdwr_buf, buffer, flash.page_size);
1638 if (write_extra_bytes) {
1639 memcpy(rdwr_buf + flash.page_size,
1640 buffer + flash.page_size, spare_byte_count);
1641 ret = qpic_nand_write_page(start_page + i,
1642 NAND_CFG, rdwr_buf, rdwr_buf + flash.page_size);
1643 } else {
1644 ret = qpic_nand_write_page(start_page + i,
1645 NAND_CFG, rdwr_buf, spare);
1646 }
1647 if (ret) {
1648 dprintf(CRITICAL,
1649 "flash_write: write failure @ page %d, block %d\n",
1650 start_page + i,
1651 (start_page + i) / flash.num_pages_per_blk);
1652 if (ret == NANDC_RESULT_BAD_PAGE)
1653 qpic_nand_mark_badblock(start_page + i);
1654 goto out;
1655 }
1656 buffer += wsize;
1657 }
1658out:
1659 return ret;
1660}
1661
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001662/* Function to read a flash partition.
1663 * ptn : Partition to read.
1664 * extra_per_page : Spare data to be read.
1665 * offset : Num of bytes offset into the partition.
1666 * data : Buffer to read the data into.
1667 * bytes : Num of bytes to be read.
1668 */
1669 /* TODO: call this func read_partition. */
1670int
1671flash_read_ext(struct ptentry *ptn,
1672 unsigned extra_per_page,
1673 unsigned offset,
1674 void *data,
1675 unsigned bytes)
1676{
1677 uint32_t page =
1678 (ptn->start * flash.num_pages_per_blk) + (offset / flash.page_size);
1679 uint32_t lastpage = (ptn->start + ptn->length) * flash.num_pages_per_blk;
1680 uint32_t count =
1681 (bytes + flash.page_size - 1 + extra_per_page) / (flash.page_size +
1682 extra_per_page);
1683 uint32_t *spare = (unsigned *)flash_spare_bytes;
1684 uint32_t errors = 0;
1685 unsigned char *image = data;
1686 int result = 0;
1687 uint32_t current_block =
1688 (page - (page & flash.num_pages_per_blk_mask)) / flash.num_pages_per_blk;
1689 uint32_t start_block = ptn->start;
1690 uint32_t start_block_count = 0;
1691 uint32_t isbad = 0;
Deepa Dinamani2f7006c2013-08-19 11:59:38 -07001692 uint32_t current_page;
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001693
1694 /* Verify first byte is at page boundary. */
1695 if (offset & (flash.page_size - 1))
1696 {
1697 dprintf(CRITICAL, "Read request start not at page boundary: %d\n",
1698 offset);
1699 return NANDC_RESULT_PARAM_INVALID;
1700 }
1701
Deepa Dinamani2f7006c2013-08-19 11:59:38 -07001702 current_page = start_block * flash.num_pages_per_blk;
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001703 /* Adjust page offset based on number of bad blocks from start to current page */
1704 if (start_block < current_block)
1705 {
1706 start_block_count = (current_block - start_block);
1707 while (start_block_count
1708 && (start_block < (ptn->start + ptn->length)))
1709 {
Deepa Dinamani2f7006c2013-08-19 11:59:38 -07001710 isbad = qpic_nand_block_isbad(current_page);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001711 if (isbad)
1712 page += flash.num_pages_per_blk;
1713 else
1714 start_block_count--;
1715 start_block++;
Deepa Dinamani2f7006c2013-08-19 11:59:38 -07001716 current_page += flash.num_pages_per_blk;
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001717 }
1718 }
1719
1720 while ((page < lastpage) && !start_block_count)
1721 {
1722 if (count == 0)
1723 {
Deepa Dinamani52aca8d2013-02-05 11:41:41 -08001724 dprintf(SPEW, "flash_read_image: success (%d errors)\n",
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001725 errors);
1726 return NANDC_RESULT_SUCCESS;
1727 }
1728
Sundarajan Srinivasan29d927c2014-02-10 14:11:24 -08001729#if CONTIGUOUS_MEMORY
1730 result = qpic_nand_read_page(page, image, (unsigned char *) spare);
1731#else
1732 result = qpic_nand_read_page(page, rdwr_buf, (unsigned char *) spare);
1733#endif
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001734 if (result == NANDC_RESULT_BAD_PAGE)
1735 {
1736 /* bad page, go to next page. */
1737 page++;
1738 errors++;
1739 continue;
1740 }
1741 else if (result == NANDC_RESULT_BAD_BLOCK)
1742 {
1743 /* bad block, go to next block same offset. */
1744 page += flash.num_pages_per_blk;
1745 errors++;
1746 continue;
1747 }
1748
Sundarajan Srinivasan29d927c2014-02-10 14:11:24 -08001749#ifndef CONTIGUOUS_MEMORY
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001750 /* Copy the read page into correct location. */
1751 memcpy(image, rdwr_buf, flash.page_size);
Sundarajan Srinivasan29d927c2014-02-10 14:11:24 -08001752#endif
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001753 page++;
1754 image += flash.page_size;
1755 /* Copy spare bytes to image */
Sundarajan Srinivasan29d927c2014-02-10 14:11:24 -08001756 if(extra_per_page)
1757 {
1758 memcpy(image, spare, extra_per_page);
1759 image += extra_per_page;
1760 }
1761
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001762 count -= 1;
1763 }
1764
1765 /* could not find enough valid pages before we hit the end */
1766 dprintf(CRITICAL, "flash_read_image: failed (%d errors)\n", errors);
1767 return NANDC_RESULT_FAILURE;
1768}
1769
1770int
1771flash_erase(struct ptentry *ptn)
1772{
Tanya Brokhman646eedb2015-01-06 23:09:54 +02001773 int ret = 0, i;
Deepa Dinamani2467bbb2012-10-02 13:59:58 -07001774
Tanya Brokhman646eedb2015-01-06 23:09:54 +02001775 for (i = 0; i < (int)ptn->length; i++) {
1776 ret = qpic_nand_blk_erase((ptn->start + i) * flash.num_pages_per_blk);
1777 if (ret)
1778 dprintf(CRITICAL, "Erase operation failed @ page #%d\n",
1779 ptn->start + i);
1780 }
Deepa Dinamani2467bbb2012-10-02 13:59:58 -07001781 return ret;
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001782}
Deepa Dinamani2467bbb2012-10-02 13:59:58 -07001783
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001784int
1785flash_ecc_bch_enabled()
1786{
1787 return (flash.ecc_width == NAND_WITH_4_BIT_ECC)? 0 : 1;
1788}
1789
1790int
1791flash_write(struct ptentry *ptn,
Deepa Dinamanic13d5942013-04-30 15:48:53 -07001792 unsigned write_extra_bytes,
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001793 const void *data,
1794 unsigned bytes)
1795{
1796 uint32_t page = ptn->start * flash.num_pages_per_blk;
1797 uint32_t lastpage = (ptn->start + ptn->length) * flash.num_pages_per_blk;
1798 uint32_t *spare = (unsigned *)flash_spare_bytes;
1799 const unsigned char *image = data;
Deepa Dinamanic13d5942013-04-30 15:48:53 -07001800 uint32_t wsize;
Sundarajan Srinivasan223d7002014-02-11 19:48:11 -08001801 uint32_t spare_byte_count = 0;
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001802 int r;
1803
Sundarajan Srinivasan223d7002014-02-11 19:48:11 -08001804 spare_byte_count = ((flash.cw_size * flash.cws_per_page)- flash.page_size);
1805
Deepa Dinamanic13d5942013-04-30 15:48:53 -07001806 if(write_extra_bytes)
Sundarajan Srinivasan223d7002014-02-11 19:48:11 -08001807 wsize = flash.page_size + spare_byte_count;
Deepa Dinamanic13d5942013-04-30 15:48:53 -07001808 else
1809 wsize = flash.page_size;
1810
Sundarajan Srinivasan223d7002014-02-11 19:48:11 -08001811 memset(spare, 0xff, (spare_byte_count / flash.cws_per_page));
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001812
1813 while (bytes > 0)
1814 {
1815 if (bytes < wsize)
1816 {
1817 dprintf(CRITICAL,
1818 "flash_write_image: image undersized (%d < %d)\n",
1819 bytes,
1820 wsize);
1821 return -1;
1822 }
1823
1824 if (page >= lastpage)
1825 {
1826 dprintf(CRITICAL, "flash_write_image: out of space\n");
1827 return -1;
1828 }
1829
1830 if ((page & flash.num_pages_per_blk_mask) == 0)
1831 {
Deepa Dinamani2467bbb2012-10-02 13:59:58 -07001832 if (qpic_nand_blk_erase(page))
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001833 {
1834 dprintf(INFO,
1835 "flash_write_image: bad block @ %d\n",
1836 page / flash.num_pages_per_blk);
1837
1838 page += flash.num_pages_per_blk;
1839 continue;
1840 }
1841 }
1842
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001843 memcpy(rdwr_buf, image, flash.page_size);
1844
Deepa Dinamanic13d5942013-04-30 15:48:53 -07001845 if (write_extra_bytes)
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001846 {
Sundarajan Srinivasan223d7002014-02-11 19:48:11 -08001847 memcpy(rdwr_buf + flash.page_size, image + flash.page_size, spare_byte_count);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001848 r = qpic_nand_write_page(page,
1849 NAND_CFG,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001850 rdwr_buf,
1851 rdwr_buf + flash.page_size);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001852 }
1853 else
1854 {
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001855 r = qpic_nand_write_page(page, NAND_CFG, rdwr_buf, spare);
Deepa Dinamanie4573be2012-08-03 16:32:29 -07001856 }
1857
1858 if (r)
1859 {
1860 dprintf(INFO,
1861 "flash_write_image: write failure @ page %d (src %d)\n",
1862 page,
1863 image - (const unsigned char *)data);
1864
1865 image -= (page & flash.num_pages_per_blk_mask) * wsize;
1866 bytes += (page & flash.num_pages_per_blk_mask) * wsize;
1867 page &= ~flash.num_pages_per_blk_mask;
1868 if (qpic_nand_blk_erase(page))
1869 {
1870 dprintf(INFO,
1871 "flash_write_image: erase failure @ page %d\n",
1872 page);
1873 }
1874
1875 qpic_nand_mark_badblock(page);
1876
1877 dprintf(INFO,
1878 "flash_write_image: restart write @ page %d (src %d)\n",
1879 page, image - (const unsigned char *)data);
1880
1881 page += flash.num_pages_per_blk;
1882 continue;
1883 }
1884 page++;
1885 image += wsize;
1886 bytes -= wsize;
1887 }
1888
1889 /* erase any remaining pages in the partition */
1890 page = (page + flash.num_pages_per_blk_mask) & (~flash.num_pages_per_blk_mask);
1891
1892 while (page < lastpage)
1893 {
1894 if (qpic_nand_blk_erase(page))
1895 {
1896 dprintf(INFO, "flash_write_image: bad block @ %d\n",
1897 page / flash.num_pages_per_blk);
1898 }
1899 page += flash.num_pages_per_blk;
1900 }
1901
1902 dprintf(INFO, "flash_write_image: success\n");
1903 return 0;
1904}
Smita Ghoshf5431c62014-09-18 14:11:14 -07001905
1906uint32_t nand_device_base()
1907{
1908 return nand_base;
1909}