blob: 2f04c698d3b850142218c31989715e97d8b6b746 [file] [log] [blame]
Dipen Dudhat9eae0832011-03-22 09:27:39 +05301/* Integrated Flash Controller NAND Machine Driver
2 *
Prabhakar Kushwahacdd045d2012-01-20 18:38:14 +05303 * Copyright (c) 2012 Freescale Semiconductor, Inc
Dipen Dudhat9eae0832011-03-22 09:27:39 +05304 *
5 * Authors: Dipen Dudhat <Dipen.Dudhat@freescale.com>
6 *
Wolfgang Denkd79de1d2013-07-08 09:37:19 +02007 * SPDX-License-Identifier: GPL-2.0+
Dipen Dudhat9eae0832011-03-22 09:27:39 +05308 */
9
10#include <common.h>
11#include <malloc.h>
Prabhakar Kushwaha895d0392013-04-04 18:44:06 +000012#include <nand.h>
Dipen Dudhat9eae0832011-03-22 09:27:39 +053013
14#include <linux/mtd/mtd.h>
15#include <linux/mtd/nand.h>
16#include <linux/mtd/nand_ecc.h>
17
18#include <asm/io.h>
19#include <asm/errno.h>
York Sun37562f62013-10-22 12:39:02 -070020#include <fsl_ifc.h>
Dipen Dudhat9eae0832011-03-22 09:27:39 +053021
Prabhakar Kushwahaa8759642014-06-12 09:13:08 +053022#ifndef CONFIG_SYS_FSL_IFC_BANK_COUNT
23#define CONFIG_SYS_FSL_IFC_BANK_COUNT 4
24#endif
25
Prabhakar Kushwahaa8759642014-06-12 09:13:08 +053026#define MAX_BANKS CONFIG_SYS_FSL_IFC_BANK_COUNT
Dipen Dudhat9eae0832011-03-22 09:27:39 +053027#define ERR_BYTE 0xFF /* Value returned for read bytes
28 when read failed */
29#define IFC_TIMEOUT_MSECS 10 /* Maximum number of mSecs to wait for IFC
30 NAND Machine */
31
32struct fsl_ifc_ctrl;
33
34/* mtd information per set */
35struct fsl_ifc_mtd {
Dipen Dudhat9eae0832011-03-22 09:27:39 +053036 struct nand_chip chip;
37 struct fsl_ifc_ctrl *ctrl;
38
39 struct device *dev;
40 int bank; /* Chip select bank number */
41 unsigned int bufnum_mask; /* bufnum = page & bufnum_mask */
42 u8 __iomem *vbase; /* Chip select base virtual address */
43};
44
45/* overview of the fsl ifc controller */
46struct fsl_ifc_ctrl {
47 struct nand_hw_control controller;
48 struct fsl_ifc_mtd *chips[MAX_BANKS];
49
50 /* device info */
51 struct fsl_ifc *regs;
52 uint8_t __iomem *addr; /* Address of assigned IFC buffer */
53 unsigned int cs_nand; /* On which chipsel NAND is connected */
54 unsigned int page; /* Last page written to / read from */
55 unsigned int read_bytes; /* Number of bytes read during command */
56 unsigned int column; /* Saved column from SEQIN */
57 unsigned int index; /* Pointer to next byte to 'read' */
58 unsigned int status; /* status read from NEESR after last op */
59 unsigned int oob; /* Non zero if operating on OOB data */
60 unsigned int eccread; /* Non zero for a full-page ECC read */
61};
62
63static struct fsl_ifc_ctrl *ifc_ctrl;
64
65/* 512-byte page with 4-bit ECC, 8-bit */
66static struct nand_ecclayout oob_512_8bit_ecc4 = {
67 .eccbytes = 8,
68 .eccpos = {8, 9, 10, 11, 12, 13, 14, 15},
69 .oobfree = { {0, 5}, {6, 2} },
70};
71
72/* 512-byte page with 4-bit ECC, 16-bit */
73static struct nand_ecclayout oob_512_16bit_ecc4 = {
74 .eccbytes = 8,
75 .eccpos = {8, 9, 10, 11, 12, 13, 14, 15},
76 .oobfree = { {2, 6}, },
77};
78
79/* 2048-byte page size with 4-bit ECC */
80static struct nand_ecclayout oob_2048_ecc4 = {
81 .eccbytes = 32,
82 .eccpos = {
83 8, 9, 10, 11, 12, 13, 14, 15,
84 16, 17, 18, 19, 20, 21, 22, 23,
85 24, 25, 26, 27, 28, 29, 30, 31,
86 32, 33, 34, 35, 36, 37, 38, 39,
87 },
88 .oobfree = { {2, 6}, {40, 24} },
89};
90
91/* 4096-byte page size with 4-bit ECC */
92static struct nand_ecclayout oob_4096_ecc4 = {
93 .eccbytes = 64,
94 .eccpos = {
95 8, 9, 10, 11, 12, 13, 14, 15,
96 16, 17, 18, 19, 20, 21, 22, 23,
97 24, 25, 26, 27, 28, 29, 30, 31,
98 32, 33, 34, 35, 36, 37, 38, 39,
99 40, 41, 42, 43, 44, 45, 46, 47,
100 48, 49, 50, 51, 52, 53, 54, 55,
101 56, 57, 58, 59, 60, 61, 62, 63,
102 64, 65, 66, 67, 68, 69, 70, 71,
103 },
104 .oobfree = { {2, 6}, {72, 56} },
105};
106
107/* 4096-byte page size with 8-bit ECC -- requires 218-byte OOB */
108static struct nand_ecclayout oob_4096_ecc8 = {
109 .eccbytes = 128,
110 .eccpos = {
111 8, 9, 10, 11, 12, 13, 14, 15,
112 16, 17, 18, 19, 20, 21, 22, 23,
113 24, 25, 26, 27, 28, 29, 30, 31,
114 32, 33, 34, 35, 36, 37, 38, 39,
115 40, 41, 42, 43, 44, 45, 46, 47,
116 48, 49, 50, 51, 52, 53, 54, 55,
117 56, 57, 58, 59, 60, 61, 62, 63,
118 64, 65, 66, 67, 68, 69, 70, 71,
119 72, 73, 74, 75, 76, 77, 78, 79,
120 80, 81, 82, 83, 84, 85, 86, 87,
121 88, 89, 90, 91, 92, 93, 94, 95,
122 96, 97, 98, 99, 100, 101, 102, 103,
123 104, 105, 106, 107, 108, 109, 110, 111,
124 112, 113, 114, 115, 116, 117, 118, 119,
125 120, 121, 122, 123, 124, 125, 126, 127,
126 128, 129, 130, 131, 132, 133, 134, 135,
127 },
128 .oobfree = { {2, 6}, {136, 82} },
129};
130
Prabhakar Kushwahaa3aaf1d2013-10-04 10:05:36 +0530131/* 8192-byte page size with 4-bit ECC */
132static struct nand_ecclayout oob_8192_ecc4 = {
133 .eccbytes = 128,
134 .eccpos = {
135 8, 9, 10, 11, 12, 13, 14, 15,
136 16, 17, 18, 19, 20, 21, 22, 23,
137 24, 25, 26, 27, 28, 29, 30, 31,
138 32, 33, 34, 35, 36, 37, 38, 39,
139 40, 41, 42, 43, 44, 45, 46, 47,
140 48, 49, 50, 51, 52, 53, 54, 55,
141 56, 57, 58, 59, 60, 61, 62, 63,
142 64, 65, 66, 67, 68, 69, 70, 71,
143 72, 73, 74, 75, 76, 77, 78, 79,
144 80, 81, 82, 83, 84, 85, 86, 87,
145 88, 89, 90, 91, 92, 93, 94, 95,
146 96, 97, 98, 99, 100, 101, 102, 103,
147 104, 105, 106, 107, 108, 109, 110, 111,
148 112, 113, 114, 115, 116, 117, 118, 119,
149 120, 121, 122, 123, 124, 125, 126, 127,
150 128, 129, 130, 131, 132, 133, 134, 135,
151 },
152 .oobfree = { {2, 6}, {136, 208} },
153};
154
155/* 8192-byte page size with 8-bit ECC -- requires 218-byte OOB */
156static struct nand_ecclayout oob_8192_ecc8 = {
157 .eccbytes = 256,
158 .eccpos = {
159 8, 9, 10, 11, 12, 13, 14, 15,
160 16, 17, 18, 19, 20, 21, 22, 23,
161 24, 25, 26, 27, 28, 29, 30, 31,
162 32, 33, 34, 35, 36, 37, 38, 39,
163 40, 41, 42, 43, 44, 45, 46, 47,
164 48, 49, 50, 51, 52, 53, 54, 55,
165 56, 57, 58, 59, 60, 61, 62, 63,
166 64, 65, 66, 67, 68, 69, 70, 71,
167 72, 73, 74, 75, 76, 77, 78, 79,
168 80, 81, 82, 83, 84, 85, 86, 87,
169 88, 89, 90, 91, 92, 93, 94, 95,
170 96, 97, 98, 99, 100, 101, 102, 103,
171 104, 105, 106, 107, 108, 109, 110, 111,
172 112, 113, 114, 115, 116, 117, 118, 119,
173 120, 121, 122, 123, 124, 125, 126, 127,
174 128, 129, 130, 131, 132, 133, 134, 135,
175 136, 137, 138, 139, 140, 141, 142, 143,
176 144, 145, 146, 147, 148, 149, 150, 151,
177 152, 153, 154, 155, 156, 157, 158, 159,
178 160, 161, 162, 163, 164, 165, 166, 167,
179 168, 169, 170, 171, 172, 173, 174, 175,
180 176, 177, 178, 179, 180, 181, 182, 183,
181 184, 185, 186, 187, 188, 189, 190, 191,
182 192, 193, 194, 195, 196, 197, 198, 199,
183 200, 201, 202, 203, 204, 205, 206, 207,
184 208, 209, 210, 211, 212, 213, 214, 215,
185 216, 217, 218, 219, 220, 221, 222, 223,
186 224, 225, 226, 227, 228, 229, 230, 231,
187 232, 233, 234, 235, 236, 237, 238, 239,
188 240, 241, 242, 243, 244, 245, 246, 247,
189 248, 249, 250, 251, 252, 253, 254, 255,
190 256, 257, 258, 259, 260, 261, 262, 263,
191 },
192 .oobfree = { {2, 6}, {264, 80} },
193};
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530194
195/*
196 * Generic flash bbt descriptors
197 */
198static u8 bbt_pattern[] = {'B', 'b', 't', '0' };
199static u8 mirror_pattern[] = {'1', 't', 'b', 'B' };
200
201static struct nand_bbt_descr bbt_main_descr = {
202 .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE |
203 NAND_BBT_2BIT | NAND_BBT_VERSION,
204 .offs = 2, /* 0 on 8-bit small page */
205 .len = 4,
206 .veroffs = 6,
207 .maxblocks = 4,
208 .pattern = bbt_pattern,
209};
210
211static struct nand_bbt_descr bbt_mirror_descr = {
212 .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE |
213 NAND_BBT_2BIT | NAND_BBT_VERSION,
214 .offs = 2, /* 0 on 8-bit small page */
215 .len = 4,
216 .veroffs = 6,
217 .maxblocks = 4,
218 .pattern = mirror_pattern,
219};
220
221/*
222 * Set up the IFC hardware block and page address fields, and the ifc nand
223 * structure addr field to point to the correct IFC buffer in memory
224 */
225static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob)
226{
227 struct nand_chip *chip = mtd->priv;
228 struct fsl_ifc_mtd *priv = chip->priv;
229 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
230 struct fsl_ifc *ifc = ctrl->regs;
231 int buf_num;
232
233 ctrl->page = page_addr;
234
235 /* Program ROW0/COL0 */
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530236 ifc_out32(&ifc->ifc_nand.row0, page_addr);
237 ifc_out32(&ifc->ifc_nand.col0, (oob ? IFC_NAND_COL_MS : 0) | column);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530238
239 buf_num = page_addr & priv->bufnum_mask;
240
241 ctrl->addr = priv->vbase + buf_num * (mtd->writesize * 2);
242 ctrl->index = column;
243
244 /* for OOB data point to the second half of the buffer */
245 if (oob)
246 ctrl->index += mtd->writesize;
247}
248
249static int is_blank(struct mtd_info *mtd, struct fsl_ifc_ctrl *ctrl,
250 unsigned int bufnum)
251{
252 struct nand_chip *chip = mtd->priv;
253 struct fsl_ifc_mtd *priv = chip->priv;
254 u8 __iomem *addr = priv->vbase + bufnum * (mtd->writesize * 2);
255 u32 __iomem *main = (u32 *)addr;
256 u8 __iomem *oob = addr + mtd->writesize;
257 int i;
258
259 for (i = 0; i < mtd->writesize / 4; i++) {
260 if (__raw_readl(&main[i]) != 0xffffffff)
261 return 0;
262 }
263
264 for (i = 0; i < chip->ecc.layout->eccbytes; i++) {
265 int pos = chip->ecc.layout->eccpos[i];
266
267 if (__raw_readb(&oob[pos]) != 0xff)
268 return 0;
269 }
270
271 return 1;
272}
273
274/* returns nonzero if entire page is blank */
275static int check_read_ecc(struct mtd_info *mtd, struct fsl_ifc_ctrl *ctrl,
276 u32 *eccstat, unsigned int bufnum)
277{
278 u32 reg = eccstat[bufnum / 4];
Prabhakar Kushwahacdd045d2012-01-20 18:38:14 +0530279 int errors;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530280
Prabhakar Kushwahacdd045d2012-01-20 18:38:14 +0530281 errors = (reg >> ((3 - bufnum % 4) * 8)) & 15;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530282
Prabhakar Kushwahacdd045d2012-01-20 18:38:14 +0530283 return errors;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530284}
285
286/*
287 * execute IFC NAND command and wait for it to complete
288 */
289static int fsl_ifc_run_command(struct mtd_info *mtd)
290{
291 struct nand_chip *chip = mtd->priv;
292 struct fsl_ifc_mtd *priv = chip->priv;
293 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
294 struct fsl_ifc *ifc = ctrl->regs;
295 long long end_tick;
296 u32 eccstat[4];
297 int i;
298
299 /* set the chip select for NAND Transaction */
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530300 ifc_out32(&ifc->ifc_nand.nand_csel, ifc_ctrl->cs_nand);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530301
302 /* start read/write seq */
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530303 ifc_out32(&ifc->ifc_nand.nandseq_strt,
304 IFC_NAND_SEQ_STRT_FIR_STRT);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530305
306 /* wait for NAND Machine complete flag or timeout */
307 end_tick = usec2ticks(IFC_TIMEOUT_MSECS * 1000) + get_ticks();
308
309 while (end_tick > get_ticks()) {
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530310 ctrl->status = ifc_in32(&ifc->ifc_nand.nand_evter_stat);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530311
312 if (ctrl->status & IFC_NAND_EVTER_STAT_OPC)
313 break;
314 }
315
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530316 ifc_out32(&ifc->ifc_nand.nand_evter_stat, ctrl->status);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530317
318 if (ctrl->status & IFC_NAND_EVTER_STAT_FTOER)
319 printf("%s: Flash Time Out Error\n", __func__);
320 if (ctrl->status & IFC_NAND_EVTER_STAT_WPER)
321 printf("%s: Write Protect Error\n", __func__);
322
323 if (ctrl->eccread) {
Prabhakar Kushwahacdd045d2012-01-20 18:38:14 +0530324 int errors;
325 int bufnum = ctrl->page & priv->bufnum_mask;
326 int sector = bufnum * chip->ecc.steps;
327 int sector_end = sector + chip->ecc.steps - 1;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530328
Prabhakar Kushwahacdd045d2012-01-20 18:38:14 +0530329 for (i = sector / 4; i <= sector_end / 4; i++)
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530330 eccstat[i] = ifc_in32(&ifc->ifc_nand.nand_eccstat[i]);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530331
Prabhakar Kushwahacdd045d2012-01-20 18:38:14 +0530332 for (i = sector; i <= sector_end; i++) {
333 errors = check_read_ecc(mtd, ctrl, eccstat, i);
334
335 if (errors == 15) {
336 /*
337 * Uncorrectable error.
338 * OK only if the whole page is blank.
339 *
340 * We disable ECCER reporting due to erratum
341 * IFC-A002770 -- so report it now if we
342 * see an uncorrectable error in ECCSTAT.
343 */
344 if (!is_blank(mtd, ctrl, bufnum))
345 ctrl->status |=
346 IFC_NAND_EVTER_STAT_ECCER;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530347 break;
Prabhakar Kushwahacdd045d2012-01-20 18:38:14 +0530348 }
349
350 mtd->ecc_stats.corrected += errors;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530351 }
352
353 ctrl->eccread = 0;
354 }
355
356 /* returns 0 on success otherwise non-zero) */
357 return ctrl->status == IFC_NAND_EVTER_STAT_OPC ? 0 : -EIO;
358}
359
360static void fsl_ifc_do_read(struct nand_chip *chip,
361 int oob,
362 struct mtd_info *mtd)
363{
364 struct fsl_ifc_mtd *priv = chip->priv;
365 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
366 struct fsl_ifc *ifc = ctrl->regs;
367
368 /* Program FIR/IFC_NAND_FCR0 for Small/Large page */
369 if (mtd->writesize > 512) {
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530370 ifc_out32(&ifc->ifc_nand.nand_fir0,
371 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
372 (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP1_SHIFT) |
373 (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP2_SHIFT) |
374 (IFC_FIR_OP_CMD1 << IFC_NAND_FIR0_OP3_SHIFT) |
375 (IFC_FIR_OP_RBCD << IFC_NAND_FIR0_OP4_SHIFT));
376 ifc_out32(&ifc->ifc_nand.nand_fir1, 0x0);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530377
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530378 ifc_out32(&ifc->ifc_nand.nand_fcr0,
379 (NAND_CMD_READ0 << IFC_NAND_FCR0_CMD0_SHIFT) |
380 (NAND_CMD_READSTART << IFC_NAND_FCR0_CMD1_SHIFT));
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530381 } else {
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530382 ifc_out32(&ifc->ifc_nand.nand_fir0,
383 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
384 (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP1_SHIFT) |
385 (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP2_SHIFT) |
386 (IFC_FIR_OP_RBCD << IFC_NAND_FIR0_OP3_SHIFT));
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530387
388 if (oob)
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530389 ifc_out32(&ifc->ifc_nand.nand_fcr0,
390 NAND_CMD_READOOB << IFC_NAND_FCR0_CMD0_SHIFT);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530391 else
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530392 ifc_out32(&ifc->ifc_nand.nand_fcr0,
393 NAND_CMD_READ0 << IFC_NAND_FCR0_CMD0_SHIFT);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530394 }
395}
396
397/* cmdfunc send commands to the IFC NAND Machine */
398static void fsl_ifc_cmdfunc(struct mtd_info *mtd, unsigned int command,
399 int column, int page_addr)
400{
401 struct nand_chip *chip = mtd->priv;
402 struct fsl_ifc_mtd *priv = chip->priv;
403 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
404 struct fsl_ifc *ifc = ctrl->regs;
405
406 /* clear the read buffer */
407 ctrl->read_bytes = 0;
408 if (command != NAND_CMD_PAGEPROG)
409 ctrl->index = 0;
410
411 switch (command) {
412 /* READ0 read the entire buffer to use hardware ECC. */
413 case NAND_CMD_READ0: {
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530414 ifc_out32(&ifc->ifc_nand.nand_fbcr, 0);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530415 set_addr(mtd, 0, page_addr, 0);
416
417 ctrl->read_bytes = mtd->writesize + mtd->oobsize;
418 ctrl->index += column;
419
420 if (chip->ecc.mode == NAND_ECC_HW)
421 ctrl->eccread = 1;
422
423 fsl_ifc_do_read(chip, 0, mtd);
424 fsl_ifc_run_command(mtd);
425 return;
426 }
427
428 /* READOOB reads only the OOB because no ECC is performed. */
429 case NAND_CMD_READOOB:
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530430 ifc_out32(&ifc->ifc_nand.nand_fbcr, mtd->oobsize - column);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530431 set_addr(mtd, column, page_addr, 1);
432
433 ctrl->read_bytes = mtd->writesize + mtd->oobsize;
434
435 fsl_ifc_do_read(chip, 1, mtd);
436 fsl_ifc_run_command(mtd);
437
438 return;
439
440 /* READID must read all possible bytes while CEB is active */
441 case NAND_CMD_READID:
Prabhakar Kushwahaf31cf532012-04-08 18:57:18 +0000442 case NAND_CMD_PARAM: {
443 int timing = IFC_FIR_OP_RB;
444 if (command == NAND_CMD_PARAM)
445 timing = IFC_FIR_OP_RBCD;
446
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530447 ifc_out32(&ifc->ifc_nand.nand_fir0,
448 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
449 (IFC_FIR_OP_UA << IFC_NAND_FIR0_OP1_SHIFT) |
450 (timing << IFC_NAND_FIR0_OP2_SHIFT));
451 ifc_out32(&ifc->ifc_nand.nand_fcr0,
452 command << IFC_NAND_FCR0_CMD0_SHIFT);
453 ifc_out32(&ifc->ifc_nand.row3, column);
Prabhakar Kushwahaf31cf532012-04-08 18:57:18 +0000454
455 /*
456 * although currently it's 8 bytes for READID, we always read
457 * the maximum 256 bytes(for PARAM)
458 */
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530459 ifc_out32(&ifc->ifc_nand.nand_fbcr, 256);
Prabhakar Kushwahaf31cf532012-04-08 18:57:18 +0000460 ctrl->read_bytes = 256;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530461
462 set_addr(mtd, 0, 0, 0);
463 fsl_ifc_run_command(mtd);
464 return;
Prabhakar Kushwahaf31cf532012-04-08 18:57:18 +0000465 }
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530466
467 /* ERASE1 stores the block and page address */
468 case NAND_CMD_ERASE1:
469 set_addr(mtd, 0, page_addr, 0);
470 return;
471
472 /* ERASE2 uses the block and page address from ERASE1 */
473 case NAND_CMD_ERASE2:
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530474 ifc_out32(&ifc->ifc_nand.nand_fir0,
475 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
476 (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP1_SHIFT) |
477 (IFC_FIR_OP_CMD1 << IFC_NAND_FIR0_OP2_SHIFT));
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530478
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530479 ifc_out32(&ifc->ifc_nand.nand_fcr0,
480 (NAND_CMD_ERASE1 << IFC_NAND_FCR0_CMD0_SHIFT) |
481 (NAND_CMD_ERASE2 << IFC_NAND_FCR0_CMD1_SHIFT));
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530482
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530483 ifc_out32(&ifc->ifc_nand.nand_fbcr, 0);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530484 ctrl->read_bytes = 0;
485 fsl_ifc_run_command(mtd);
486 return;
487
488 /* SEQIN sets up the addr buffer and all registers except the length */
489 case NAND_CMD_SEQIN: {
490 u32 nand_fcr0;
491 ctrl->column = column;
492 ctrl->oob = 0;
493
494 if (mtd->writesize > 512) {
495 nand_fcr0 =
496 (NAND_CMD_SEQIN << IFC_NAND_FCR0_CMD0_SHIFT) |
Prabhakar Kushwaha18e6bde2013-10-03 11:35:35 +0530497 (NAND_CMD_STATUS << IFC_NAND_FCR0_CMD1_SHIFT) |
498 (NAND_CMD_PAGEPROG << IFC_NAND_FCR0_CMD2_SHIFT);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530499
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530500 ifc_out32(&ifc->ifc_nand.nand_fir0,
501 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
502 (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP1_SHIFT) |
503 (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP2_SHIFT) |
504 (IFC_FIR_OP_WBCD <<
505 IFC_NAND_FIR0_OP3_SHIFT) |
506 (IFC_FIR_OP_CMD2 << IFC_NAND_FIR0_OP4_SHIFT));
507 ifc_out32(&ifc->ifc_nand.nand_fir1,
508 (IFC_FIR_OP_CW1 << IFC_NAND_FIR1_OP5_SHIFT) |
509 (IFC_FIR_OP_RDSTAT <<
Prabhakar Kushwaha18e6bde2013-10-03 11:35:35 +0530510 IFC_NAND_FIR1_OP6_SHIFT) |
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530511 (IFC_FIR_OP_NOP << IFC_NAND_FIR1_OP7_SHIFT));
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530512 } else {
513 nand_fcr0 = ((NAND_CMD_PAGEPROG <<
514 IFC_NAND_FCR0_CMD1_SHIFT) |
515 (NAND_CMD_SEQIN <<
Prabhakar Kushwaha18e6bde2013-10-03 11:35:35 +0530516 IFC_NAND_FCR0_CMD2_SHIFT) |
517 (NAND_CMD_STATUS <<
518 IFC_NAND_FCR0_CMD3_SHIFT));
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530519
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530520 ifc_out32(&ifc->ifc_nand.nand_fir0,
521 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
522 (IFC_FIR_OP_CMD2 << IFC_NAND_FIR0_OP1_SHIFT) |
523 (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP2_SHIFT) |
524 (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP3_SHIFT) |
525 (IFC_FIR_OP_WBCD << IFC_NAND_FIR0_OP4_SHIFT));
526 ifc_out32(&ifc->ifc_nand.nand_fir1,
527 (IFC_FIR_OP_CMD1 << IFC_NAND_FIR1_OP5_SHIFT) |
528 (IFC_FIR_OP_CW3 << IFC_NAND_FIR1_OP6_SHIFT) |
529 (IFC_FIR_OP_RDSTAT <<
Prabhakar Kushwaha18e6bde2013-10-03 11:35:35 +0530530 IFC_NAND_FIR1_OP7_SHIFT) |
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530531 (IFC_FIR_OP_NOP << IFC_NAND_FIR1_OP8_SHIFT));
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530532
Prabhakar Kushwaha0ed5e772012-01-20 18:39:05 +0530533 if (column >= mtd->writesize)
534 nand_fcr0 |=
535 NAND_CMD_READOOB << IFC_NAND_FCR0_CMD0_SHIFT;
536 else
537 nand_fcr0 |=
538 NAND_CMD_READ0 << IFC_NAND_FCR0_CMD0_SHIFT;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530539 }
540
Prabhakar Kushwaha0ed5e772012-01-20 18:39:05 +0530541 if (column >= mtd->writesize) {
542 /* OOB area --> READOOB */
543 column -= mtd->writesize;
544 ctrl->oob = 1;
545 }
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530546 ifc_out32(&ifc->ifc_nand.nand_fcr0, nand_fcr0);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530547 set_addr(mtd, column, page_addr, ctrl->oob);
548 return;
549 }
550
551 /* PAGEPROG reuses all of the setup from SEQIN and adds the length */
552 case NAND_CMD_PAGEPROG:
553 if (ctrl->oob)
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530554 ifc_out32(&ifc->ifc_nand.nand_fbcr,
555 ctrl->index - ctrl->column);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530556 else
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530557 ifc_out32(&ifc->ifc_nand.nand_fbcr, 0);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530558
559 fsl_ifc_run_command(mtd);
560 return;
561
562 case NAND_CMD_STATUS:
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530563 ifc_out32(&ifc->ifc_nand.nand_fir0,
564 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
565 (IFC_FIR_OP_RB << IFC_NAND_FIR0_OP1_SHIFT));
566 ifc_out32(&ifc->ifc_nand.nand_fcr0,
567 NAND_CMD_STATUS << IFC_NAND_FCR0_CMD0_SHIFT);
568 ifc_out32(&ifc->ifc_nand.nand_fbcr, 1);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530569 set_addr(mtd, 0, 0, 0);
570 ctrl->read_bytes = 1;
571
572 fsl_ifc_run_command(mtd);
573
574 /* Chip sometimes reporting write protect even when it's not */
575 out_8(ctrl->addr, in_8(ctrl->addr) | NAND_STATUS_WP);
576 return;
577
578 case NAND_CMD_RESET:
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530579 ifc_out32(&ifc->ifc_nand.nand_fir0,
580 IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT);
581 ifc_out32(&ifc->ifc_nand.nand_fcr0,
582 NAND_CMD_RESET << IFC_NAND_FCR0_CMD0_SHIFT);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530583 fsl_ifc_run_command(mtd);
584 return;
585
586 default:
587 printf("%s: error, unsupported command 0x%x.\n",
588 __func__, command);
589 }
590}
591
592/*
593 * Write buf to the IFC NAND Controller Data Buffer
594 */
595static void fsl_ifc_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
596{
597 struct nand_chip *chip = mtd->priv;
598 struct fsl_ifc_mtd *priv = chip->priv;
599 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
600 unsigned int bufsize = mtd->writesize + mtd->oobsize;
601
602 if (len <= 0) {
603 printf("%s of %d bytes", __func__, len);
604 ctrl->status = 0;
605 return;
606 }
607
608 if ((unsigned int)len > bufsize - ctrl->index) {
609 printf("%s beyond end of buffer "
610 "(%d requested, %u available)\n",
611 __func__, len, bufsize - ctrl->index);
612 len = bufsize - ctrl->index;
613 }
614
615 memcpy_toio(&ctrl->addr[ctrl->index], buf, len);
616 ctrl->index += len;
617}
618
619/*
620 * read a byte from either the IFC hardware buffer if it has any data left
621 * otherwise issue a command to read a single byte.
622 */
623static u8 fsl_ifc_read_byte(struct mtd_info *mtd)
624{
625 struct nand_chip *chip = mtd->priv;
626 struct fsl_ifc_mtd *priv = chip->priv;
627 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
628
629 /* If there are still bytes in the IFC buffer, then use the
630 * next byte. */
631 if (ctrl->index < ctrl->read_bytes)
632 return in_8(&ctrl->addr[ctrl->index++]);
633
634 printf("%s beyond end of buffer\n", __func__);
635 return ERR_BYTE;
636}
637
638/*
639 * Read two bytes from the IFC hardware buffer
640 * read function for 16-bit buswith
641 */
642static uint8_t fsl_ifc_read_byte16(struct mtd_info *mtd)
643{
644 struct nand_chip *chip = mtd->priv;
645 struct fsl_ifc_mtd *priv = chip->priv;
646 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
647 uint16_t data;
648
649 /*
650 * If there are still bytes in the IFC buffer, then use the
651 * next byte.
652 */
653 if (ctrl->index < ctrl->read_bytes) {
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530654 data = ifc_in16((uint16_t *)&ctrl->
655 addr[ctrl->index]);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530656 ctrl->index += 2;
657 return (uint8_t)data;
658 }
659
660 printf("%s beyond end of buffer\n", __func__);
661 return ERR_BYTE;
662}
663
664/*
665 * Read from the IFC Controller Data Buffer
666 */
667static void fsl_ifc_read_buf(struct mtd_info *mtd, u8 *buf, int len)
668{
669 struct nand_chip *chip = mtd->priv;
670 struct fsl_ifc_mtd *priv = chip->priv;
671 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
672 int avail;
673
674 if (len < 0)
675 return;
676
677 avail = min((unsigned int)len, ctrl->read_bytes - ctrl->index);
678 memcpy_fromio(buf, &ctrl->addr[ctrl->index], avail);
679 ctrl->index += avail;
680
681 if (len > avail)
682 printf("%s beyond end of buffer "
683 "(%d requested, %d available)\n",
684 __func__, len, avail);
685}
686
Heiko Schocherf5895d12014-06-24 10:10:04 +0200687#if defined(CONFIG_MTD_NAND_VERIFY_WRITE)
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530688/*
689 * Verify buffer against the IFC Controller Data Buffer
690 */
691static int fsl_ifc_verify_buf(struct mtd_info *mtd,
692 const u_char *buf, int len)
693{
694 struct nand_chip *chip = mtd->priv;
695 struct fsl_ifc_mtd *priv = chip->priv;
696 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
697 int i;
698
699 if (len < 0) {
700 printf("%s of %d bytes", __func__, len);
701 return -EINVAL;
702 }
703
704 if ((unsigned int)len > ctrl->read_bytes - ctrl->index) {
705 printf("%s beyond end of buffer "
706 "(%d requested, %u available)\n",
707 __func__, len, ctrl->read_bytes - ctrl->index);
708
709 ctrl->index = ctrl->read_bytes;
710 return -EINVAL;
711 }
712
713 for (i = 0; i < len; i++)
714 if (in_8(&ctrl->addr[ctrl->index + i]) != buf[i])
715 break;
716
717 ctrl->index += len;
718 return i == len && ctrl->status == IFC_NAND_EVTER_STAT_OPC ? 0 : -EIO;
719}
Heiko Schocherf5895d12014-06-24 10:10:04 +0200720#endif
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530721
722/* This function is called after Program and Erase Operations to
723 * check for success or failure.
724 */
725static int fsl_ifc_wait(struct mtd_info *mtd, struct nand_chip *chip)
726{
727 struct fsl_ifc_mtd *priv = chip->priv;
728 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
729 struct fsl_ifc *ifc = ctrl->regs;
730 u32 nand_fsr;
731
732 if (ctrl->status != IFC_NAND_EVTER_STAT_OPC)
733 return NAND_STATUS_FAIL;
734
735 /* Use READ_STATUS command, but wait for the device to be ready */
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530736 ifc_out32(&ifc->ifc_nand.nand_fir0,
737 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
738 (IFC_FIR_OP_RDSTAT << IFC_NAND_FIR0_OP1_SHIFT));
739 ifc_out32(&ifc->ifc_nand.nand_fcr0, NAND_CMD_STATUS <<
740 IFC_NAND_FCR0_CMD0_SHIFT);
741 ifc_out32(&ifc->ifc_nand.nand_fbcr, 1);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530742 set_addr(mtd, 0, 0, 0);
743 ctrl->read_bytes = 1;
744
745 fsl_ifc_run_command(mtd);
746
747 if (ctrl->status != IFC_NAND_EVTER_STAT_OPC)
748 return NAND_STATUS_FAIL;
749
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530750 nand_fsr = ifc_in32(&ifc->ifc_nand.nand_fsr);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530751
752 /* Chip sometimes reporting write protect even when it's not */
753 nand_fsr = nand_fsr | NAND_STATUS_WP;
754 return nand_fsr;
755}
756
Sergey Lapin3a38a552013-01-14 03:46:50 +0000757static int fsl_ifc_read_page(struct mtd_info *mtd, struct nand_chip *chip,
758 uint8_t *buf, int oob_required, int page)
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530759{
760 struct fsl_ifc_mtd *priv = chip->priv;
761 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
762
763 fsl_ifc_read_buf(mtd, buf, mtd->writesize);
764 fsl_ifc_read_buf(mtd, chip->oob_poi, mtd->oobsize);
765
766 if (ctrl->status != IFC_NAND_EVTER_STAT_OPC)
767 mtd->ecc_stats.failed++;
768
769 return 0;
770}
771
772/* ECC will be calculated automatically, and errors will be detected in
773 * waitfunc.
774 */
Sergey Lapin3a38a552013-01-14 03:46:50 +0000775static int fsl_ifc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
776 const uint8_t *buf, int oob_required)
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530777{
778 fsl_ifc_write_buf(mtd, buf, mtd->writesize);
779 fsl_ifc_write_buf(mtd, chip->oob_poi, mtd->oobsize);
Sergey Lapin3a38a552013-01-14 03:46:50 +0000780
781 return 0;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530782}
783
784static void fsl_ifc_ctrl_init(void)
785{
786 ifc_ctrl = kzalloc(sizeof(*ifc_ctrl), GFP_KERNEL);
787 if (!ifc_ctrl)
788 return;
789
790 ifc_ctrl->regs = IFC_BASE_ADDR;
791
792 /* clear event registers */
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530793 ifc_out32(&ifc_ctrl->regs->ifc_nand.nand_evter_stat, ~0U);
794 ifc_out32(&ifc_ctrl->regs->ifc_nand.pgrdcmpl_evt_stat, ~0U);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530795
796 /* Enable error and event for any detected errors */
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530797 ifc_out32(&ifc_ctrl->regs->ifc_nand.nand_evter_en,
798 IFC_NAND_EVTER_EN_OPC_EN |
799 IFC_NAND_EVTER_EN_PGRDCMPL_EN |
800 IFC_NAND_EVTER_EN_FTOER_EN |
801 IFC_NAND_EVTER_EN_WPER_EN);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530802
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530803 ifc_out32(&ifc_ctrl->regs->ifc_nand.ncfgr, 0x0);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530804}
805
806static void fsl_ifc_select_chip(struct mtd_info *mtd, int chip)
807{
808}
809
Prabhakar Kushwaha82efc812014-06-12 12:14:00 +0530810static int fsl_ifc_sram_init(uint32_t ver)
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000811{
812 struct fsl_ifc *ifc = ifc_ctrl->regs;
813 uint32_t cs = 0, csor = 0, csor_8k = 0, csor_ext = 0;
Prabhakar Kushwaha82efc812014-06-12 12:14:00 +0530814 uint32_t ncfgr = 0;
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000815 long long end_tick;
816
Prabhakar Kushwaha82efc812014-06-12 12:14:00 +0530817 if (ver > FSL_IFC_V1_1_0) {
818 ncfgr = ifc_in32(&ifc->ifc_nand.ncfgr);
819 ifc_out32(&ifc->ifc_nand.ncfgr, ncfgr | IFC_NAND_SRAM_INIT_EN);
820
821 /* wait for SRAM_INIT bit to be clear or timeout */
822 end_tick = usec2ticks(IFC_TIMEOUT_MSECS * 1000) + get_ticks();
823 while (end_tick > get_ticks()) {
824 ifc_ctrl->status =
825 ifc_in32(&ifc->ifc_nand.nand_evter_stat);
826
827 if (!(ifc_ctrl->status & IFC_NAND_SRAM_INIT_EN))
828 return 0;
829 }
830 printf("fsl-ifc: Failed to Initialise SRAM\n");
831 return 1;
832 }
833
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000834 cs = ifc_ctrl->cs_nand >> IFC_NAND_CSEL_SHIFT;
835
836 /* Save CSOR and CSOR_ext */
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530837 csor = ifc_in32(&ifc_ctrl->regs->csor_cs[cs].csor);
838 csor_ext = ifc_in32(&ifc_ctrl->regs->csor_cs[cs].csor_ext);
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000839
840 /* chage PageSize 8K and SpareSize 1K*/
841 csor_8k = (csor & ~(CSOR_NAND_PGS_MASK)) | 0x0018C000;
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530842 ifc_out32(&ifc_ctrl->regs->csor_cs[cs].csor, csor_8k);
843 ifc_out32(&ifc_ctrl->regs->csor_cs[cs].csor_ext, 0x0000400);
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000844
845 /* READID */
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530846 ifc_out32(&ifc->ifc_nand.nand_fir0,
847 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
848 (IFC_FIR_OP_UA << IFC_NAND_FIR0_OP1_SHIFT) |
849 (IFC_FIR_OP_RB << IFC_NAND_FIR0_OP2_SHIFT));
850 ifc_out32(&ifc->ifc_nand.nand_fcr0,
851 NAND_CMD_READID << IFC_NAND_FCR0_CMD0_SHIFT);
852 ifc_out32(&ifc->ifc_nand.row3, 0x0);
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000853
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530854 ifc_out32(&ifc->ifc_nand.nand_fbcr, 0x0);
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000855
856 /* Program ROW0/COL0 */
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530857 ifc_out32(&ifc->ifc_nand.row0, 0x0);
858 ifc_out32(&ifc->ifc_nand.col0, 0x0);
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000859
860 /* set the chip select for NAND Transaction */
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530861 ifc_out32(&ifc->ifc_nand.nand_csel, ifc_ctrl->cs_nand);
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000862
863 /* start read seq */
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530864 ifc_out32(&ifc->ifc_nand.nandseq_strt, IFC_NAND_SEQ_STRT_FIR_STRT);
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000865
866 /* wait for NAND Machine complete flag or timeout */
867 end_tick = usec2ticks(IFC_TIMEOUT_MSECS * 1000) + get_ticks();
868
869 while (end_tick > get_ticks()) {
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530870 ifc_ctrl->status = ifc_in32(&ifc->ifc_nand.nand_evter_stat);
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000871
872 if (ifc_ctrl->status & IFC_NAND_EVTER_STAT_OPC)
873 break;
874 }
875
Prabhakar Kushwaha82efc812014-06-12 12:14:00 +0530876 if (ifc_ctrl->status != IFC_NAND_EVTER_STAT_OPC) {
877 printf("fsl-ifc: Failed to Initialise SRAM\n");
878 return 1;
879 }
880
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530881 ifc_out32(&ifc->ifc_nand.nand_evter_stat, ifc_ctrl->status);
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000882
883 /* Restore CSOR and CSOR_ext */
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530884 ifc_out32(&ifc_ctrl->regs->csor_cs[cs].csor, csor);
885 ifc_out32(&ifc_ctrl->regs->csor_cs[cs].csor_ext, csor_ext);
Prabhakar Kushwaha82efc812014-06-12 12:14:00 +0530886
887 return 0;
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000888}
889
Prabhakar Kushwaha895d0392013-04-04 18:44:06 +0000890static int fsl_ifc_chip_init(int devnum, u8 *addr)
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530891{
Prabhakar Kushwaha895d0392013-04-04 18:44:06 +0000892 struct mtd_info *mtd = &nand_info[devnum];
893 struct nand_chip *nand;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530894 struct fsl_ifc_mtd *priv;
895 struct nand_ecclayout *layout;
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000896 uint32_t cspr = 0, csor = 0, ver = 0;
Prabhakar Kushwaha82efc812014-06-12 12:14:00 +0530897 int ret = 0;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530898
899 if (!ifc_ctrl) {
900 fsl_ifc_ctrl_init();
901 if (!ifc_ctrl)
902 return -1;
903 }
904
905 priv = kzalloc(sizeof(*priv), GFP_KERNEL);
906 if (!priv)
907 return -ENOMEM;
908
909 priv->ctrl = ifc_ctrl;
Prabhakar Kushwaha895d0392013-04-04 18:44:06 +0000910 priv->vbase = addr;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530911
912 /* Find which chip select it is connected to.
913 */
914 for (priv->bank = 0; priv->bank < MAX_BANKS; priv->bank++) {
Prabhakar Kushwaha895d0392013-04-04 18:44:06 +0000915 phys_addr_t phys_addr = virt_to_phys(addr);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530916
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530917 cspr = ifc_in32(&ifc_ctrl->regs->cspr_cs[priv->bank].cspr);
918 csor = ifc_in32(&ifc_ctrl->regs->csor_cs[priv->bank].csor);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530919
920 if ((cspr & CSPR_V) && (cspr & CSPR_MSEL) == CSPR_MSEL_NAND &&
Prabhakar Kushwaha895d0392013-04-04 18:44:06 +0000921 (cspr & CSPR_BA) == CSPR_PHYS_ADDR(phys_addr)) {
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530922 ifc_ctrl->cs_nand = priv->bank << IFC_NAND_CSEL_SHIFT;
923 break;
924 }
925 }
926
927 if (priv->bank >= MAX_BANKS) {
928 printf("%s: address did not match any "
929 "chip selects\n", __func__);
Prabhakar Kushwahaae25e882012-04-10 22:48:27 +0000930 kfree(priv);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530931 return -ENODEV;
932 }
933
Prabhakar Kushwaha895d0392013-04-04 18:44:06 +0000934 nand = &priv->chip;
935 mtd->priv = nand;
936
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530937 ifc_ctrl->chips[priv->bank] = priv;
938
939 /* fill in nand_chip structure */
940 /* set up function call table */
941
942 nand->write_buf = fsl_ifc_write_buf;
943 nand->read_buf = fsl_ifc_read_buf;
Heiko Schocherf5895d12014-06-24 10:10:04 +0200944#if defined(CONFIG_MTD_NAND_VERIFY_WRITE)
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530945 nand->verify_buf = fsl_ifc_verify_buf;
Heiko Schocherf5895d12014-06-24 10:10:04 +0200946#endif
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530947 nand->select_chip = fsl_ifc_select_chip;
948 nand->cmdfunc = fsl_ifc_cmdfunc;
949 nand->waitfunc = fsl_ifc_wait;
950
951 /* set up nand options */
952 nand->bbt_td = &bbt_main_descr;
953 nand->bbt_md = &bbt_mirror_descr;
954
955 /* set up nand options */
Sergey Lapin3a38a552013-01-14 03:46:50 +0000956 nand->options = NAND_NO_SUBPAGE_WRITE;
957 nand->bbt_options = NAND_BBT_USE_FLASH;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530958
959 if (cspr & CSPR_PORT_SIZE_16) {
960 nand->read_byte = fsl_ifc_read_byte16;
961 nand->options |= NAND_BUSWIDTH_16;
962 } else {
963 nand->read_byte = fsl_ifc_read_byte;
964 }
965
966 nand->controller = &ifc_ctrl->controller;
967 nand->priv = priv;
968
969 nand->ecc.read_page = fsl_ifc_read_page;
970 nand->ecc.write_page = fsl_ifc_write_page;
971
972 /* Hardware generates ECC per 512 Bytes */
973 nand->ecc.size = 512;
974 nand->ecc.bytes = 8;
975
976 switch (csor & CSOR_NAND_PGS_MASK) {
977 case CSOR_NAND_PGS_512:
978 if (nand->options & NAND_BUSWIDTH_16) {
979 layout = &oob_512_16bit_ecc4;
980 } else {
981 layout = &oob_512_8bit_ecc4;
982
983 /* Avoid conflict with bad block marker */
984 bbt_main_descr.offs = 0;
985 bbt_mirror_descr.offs = 0;
986 }
987
Sergey Lapin3a38a552013-01-14 03:46:50 +0000988 nand->ecc.strength = 4;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530989 priv->bufnum_mask = 15;
990 break;
991
992 case CSOR_NAND_PGS_2K:
993 layout = &oob_2048_ecc4;
Sergey Lapin3a38a552013-01-14 03:46:50 +0000994 nand->ecc.strength = 4;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530995 priv->bufnum_mask = 3;
996 break;
997
998 case CSOR_NAND_PGS_4K:
999 if ((csor & CSOR_NAND_ECC_MODE_MASK) ==
1000 CSOR_NAND_ECC_MODE_4) {
1001 layout = &oob_4096_ecc4;
Sergey Lapin3a38a552013-01-14 03:46:50 +00001002 nand->ecc.strength = 4;
Dipen Dudhat9eae0832011-03-22 09:27:39 +05301003 } else {
1004 layout = &oob_4096_ecc8;
Sergey Lapin3a38a552013-01-14 03:46:50 +00001005 nand->ecc.strength = 8;
Dipen Dudhat9eae0832011-03-22 09:27:39 +05301006 nand->ecc.bytes = 16;
1007 }
1008
1009 priv->bufnum_mask = 1;
1010 break;
1011
Prabhakar Kushwahaa3aaf1d2013-10-04 10:05:36 +05301012 case CSOR_NAND_PGS_8K:
1013 if ((csor & CSOR_NAND_ECC_MODE_MASK) ==
1014 CSOR_NAND_ECC_MODE_4) {
1015 layout = &oob_8192_ecc4;
1016 nand->ecc.strength = 4;
1017 } else {
1018 layout = &oob_8192_ecc8;
1019 nand->ecc.strength = 8;
1020 nand->ecc.bytes = 16;
1021 }
1022
1023 priv->bufnum_mask = 0;
1024 break;
1025
1026
Dipen Dudhat9eae0832011-03-22 09:27:39 +05301027 default:
1028 printf("ifc nand: bad csor %#x: bad page size\n", csor);
1029 return -ENODEV;
1030 }
1031
1032 /* Must also set CSOR_NAND_ECC_ENC_EN if DEC_EN set */
1033 if (csor & CSOR_NAND_ECC_DEC_EN) {
1034 nand->ecc.mode = NAND_ECC_HW;
1035 nand->ecc.layout = layout;
1036 } else {
1037 nand->ecc.mode = NAND_ECC_SOFT;
1038 }
1039
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +05301040 ver = ifc_in32(&ifc_ctrl->regs->ifc_rev);
Prabhakar Kushwaha82efc812014-06-12 12:14:00 +05301041 if (ver >= FSL_IFC_V1_1_0)
1042 ret = fsl_ifc_sram_init(ver);
1043 if (ret)
1044 return ret;
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +00001045
Prabhakar Kushwaha5c23a822014-06-14 08:48:19 +05301046 if (ver >= FSL_IFC_V2_0_0)
1047 priv->bufnum_mask = (priv->bufnum_mask * 2) + 1;
1048
Prabhakar Kushwaha895d0392013-04-04 18:44:06 +00001049 ret = nand_scan_ident(mtd, 1, NULL);
1050 if (ret)
1051 return ret;
1052
1053 ret = nand_scan_tail(mtd);
1054 if (ret)
1055 return ret;
1056
1057 ret = nand_register(devnum);
1058 if (ret)
1059 return ret;
Dipen Dudhat9eae0832011-03-22 09:27:39 +05301060 return 0;
1061}
Prabhakar Kushwaha895d0392013-04-04 18:44:06 +00001062
1063#ifndef CONFIG_SYS_NAND_BASE_LIST
1064#define CONFIG_SYS_NAND_BASE_LIST { CONFIG_SYS_NAND_BASE }
1065#endif
1066
1067static unsigned long base_address[CONFIG_SYS_MAX_NAND_DEVICE] =
1068 CONFIG_SYS_NAND_BASE_LIST;
1069
1070void board_nand_init(void)
1071{
1072 int i;
1073
1074 for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++)
1075 fsl_ifc_chip_init(i, (u8 *)base_address[i]);
1076}