blob: be5a16a1ba94fed611b3a733f7b2b1a9fcd524e1 [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 Kushwahadccbf352012-09-12 22:26:05 +000022#define FSL_IFC_V1_1_0 0x01010000
Dipen Dudhat9eae0832011-03-22 09:27:39 +053023#define MAX_BANKS 4
24#define ERR_BYTE 0xFF /* Value returned for read bytes
25 when read failed */
26#define IFC_TIMEOUT_MSECS 10 /* Maximum number of mSecs to wait for IFC
27 NAND Machine */
28
29struct fsl_ifc_ctrl;
30
31/* mtd information per set */
32struct fsl_ifc_mtd {
Dipen Dudhat9eae0832011-03-22 09:27:39 +053033 struct nand_chip chip;
34 struct fsl_ifc_ctrl *ctrl;
35
36 struct device *dev;
37 int bank; /* Chip select bank number */
38 unsigned int bufnum_mask; /* bufnum = page & bufnum_mask */
39 u8 __iomem *vbase; /* Chip select base virtual address */
40};
41
42/* overview of the fsl ifc controller */
43struct fsl_ifc_ctrl {
44 struct nand_hw_control controller;
45 struct fsl_ifc_mtd *chips[MAX_BANKS];
46
47 /* device info */
48 struct fsl_ifc *regs;
49 uint8_t __iomem *addr; /* Address of assigned IFC buffer */
50 unsigned int cs_nand; /* On which chipsel NAND is connected */
51 unsigned int page; /* Last page written to / read from */
52 unsigned int read_bytes; /* Number of bytes read during command */
53 unsigned int column; /* Saved column from SEQIN */
54 unsigned int index; /* Pointer to next byte to 'read' */
55 unsigned int status; /* status read from NEESR after last op */
56 unsigned int oob; /* Non zero if operating on OOB data */
57 unsigned int eccread; /* Non zero for a full-page ECC read */
58};
59
60static struct fsl_ifc_ctrl *ifc_ctrl;
61
62/* 512-byte page with 4-bit ECC, 8-bit */
63static struct nand_ecclayout oob_512_8bit_ecc4 = {
64 .eccbytes = 8,
65 .eccpos = {8, 9, 10, 11, 12, 13, 14, 15},
66 .oobfree = { {0, 5}, {6, 2} },
67};
68
69/* 512-byte page with 4-bit ECC, 16-bit */
70static struct nand_ecclayout oob_512_16bit_ecc4 = {
71 .eccbytes = 8,
72 .eccpos = {8, 9, 10, 11, 12, 13, 14, 15},
73 .oobfree = { {2, 6}, },
74};
75
76/* 2048-byte page size with 4-bit ECC */
77static struct nand_ecclayout oob_2048_ecc4 = {
78 .eccbytes = 32,
79 .eccpos = {
80 8, 9, 10, 11, 12, 13, 14, 15,
81 16, 17, 18, 19, 20, 21, 22, 23,
82 24, 25, 26, 27, 28, 29, 30, 31,
83 32, 33, 34, 35, 36, 37, 38, 39,
84 },
85 .oobfree = { {2, 6}, {40, 24} },
86};
87
88/* 4096-byte page size with 4-bit ECC */
89static struct nand_ecclayout oob_4096_ecc4 = {
90 .eccbytes = 64,
91 .eccpos = {
92 8, 9, 10, 11, 12, 13, 14, 15,
93 16, 17, 18, 19, 20, 21, 22, 23,
94 24, 25, 26, 27, 28, 29, 30, 31,
95 32, 33, 34, 35, 36, 37, 38, 39,
96 40, 41, 42, 43, 44, 45, 46, 47,
97 48, 49, 50, 51, 52, 53, 54, 55,
98 56, 57, 58, 59, 60, 61, 62, 63,
99 64, 65, 66, 67, 68, 69, 70, 71,
100 },
101 .oobfree = { {2, 6}, {72, 56} },
102};
103
104/* 4096-byte page size with 8-bit ECC -- requires 218-byte OOB */
105static struct nand_ecclayout oob_4096_ecc8 = {
106 .eccbytes = 128,
107 .eccpos = {
108 8, 9, 10, 11, 12, 13, 14, 15,
109 16, 17, 18, 19, 20, 21, 22, 23,
110 24, 25, 26, 27, 28, 29, 30, 31,
111 32, 33, 34, 35, 36, 37, 38, 39,
112 40, 41, 42, 43, 44, 45, 46, 47,
113 48, 49, 50, 51, 52, 53, 54, 55,
114 56, 57, 58, 59, 60, 61, 62, 63,
115 64, 65, 66, 67, 68, 69, 70, 71,
116 72, 73, 74, 75, 76, 77, 78, 79,
117 80, 81, 82, 83, 84, 85, 86, 87,
118 88, 89, 90, 91, 92, 93, 94, 95,
119 96, 97, 98, 99, 100, 101, 102, 103,
120 104, 105, 106, 107, 108, 109, 110, 111,
121 112, 113, 114, 115, 116, 117, 118, 119,
122 120, 121, 122, 123, 124, 125, 126, 127,
123 128, 129, 130, 131, 132, 133, 134, 135,
124 },
125 .oobfree = { {2, 6}, {136, 82} },
126};
127
Prabhakar Kushwahaa3aaf1d2013-10-04 10:05:36 +0530128/* 8192-byte page size with 4-bit ECC */
129static struct nand_ecclayout oob_8192_ecc4 = {
130 .eccbytes = 128,
131 .eccpos = {
132 8, 9, 10, 11, 12, 13, 14, 15,
133 16, 17, 18, 19, 20, 21, 22, 23,
134 24, 25, 26, 27, 28, 29, 30, 31,
135 32, 33, 34, 35, 36, 37, 38, 39,
136 40, 41, 42, 43, 44, 45, 46, 47,
137 48, 49, 50, 51, 52, 53, 54, 55,
138 56, 57, 58, 59, 60, 61, 62, 63,
139 64, 65, 66, 67, 68, 69, 70, 71,
140 72, 73, 74, 75, 76, 77, 78, 79,
141 80, 81, 82, 83, 84, 85, 86, 87,
142 88, 89, 90, 91, 92, 93, 94, 95,
143 96, 97, 98, 99, 100, 101, 102, 103,
144 104, 105, 106, 107, 108, 109, 110, 111,
145 112, 113, 114, 115, 116, 117, 118, 119,
146 120, 121, 122, 123, 124, 125, 126, 127,
147 128, 129, 130, 131, 132, 133, 134, 135,
148 },
149 .oobfree = { {2, 6}, {136, 208} },
150};
151
152/* 8192-byte page size with 8-bit ECC -- requires 218-byte OOB */
153static struct nand_ecclayout oob_8192_ecc8 = {
154 .eccbytes = 256,
155 .eccpos = {
156 8, 9, 10, 11, 12, 13, 14, 15,
157 16, 17, 18, 19, 20, 21, 22, 23,
158 24, 25, 26, 27, 28, 29, 30, 31,
159 32, 33, 34, 35, 36, 37, 38, 39,
160 40, 41, 42, 43, 44, 45, 46, 47,
161 48, 49, 50, 51, 52, 53, 54, 55,
162 56, 57, 58, 59, 60, 61, 62, 63,
163 64, 65, 66, 67, 68, 69, 70, 71,
164 72, 73, 74, 75, 76, 77, 78, 79,
165 80, 81, 82, 83, 84, 85, 86, 87,
166 88, 89, 90, 91, 92, 93, 94, 95,
167 96, 97, 98, 99, 100, 101, 102, 103,
168 104, 105, 106, 107, 108, 109, 110, 111,
169 112, 113, 114, 115, 116, 117, 118, 119,
170 120, 121, 122, 123, 124, 125, 126, 127,
171 128, 129, 130, 131, 132, 133, 134, 135,
172 136, 137, 138, 139, 140, 141, 142, 143,
173 144, 145, 146, 147, 148, 149, 150, 151,
174 152, 153, 154, 155, 156, 157, 158, 159,
175 160, 161, 162, 163, 164, 165, 166, 167,
176 168, 169, 170, 171, 172, 173, 174, 175,
177 176, 177, 178, 179, 180, 181, 182, 183,
178 184, 185, 186, 187, 188, 189, 190, 191,
179 192, 193, 194, 195, 196, 197, 198, 199,
180 200, 201, 202, 203, 204, 205, 206, 207,
181 208, 209, 210, 211, 212, 213, 214, 215,
182 216, 217, 218, 219, 220, 221, 222, 223,
183 224, 225, 226, 227, 228, 229, 230, 231,
184 232, 233, 234, 235, 236, 237, 238, 239,
185 240, 241, 242, 243, 244, 245, 246, 247,
186 248, 249, 250, 251, 252, 253, 254, 255,
187 256, 257, 258, 259, 260, 261, 262, 263,
188 },
189 .oobfree = { {2, 6}, {264, 80} },
190};
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530191
192/*
193 * Generic flash bbt descriptors
194 */
195static u8 bbt_pattern[] = {'B', 'b', 't', '0' };
196static u8 mirror_pattern[] = {'1', 't', 'b', 'B' };
197
198static struct nand_bbt_descr bbt_main_descr = {
199 .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE |
200 NAND_BBT_2BIT | NAND_BBT_VERSION,
201 .offs = 2, /* 0 on 8-bit small page */
202 .len = 4,
203 .veroffs = 6,
204 .maxblocks = 4,
205 .pattern = bbt_pattern,
206};
207
208static struct nand_bbt_descr bbt_mirror_descr = {
209 .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE |
210 NAND_BBT_2BIT | NAND_BBT_VERSION,
211 .offs = 2, /* 0 on 8-bit small page */
212 .len = 4,
213 .veroffs = 6,
214 .maxblocks = 4,
215 .pattern = mirror_pattern,
216};
217
218/*
219 * Set up the IFC hardware block and page address fields, and the ifc nand
220 * structure addr field to point to the correct IFC buffer in memory
221 */
222static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob)
223{
224 struct nand_chip *chip = mtd->priv;
225 struct fsl_ifc_mtd *priv = chip->priv;
226 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
227 struct fsl_ifc *ifc = ctrl->regs;
228 int buf_num;
229
230 ctrl->page = page_addr;
231
232 /* Program ROW0/COL0 */
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530233 ifc_out32(&ifc->ifc_nand.row0, page_addr);
234 ifc_out32(&ifc->ifc_nand.col0, (oob ? IFC_NAND_COL_MS : 0) | column);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530235
236 buf_num = page_addr & priv->bufnum_mask;
237
238 ctrl->addr = priv->vbase + buf_num * (mtd->writesize * 2);
239 ctrl->index = column;
240
241 /* for OOB data point to the second half of the buffer */
242 if (oob)
243 ctrl->index += mtd->writesize;
244}
245
246static int is_blank(struct mtd_info *mtd, struct fsl_ifc_ctrl *ctrl,
247 unsigned int bufnum)
248{
249 struct nand_chip *chip = mtd->priv;
250 struct fsl_ifc_mtd *priv = chip->priv;
251 u8 __iomem *addr = priv->vbase + bufnum * (mtd->writesize * 2);
252 u32 __iomem *main = (u32 *)addr;
253 u8 __iomem *oob = addr + mtd->writesize;
254 int i;
255
256 for (i = 0; i < mtd->writesize / 4; i++) {
257 if (__raw_readl(&main[i]) != 0xffffffff)
258 return 0;
259 }
260
261 for (i = 0; i < chip->ecc.layout->eccbytes; i++) {
262 int pos = chip->ecc.layout->eccpos[i];
263
264 if (__raw_readb(&oob[pos]) != 0xff)
265 return 0;
266 }
267
268 return 1;
269}
270
271/* returns nonzero if entire page is blank */
272static int check_read_ecc(struct mtd_info *mtd, struct fsl_ifc_ctrl *ctrl,
273 u32 *eccstat, unsigned int bufnum)
274{
275 u32 reg = eccstat[bufnum / 4];
Prabhakar Kushwahacdd045d2012-01-20 18:38:14 +0530276 int errors;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530277
Prabhakar Kushwahacdd045d2012-01-20 18:38:14 +0530278 errors = (reg >> ((3 - bufnum % 4) * 8)) & 15;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530279
Prabhakar Kushwahacdd045d2012-01-20 18:38:14 +0530280 return errors;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530281}
282
283/*
284 * execute IFC NAND command and wait for it to complete
285 */
286static int fsl_ifc_run_command(struct mtd_info *mtd)
287{
288 struct nand_chip *chip = mtd->priv;
289 struct fsl_ifc_mtd *priv = chip->priv;
290 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
291 struct fsl_ifc *ifc = ctrl->regs;
292 long long end_tick;
293 u32 eccstat[4];
294 int i;
295
296 /* set the chip select for NAND Transaction */
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530297 ifc_out32(&ifc->ifc_nand.nand_csel, ifc_ctrl->cs_nand);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530298
299 /* start read/write seq */
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530300 ifc_out32(&ifc->ifc_nand.nandseq_strt,
301 IFC_NAND_SEQ_STRT_FIR_STRT);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530302
303 /* wait for NAND Machine complete flag or timeout */
304 end_tick = usec2ticks(IFC_TIMEOUT_MSECS * 1000) + get_ticks();
305
306 while (end_tick > get_ticks()) {
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530307 ctrl->status = ifc_in32(&ifc->ifc_nand.nand_evter_stat);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530308
309 if (ctrl->status & IFC_NAND_EVTER_STAT_OPC)
310 break;
311 }
312
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530313 ifc_out32(&ifc->ifc_nand.nand_evter_stat, ctrl->status);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530314
315 if (ctrl->status & IFC_NAND_EVTER_STAT_FTOER)
316 printf("%s: Flash Time Out Error\n", __func__);
317 if (ctrl->status & IFC_NAND_EVTER_STAT_WPER)
318 printf("%s: Write Protect Error\n", __func__);
319
320 if (ctrl->eccread) {
Prabhakar Kushwahacdd045d2012-01-20 18:38:14 +0530321 int errors;
322 int bufnum = ctrl->page & priv->bufnum_mask;
323 int sector = bufnum * chip->ecc.steps;
324 int sector_end = sector + chip->ecc.steps - 1;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530325
Prabhakar Kushwahacdd045d2012-01-20 18:38:14 +0530326 for (i = sector / 4; i <= sector_end / 4; i++)
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530327 eccstat[i] = ifc_in32(&ifc->ifc_nand.nand_eccstat[i]);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530328
Prabhakar Kushwahacdd045d2012-01-20 18:38:14 +0530329 for (i = sector; i <= sector_end; i++) {
330 errors = check_read_ecc(mtd, ctrl, eccstat, i);
331
332 if (errors == 15) {
333 /*
334 * Uncorrectable error.
335 * OK only if the whole page is blank.
336 *
337 * We disable ECCER reporting due to erratum
338 * IFC-A002770 -- so report it now if we
339 * see an uncorrectable error in ECCSTAT.
340 */
341 if (!is_blank(mtd, ctrl, bufnum))
342 ctrl->status |=
343 IFC_NAND_EVTER_STAT_ECCER;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530344 break;
Prabhakar Kushwahacdd045d2012-01-20 18:38:14 +0530345 }
346
347 mtd->ecc_stats.corrected += errors;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530348 }
349
350 ctrl->eccread = 0;
351 }
352
353 /* returns 0 on success otherwise non-zero) */
354 return ctrl->status == IFC_NAND_EVTER_STAT_OPC ? 0 : -EIO;
355}
356
357static void fsl_ifc_do_read(struct nand_chip *chip,
358 int oob,
359 struct mtd_info *mtd)
360{
361 struct fsl_ifc_mtd *priv = chip->priv;
362 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
363 struct fsl_ifc *ifc = ctrl->regs;
364
365 /* Program FIR/IFC_NAND_FCR0 for Small/Large page */
366 if (mtd->writesize > 512) {
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530367 ifc_out32(&ifc->ifc_nand.nand_fir0,
368 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
369 (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP1_SHIFT) |
370 (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP2_SHIFT) |
371 (IFC_FIR_OP_CMD1 << IFC_NAND_FIR0_OP3_SHIFT) |
372 (IFC_FIR_OP_RBCD << IFC_NAND_FIR0_OP4_SHIFT));
373 ifc_out32(&ifc->ifc_nand.nand_fir1, 0x0);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530374
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530375 ifc_out32(&ifc->ifc_nand.nand_fcr0,
376 (NAND_CMD_READ0 << IFC_NAND_FCR0_CMD0_SHIFT) |
377 (NAND_CMD_READSTART << IFC_NAND_FCR0_CMD1_SHIFT));
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530378 } else {
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530379 ifc_out32(&ifc->ifc_nand.nand_fir0,
380 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
381 (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP1_SHIFT) |
382 (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP2_SHIFT) |
383 (IFC_FIR_OP_RBCD << IFC_NAND_FIR0_OP3_SHIFT));
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530384
385 if (oob)
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530386 ifc_out32(&ifc->ifc_nand.nand_fcr0,
387 NAND_CMD_READOOB << IFC_NAND_FCR0_CMD0_SHIFT);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530388 else
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530389 ifc_out32(&ifc->ifc_nand.nand_fcr0,
390 NAND_CMD_READ0 << IFC_NAND_FCR0_CMD0_SHIFT);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530391 }
392}
393
394/* cmdfunc send commands to the IFC NAND Machine */
395static void fsl_ifc_cmdfunc(struct mtd_info *mtd, unsigned int command,
396 int column, int page_addr)
397{
398 struct nand_chip *chip = mtd->priv;
399 struct fsl_ifc_mtd *priv = chip->priv;
400 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
401 struct fsl_ifc *ifc = ctrl->regs;
402
403 /* clear the read buffer */
404 ctrl->read_bytes = 0;
405 if (command != NAND_CMD_PAGEPROG)
406 ctrl->index = 0;
407
408 switch (command) {
409 /* READ0 read the entire buffer to use hardware ECC. */
410 case NAND_CMD_READ0: {
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530411 ifc_out32(&ifc->ifc_nand.nand_fbcr, 0);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530412 set_addr(mtd, 0, page_addr, 0);
413
414 ctrl->read_bytes = mtd->writesize + mtd->oobsize;
415 ctrl->index += column;
416
417 if (chip->ecc.mode == NAND_ECC_HW)
418 ctrl->eccread = 1;
419
420 fsl_ifc_do_read(chip, 0, mtd);
421 fsl_ifc_run_command(mtd);
422 return;
423 }
424
425 /* READOOB reads only the OOB because no ECC is performed. */
426 case NAND_CMD_READOOB:
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530427 ifc_out32(&ifc->ifc_nand.nand_fbcr, mtd->oobsize - column);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530428 set_addr(mtd, column, page_addr, 1);
429
430 ctrl->read_bytes = mtd->writesize + mtd->oobsize;
431
432 fsl_ifc_do_read(chip, 1, mtd);
433 fsl_ifc_run_command(mtd);
434
435 return;
436
437 /* READID must read all possible bytes while CEB is active */
438 case NAND_CMD_READID:
Prabhakar Kushwahaf31cf532012-04-08 18:57:18 +0000439 case NAND_CMD_PARAM: {
440 int timing = IFC_FIR_OP_RB;
441 if (command == NAND_CMD_PARAM)
442 timing = IFC_FIR_OP_RBCD;
443
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530444 ifc_out32(&ifc->ifc_nand.nand_fir0,
445 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
446 (IFC_FIR_OP_UA << IFC_NAND_FIR0_OP1_SHIFT) |
447 (timing << IFC_NAND_FIR0_OP2_SHIFT));
448 ifc_out32(&ifc->ifc_nand.nand_fcr0,
449 command << IFC_NAND_FCR0_CMD0_SHIFT);
450 ifc_out32(&ifc->ifc_nand.row3, column);
Prabhakar Kushwahaf31cf532012-04-08 18:57:18 +0000451
452 /*
453 * although currently it's 8 bytes for READID, we always read
454 * the maximum 256 bytes(for PARAM)
455 */
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530456 ifc_out32(&ifc->ifc_nand.nand_fbcr, 256);
Prabhakar Kushwahaf31cf532012-04-08 18:57:18 +0000457 ctrl->read_bytes = 256;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530458
459 set_addr(mtd, 0, 0, 0);
460 fsl_ifc_run_command(mtd);
461 return;
Prabhakar Kushwahaf31cf532012-04-08 18:57:18 +0000462 }
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530463
464 /* ERASE1 stores the block and page address */
465 case NAND_CMD_ERASE1:
466 set_addr(mtd, 0, page_addr, 0);
467 return;
468
469 /* ERASE2 uses the block and page address from ERASE1 */
470 case NAND_CMD_ERASE2:
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530471 ifc_out32(&ifc->ifc_nand.nand_fir0,
472 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
473 (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP1_SHIFT) |
474 (IFC_FIR_OP_CMD1 << IFC_NAND_FIR0_OP2_SHIFT));
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530475
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530476 ifc_out32(&ifc->ifc_nand.nand_fcr0,
477 (NAND_CMD_ERASE1 << IFC_NAND_FCR0_CMD0_SHIFT) |
478 (NAND_CMD_ERASE2 << IFC_NAND_FCR0_CMD1_SHIFT));
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530479
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530480 ifc_out32(&ifc->ifc_nand.nand_fbcr, 0);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530481 ctrl->read_bytes = 0;
482 fsl_ifc_run_command(mtd);
483 return;
484
485 /* SEQIN sets up the addr buffer and all registers except the length */
486 case NAND_CMD_SEQIN: {
487 u32 nand_fcr0;
488 ctrl->column = column;
489 ctrl->oob = 0;
490
491 if (mtd->writesize > 512) {
492 nand_fcr0 =
493 (NAND_CMD_SEQIN << IFC_NAND_FCR0_CMD0_SHIFT) |
Prabhakar Kushwaha18e6bde2013-10-03 11:35:35 +0530494 (NAND_CMD_STATUS << IFC_NAND_FCR0_CMD1_SHIFT) |
495 (NAND_CMD_PAGEPROG << IFC_NAND_FCR0_CMD2_SHIFT);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530496
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530497 ifc_out32(&ifc->ifc_nand.nand_fir0,
498 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
499 (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP1_SHIFT) |
500 (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP2_SHIFT) |
501 (IFC_FIR_OP_WBCD <<
502 IFC_NAND_FIR0_OP3_SHIFT) |
503 (IFC_FIR_OP_CMD2 << IFC_NAND_FIR0_OP4_SHIFT));
504 ifc_out32(&ifc->ifc_nand.nand_fir1,
505 (IFC_FIR_OP_CW1 << IFC_NAND_FIR1_OP5_SHIFT) |
506 (IFC_FIR_OP_RDSTAT <<
Prabhakar Kushwaha18e6bde2013-10-03 11:35:35 +0530507 IFC_NAND_FIR1_OP6_SHIFT) |
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530508 (IFC_FIR_OP_NOP << IFC_NAND_FIR1_OP7_SHIFT));
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530509 } else {
510 nand_fcr0 = ((NAND_CMD_PAGEPROG <<
511 IFC_NAND_FCR0_CMD1_SHIFT) |
512 (NAND_CMD_SEQIN <<
Prabhakar Kushwaha18e6bde2013-10-03 11:35:35 +0530513 IFC_NAND_FCR0_CMD2_SHIFT) |
514 (NAND_CMD_STATUS <<
515 IFC_NAND_FCR0_CMD3_SHIFT));
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530516
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530517 ifc_out32(&ifc->ifc_nand.nand_fir0,
518 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
519 (IFC_FIR_OP_CMD2 << IFC_NAND_FIR0_OP1_SHIFT) |
520 (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP2_SHIFT) |
521 (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP3_SHIFT) |
522 (IFC_FIR_OP_WBCD << IFC_NAND_FIR0_OP4_SHIFT));
523 ifc_out32(&ifc->ifc_nand.nand_fir1,
524 (IFC_FIR_OP_CMD1 << IFC_NAND_FIR1_OP5_SHIFT) |
525 (IFC_FIR_OP_CW3 << IFC_NAND_FIR1_OP6_SHIFT) |
526 (IFC_FIR_OP_RDSTAT <<
Prabhakar Kushwaha18e6bde2013-10-03 11:35:35 +0530527 IFC_NAND_FIR1_OP7_SHIFT) |
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530528 (IFC_FIR_OP_NOP << IFC_NAND_FIR1_OP8_SHIFT));
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530529
Prabhakar Kushwaha0ed5e772012-01-20 18:39:05 +0530530 if (column >= mtd->writesize)
531 nand_fcr0 |=
532 NAND_CMD_READOOB << IFC_NAND_FCR0_CMD0_SHIFT;
533 else
534 nand_fcr0 |=
535 NAND_CMD_READ0 << IFC_NAND_FCR0_CMD0_SHIFT;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530536 }
537
Prabhakar Kushwaha0ed5e772012-01-20 18:39:05 +0530538 if (column >= mtd->writesize) {
539 /* OOB area --> READOOB */
540 column -= mtd->writesize;
541 ctrl->oob = 1;
542 }
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530543 ifc_out32(&ifc->ifc_nand.nand_fcr0, nand_fcr0);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530544 set_addr(mtd, column, page_addr, ctrl->oob);
545 return;
546 }
547
548 /* PAGEPROG reuses all of the setup from SEQIN and adds the length */
549 case NAND_CMD_PAGEPROG:
550 if (ctrl->oob)
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530551 ifc_out32(&ifc->ifc_nand.nand_fbcr,
552 ctrl->index - ctrl->column);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530553 else
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530554 ifc_out32(&ifc->ifc_nand.nand_fbcr, 0);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530555
556 fsl_ifc_run_command(mtd);
557 return;
558
559 case NAND_CMD_STATUS:
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530560 ifc_out32(&ifc->ifc_nand.nand_fir0,
561 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
562 (IFC_FIR_OP_RB << IFC_NAND_FIR0_OP1_SHIFT));
563 ifc_out32(&ifc->ifc_nand.nand_fcr0,
564 NAND_CMD_STATUS << IFC_NAND_FCR0_CMD0_SHIFT);
565 ifc_out32(&ifc->ifc_nand.nand_fbcr, 1);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530566 set_addr(mtd, 0, 0, 0);
567 ctrl->read_bytes = 1;
568
569 fsl_ifc_run_command(mtd);
570
571 /* Chip sometimes reporting write protect even when it's not */
572 out_8(ctrl->addr, in_8(ctrl->addr) | NAND_STATUS_WP);
573 return;
574
575 case NAND_CMD_RESET:
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530576 ifc_out32(&ifc->ifc_nand.nand_fir0,
577 IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT);
578 ifc_out32(&ifc->ifc_nand.nand_fcr0,
579 NAND_CMD_RESET << IFC_NAND_FCR0_CMD0_SHIFT);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530580 fsl_ifc_run_command(mtd);
581 return;
582
583 default:
584 printf("%s: error, unsupported command 0x%x.\n",
585 __func__, command);
586 }
587}
588
589/*
590 * Write buf to the IFC NAND Controller Data Buffer
591 */
592static void fsl_ifc_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
593{
594 struct nand_chip *chip = mtd->priv;
595 struct fsl_ifc_mtd *priv = chip->priv;
596 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
597 unsigned int bufsize = mtd->writesize + mtd->oobsize;
598
599 if (len <= 0) {
600 printf("%s of %d bytes", __func__, len);
601 ctrl->status = 0;
602 return;
603 }
604
605 if ((unsigned int)len > bufsize - ctrl->index) {
606 printf("%s beyond end of buffer "
607 "(%d requested, %u available)\n",
608 __func__, len, bufsize - ctrl->index);
609 len = bufsize - ctrl->index;
610 }
611
612 memcpy_toio(&ctrl->addr[ctrl->index], buf, len);
613 ctrl->index += len;
614}
615
616/*
617 * read a byte from either the IFC hardware buffer if it has any data left
618 * otherwise issue a command to read a single byte.
619 */
620static u8 fsl_ifc_read_byte(struct mtd_info *mtd)
621{
622 struct nand_chip *chip = mtd->priv;
623 struct fsl_ifc_mtd *priv = chip->priv;
624 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
625
626 /* If there are still bytes in the IFC buffer, then use the
627 * next byte. */
628 if (ctrl->index < ctrl->read_bytes)
629 return in_8(&ctrl->addr[ctrl->index++]);
630
631 printf("%s beyond end of buffer\n", __func__);
632 return ERR_BYTE;
633}
634
635/*
636 * Read two bytes from the IFC hardware buffer
637 * read function for 16-bit buswith
638 */
639static uint8_t fsl_ifc_read_byte16(struct mtd_info *mtd)
640{
641 struct nand_chip *chip = mtd->priv;
642 struct fsl_ifc_mtd *priv = chip->priv;
643 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
644 uint16_t data;
645
646 /*
647 * If there are still bytes in the IFC buffer, then use the
648 * next byte.
649 */
650 if (ctrl->index < ctrl->read_bytes) {
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530651 data = ifc_in16((uint16_t *)&ctrl->
652 addr[ctrl->index]);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530653 ctrl->index += 2;
654 return (uint8_t)data;
655 }
656
657 printf("%s beyond end of buffer\n", __func__);
658 return ERR_BYTE;
659}
660
661/*
662 * Read from the IFC Controller Data Buffer
663 */
664static void fsl_ifc_read_buf(struct mtd_info *mtd, u8 *buf, int len)
665{
666 struct nand_chip *chip = mtd->priv;
667 struct fsl_ifc_mtd *priv = chip->priv;
668 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
669 int avail;
670
671 if (len < 0)
672 return;
673
674 avail = min((unsigned int)len, ctrl->read_bytes - ctrl->index);
675 memcpy_fromio(buf, &ctrl->addr[ctrl->index], avail);
676 ctrl->index += avail;
677
678 if (len > avail)
679 printf("%s beyond end of buffer "
680 "(%d requested, %d available)\n",
681 __func__, len, avail);
682}
683
684/*
685 * Verify buffer against the IFC Controller Data Buffer
686 */
687static int fsl_ifc_verify_buf(struct mtd_info *mtd,
688 const u_char *buf, int len)
689{
690 struct nand_chip *chip = mtd->priv;
691 struct fsl_ifc_mtd *priv = chip->priv;
692 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
693 int i;
694
695 if (len < 0) {
696 printf("%s of %d bytes", __func__, len);
697 return -EINVAL;
698 }
699
700 if ((unsigned int)len > ctrl->read_bytes - ctrl->index) {
701 printf("%s beyond end of buffer "
702 "(%d requested, %u available)\n",
703 __func__, len, ctrl->read_bytes - ctrl->index);
704
705 ctrl->index = ctrl->read_bytes;
706 return -EINVAL;
707 }
708
709 for (i = 0; i < len; i++)
710 if (in_8(&ctrl->addr[ctrl->index + i]) != buf[i])
711 break;
712
713 ctrl->index += len;
714 return i == len && ctrl->status == IFC_NAND_EVTER_STAT_OPC ? 0 : -EIO;
715}
716
717/* This function is called after Program and Erase Operations to
718 * check for success or failure.
719 */
720static int fsl_ifc_wait(struct mtd_info *mtd, struct nand_chip *chip)
721{
722 struct fsl_ifc_mtd *priv = chip->priv;
723 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
724 struct fsl_ifc *ifc = ctrl->regs;
725 u32 nand_fsr;
726
727 if (ctrl->status != IFC_NAND_EVTER_STAT_OPC)
728 return NAND_STATUS_FAIL;
729
730 /* Use READ_STATUS command, but wait for the device to be ready */
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530731 ifc_out32(&ifc->ifc_nand.nand_fir0,
732 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
733 (IFC_FIR_OP_RDSTAT << IFC_NAND_FIR0_OP1_SHIFT));
734 ifc_out32(&ifc->ifc_nand.nand_fcr0, NAND_CMD_STATUS <<
735 IFC_NAND_FCR0_CMD0_SHIFT);
736 ifc_out32(&ifc->ifc_nand.nand_fbcr, 1);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530737 set_addr(mtd, 0, 0, 0);
738 ctrl->read_bytes = 1;
739
740 fsl_ifc_run_command(mtd);
741
742 if (ctrl->status != IFC_NAND_EVTER_STAT_OPC)
743 return NAND_STATUS_FAIL;
744
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530745 nand_fsr = ifc_in32(&ifc->ifc_nand.nand_fsr);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530746
747 /* Chip sometimes reporting write protect even when it's not */
748 nand_fsr = nand_fsr | NAND_STATUS_WP;
749 return nand_fsr;
750}
751
Sergey Lapin3a38a552013-01-14 03:46:50 +0000752static int fsl_ifc_read_page(struct mtd_info *mtd, struct nand_chip *chip,
753 uint8_t *buf, int oob_required, int page)
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530754{
755 struct fsl_ifc_mtd *priv = chip->priv;
756 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
757
758 fsl_ifc_read_buf(mtd, buf, mtd->writesize);
759 fsl_ifc_read_buf(mtd, chip->oob_poi, mtd->oobsize);
760
761 if (ctrl->status != IFC_NAND_EVTER_STAT_OPC)
762 mtd->ecc_stats.failed++;
763
764 return 0;
765}
766
767/* ECC will be calculated automatically, and errors will be detected in
768 * waitfunc.
769 */
Sergey Lapin3a38a552013-01-14 03:46:50 +0000770static int fsl_ifc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
771 const uint8_t *buf, int oob_required)
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530772{
773 fsl_ifc_write_buf(mtd, buf, mtd->writesize);
774 fsl_ifc_write_buf(mtd, chip->oob_poi, mtd->oobsize);
Sergey Lapin3a38a552013-01-14 03:46:50 +0000775
776 return 0;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530777}
778
779static void fsl_ifc_ctrl_init(void)
780{
781 ifc_ctrl = kzalloc(sizeof(*ifc_ctrl), GFP_KERNEL);
782 if (!ifc_ctrl)
783 return;
784
785 ifc_ctrl->regs = IFC_BASE_ADDR;
786
787 /* clear event registers */
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530788 ifc_out32(&ifc_ctrl->regs->ifc_nand.nand_evter_stat, ~0U);
789 ifc_out32(&ifc_ctrl->regs->ifc_nand.pgrdcmpl_evt_stat, ~0U);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530790
791 /* Enable error and event for any detected errors */
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530792 ifc_out32(&ifc_ctrl->regs->ifc_nand.nand_evter_en,
793 IFC_NAND_EVTER_EN_OPC_EN |
794 IFC_NAND_EVTER_EN_PGRDCMPL_EN |
795 IFC_NAND_EVTER_EN_FTOER_EN |
796 IFC_NAND_EVTER_EN_WPER_EN);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530797
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530798 ifc_out32(&ifc_ctrl->regs->ifc_nand.ncfgr, 0x0);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530799}
800
801static void fsl_ifc_select_chip(struct mtd_info *mtd, int chip)
802{
803}
804
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000805static void fsl_ifc_sram_init(void)
806{
807 struct fsl_ifc *ifc = ifc_ctrl->regs;
808 uint32_t cs = 0, csor = 0, csor_8k = 0, csor_ext = 0;
809 long long end_tick;
810
811 cs = ifc_ctrl->cs_nand >> IFC_NAND_CSEL_SHIFT;
812
813 /* Save CSOR and CSOR_ext */
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530814 csor = ifc_in32(&ifc_ctrl->regs->csor_cs[cs].csor);
815 csor_ext = ifc_in32(&ifc_ctrl->regs->csor_cs[cs].csor_ext);
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000816
817 /* chage PageSize 8K and SpareSize 1K*/
818 csor_8k = (csor & ~(CSOR_NAND_PGS_MASK)) | 0x0018C000;
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530819 ifc_out32(&ifc_ctrl->regs->csor_cs[cs].csor, csor_8k);
820 ifc_out32(&ifc_ctrl->regs->csor_cs[cs].csor_ext, 0x0000400);
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000821
822 /* READID */
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530823 ifc_out32(&ifc->ifc_nand.nand_fir0,
824 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
825 (IFC_FIR_OP_UA << IFC_NAND_FIR0_OP1_SHIFT) |
826 (IFC_FIR_OP_RB << IFC_NAND_FIR0_OP2_SHIFT));
827 ifc_out32(&ifc->ifc_nand.nand_fcr0,
828 NAND_CMD_READID << IFC_NAND_FCR0_CMD0_SHIFT);
829 ifc_out32(&ifc->ifc_nand.row3, 0x0);
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000830
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530831 ifc_out32(&ifc->ifc_nand.nand_fbcr, 0x0);
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000832
833 /* Program ROW0/COL0 */
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530834 ifc_out32(&ifc->ifc_nand.row0, 0x0);
835 ifc_out32(&ifc->ifc_nand.col0, 0x0);
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000836
837 /* set the chip select for NAND Transaction */
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530838 ifc_out32(&ifc->ifc_nand.nand_csel, ifc_ctrl->cs_nand);
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000839
840 /* start read seq */
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530841 ifc_out32(&ifc->ifc_nand.nandseq_strt, IFC_NAND_SEQ_STRT_FIR_STRT);
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000842
843 /* wait for NAND Machine complete flag or timeout */
844 end_tick = usec2ticks(IFC_TIMEOUT_MSECS * 1000) + get_ticks();
845
846 while (end_tick > get_ticks()) {
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530847 ifc_ctrl->status = ifc_in32(&ifc->ifc_nand.nand_evter_stat);
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000848
849 if (ifc_ctrl->status & IFC_NAND_EVTER_STAT_OPC)
850 break;
851 }
852
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530853 ifc_out32(&ifc->ifc_nand.nand_evter_stat, ifc_ctrl->status);
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000854
855 /* Restore CSOR and CSOR_ext */
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530856 ifc_out32(&ifc_ctrl->regs->csor_cs[cs].csor, csor);
857 ifc_out32(&ifc_ctrl->regs->csor_cs[cs].csor_ext, csor_ext);
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000858}
859
Prabhakar Kushwaha895d0392013-04-04 18:44:06 +0000860static int fsl_ifc_chip_init(int devnum, u8 *addr)
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530861{
Prabhakar Kushwaha895d0392013-04-04 18:44:06 +0000862 struct mtd_info *mtd = &nand_info[devnum];
863 struct nand_chip *nand;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530864 struct fsl_ifc_mtd *priv;
865 struct nand_ecclayout *layout;
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000866 uint32_t cspr = 0, csor = 0, ver = 0;
Prabhakar Kushwaha895d0392013-04-04 18:44:06 +0000867 int ret;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530868
869 if (!ifc_ctrl) {
870 fsl_ifc_ctrl_init();
871 if (!ifc_ctrl)
872 return -1;
873 }
874
875 priv = kzalloc(sizeof(*priv), GFP_KERNEL);
876 if (!priv)
877 return -ENOMEM;
878
879 priv->ctrl = ifc_ctrl;
Prabhakar Kushwaha895d0392013-04-04 18:44:06 +0000880 priv->vbase = addr;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530881
882 /* Find which chip select it is connected to.
883 */
884 for (priv->bank = 0; priv->bank < MAX_BANKS; priv->bank++) {
Prabhakar Kushwaha895d0392013-04-04 18:44:06 +0000885 phys_addr_t phys_addr = virt_to_phys(addr);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530886
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530887 cspr = ifc_in32(&ifc_ctrl->regs->cspr_cs[priv->bank].cspr);
888 csor = ifc_in32(&ifc_ctrl->regs->csor_cs[priv->bank].csor);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530889
890 if ((cspr & CSPR_V) && (cspr & CSPR_MSEL) == CSPR_MSEL_NAND &&
Prabhakar Kushwaha895d0392013-04-04 18:44:06 +0000891 (cspr & CSPR_BA) == CSPR_PHYS_ADDR(phys_addr)) {
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530892 ifc_ctrl->cs_nand = priv->bank << IFC_NAND_CSEL_SHIFT;
893 break;
894 }
895 }
896
897 if (priv->bank >= MAX_BANKS) {
898 printf("%s: address did not match any "
899 "chip selects\n", __func__);
Prabhakar Kushwahaae25e882012-04-10 22:48:27 +0000900 kfree(priv);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530901 return -ENODEV;
902 }
903
Prabhakar Kushwaha895d0392013-04-04 18:44:06 +0000904 nand = &priv->chip;
905 mtd->priv = nand;
906
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530907 ifc_ctrl->chips[priv->bank] = priv;
908
909 /* fill in nand_chip structure */
910 /* set up function call table */
911
912 nand->write_buf = fsl_ifc_write_buf;
913 nand->read_buf = fsl_ifc_read_buf;
914 nand->verify_buf = fsl_ifc_verify_buf;
915 nand->select_chip = fsl_ifc_select_chip;
916 nand->cmdfunc = fsl_ifc_cmdfunc;
917 nand->waitfunc = fsl_ifc_wait;
918
919 /* set up nand options */
920 nand->bbt_td = &bbt_main_descr;
921 nand->bbt_md = &bbt_mirror_descr;
922
923 /* set up nand options */
Sergey Lapin3a38a552013-01-14 03:46:50 +0000924 nand->options = NAND_NO_SUBPAGE_WRITE;
925 nand->bbt_options = NAND_BBT_USE_FLASH;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530926
927 if (cspr & CSPR_PORT_SIZE_16) {
928 nand->read_byte = fsl_ifc_read_byte16;
929 nand->options |= NAND_BUSWIDTH_16;
930 } else {
931 nand->read_byte = fsl_ifc_read_byte;
932 }
933
934 nand->controller = &ifc_ctrl->controller;
935 nand->priv = priv;
936
937 nand->ecc.read_page = fsl_ifc_read_page;
938 nand->ecc.write_page = fsl_ifc_write_page;
939
940 /* Hardware generates ECC per 512 Bytes */
941 nand->ecc.size = 512;
942 nand->ecc.bytes = 8;
943
944 switch (csor & CSOR_NAND_PGS_MASK) {
945 case CSOR_NAND_PGS_512:
946 if (nand->options & NAND_BUSWIDTH_16) {
947 layout = &oob_512_16bit_ecc4;
948 } else {
949 layout = &oob_512_8bit_ecc4;
950
951 /* Avoid conflict with bad block marker */
952 bbt_main_descr.offs = 0;
953 bbt_mirror_descr.offs = 0;
954 }
955
Sergey Lapin3a38a552013-01-14 03:46:50 +0000956 nand->ecc.strength = 4;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530957 priv->bufnum_mask = 15;
958 break;
959
960 case CSOR_NAND_PGS_2K:
961 layout = &oob_2048_ecc4;
Sergey Lapin3a38a552013-01-14 03:46:50 +0000962 nand->ecc.strength = 4;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530963 priv->bufnum_mask = 3;
964 break;
965
966 case CSOR_NAND_PGS_4K:
967 if ((csor & CSOR_NAND_ECC_MODE_MASK) ==
968 CSOR_NAND_ECC_MODE_4) {
969 layout = &oob_4096_ecc4;
Sergey Lapin3a38a552013-01-14 03:46:50 +0000970 nand->ecc.strength = 4;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530971 } else {
972 layout = &oob_4096_ecc8;
Sergey Lapin3a38a552013-01-14 03:46:50 +0000973 nand->ecc.strength = 8;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530974 nand->ecc.bytes = 16;
975 }
976
977 priv->bufnum_mask = 1;
978 break;
979
Prabhakar Kushwahaa3aaf1d2013-10-04 10:05:36 +0530980 case CSOR_NAND_PGS_8K:
981 if ((csor & CSOR_NAND_ECC_MODE_MASK) ==
982 CSOR_NAND_ECC_MODE_4) {
983 layout = &oob_8192_ecc4;
984 nand->ecc.strength = 4;
985 } else {
986 layout = &oob_8192_ecc8;
987 nand->ecc.strength = 8;
988 nand->ecc.bytes = 16;
989 }
990
991 priv->bufnum_mask = 0;
992 break;
993
994
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530995 default:
996 printf("ifc nand: bad csor %#x: bad page size\n", csor);
997 return -ENODEV;
998 }
999
1000 /* Must also set CSOR_NAND_ECC_ENC_EN if DEC_EN set */
1001 if (csor & CSOR_NAND_ECC_DEC_EN) {
1002 nand->ecc.mode = NAND_ECC_HW;
1003 nand->ecc.layout = layout;
1004 } else {
1005 nand->ecc.mode = NAND_ECC_SOFT;
1006 }
1007
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +05301008 ver = ifc_in32(&ifc_ctrl->regs->ifc_rev);
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +00001009 if (ver == FSL_IFC_V1_1_0)
1010 fsl_ifc_sram_init();
1011
Prabhakar Kushwaha895d0392013-04-04 18:44:06 +00001012 ret = nand_scan_ident(mtd, 1, NULL);
1013 if (ret)
1014 return ret;
1015
1016 ret = nand_scan_tail(mtd);
1017 if (ret)
1018 return ret;
1019
1020 ret = nand_register(devnum);
1021 if (ret)
1022 return ret;
Dipen Dudhat9eae0832011-03-22 09:27:39 +05301023 return 0;
1024}
Prabhakar Kushwaha895d0392013-04-04 18:44:06 +00001025
1026#ifndef CONFIG_SYS_NAND_BASE_LIST
1027#define CONFIG_SYS_NAND_BASE_LIST { CONFIG_SYS_NAND_BASE }
1028#endif
1029
1030static unsigned long base_address[CONFIG_SYS_MAX_NAND_DEVICE] =
1031 CONFIG_SYS_NAND_BASE_LIST;
1032
1033void board_nand_init(void)
1034{
1035 int i;
1036
1037 for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++)
1038 fsl_ifc_chip_init(i, (u8 *)base_address[i]);
1039}