blob: b283eaea345be2826d802aa9a164ee3b866fa90d [file] [log] [blame]
Dipen Dudhat52f90da2011-03-22 09:27:39 +05301/* Integrated Flash Controller NAND Machine Driver
2 *
Prabhakar Kushwaha5f720b82012-01-20 18:38:14 +05303 * Copyright (c) 2012 Freescale Semiconductor, Inc
Dipen Dudhat52f90da2011-03-22 09:27:39 +05304 *
5 * Authors: Dipen Dudhat <Dipen.Dudhat@freescale.com>
6 *
Wolfgang Denk1a459662013-07-08 09:37:19 +02007 * SPDX-License-Identifier: GPL-2.0+
Dipen Dudhat52f90da2011-03-22 09:27:39 +05308 */
9
10#include <common.h>
11#include <malloc.h>
Prabhakar Kushwahaa1b81ab2013-04-04 18:44:06 +000012#include <nand.h>
Dipen Dudhat52f90da2011-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 Sun0b665132013-10-22 12:39:02 -070020#include <fsl_ifc.h>
Dipen Dudhat52f90da2011-03-22 09:27:39 +053021
Prabhakar Kushwaha3bab3d82014-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 Kushwaha3bab3d82014-06-12 09:13:08 +053026#define MAX_BANKS CONFIG_SYS_FSL_IFC_BANK_COUNT
Dipen Dudhat52f90da2011-03-22 09:27:39 +053027#define ERR_BYTE 0xFF /* Value returned for read bytes
28 when read failed */
Dipen Dudhat52f90da2011-03-22 09:27:39 +053029
30struct fsl_ifc_ctrl;
31
32/* mtd information per set */
33struct fsl_ifc_mtd {
Dipen Dudhat52f90da2011-03-22 09:27:39 +053034 struct nand_chip chip;
35 struct fsl_ifc_ctrl *ctrl;
36
37 struct device *dev;
38 int bank; /* Chip select bank number */
39 unsigned int bufnum_mask; /* bufnum = page & bufnum_mask */
40 u8 __iomem *vbase; /* Chip select base virtual address */
41};
42
43/* overview of the fsl ifc controller */
44struct fsl_ifc_ctrl {
45 struct nand_hw_control controller;
46 struct fsl_ifc_mtd *chips[MAX_BANKS];
47
48 /* device info */
49 struct fsl_ifc *regs;
50 uint8_t __iomem *addr; /* Address of assigned IFC buffer */
51 unsigned int cs_nand; /* On which chipsel NAND is connected */
52 unsigned int page; /* Last page written to / read from */
53 unsigned int read_bytes; /* Number of bytes read during command */
54 unsigned int column; /* Saved column from SEQIN */
55 unsigned int index; /* Pointer to next byte to 'read' */
56 unsigned int status; /* status read from NEESR after last op */
57 unsigned int oob; /* Non zero if operating on OOB data */
58 unsigned int eccread; /* Non zero for a full-page ECC read */
59};
60
61static struct fsl_ifc_ctrl *ifc_ctrl;
62
63/* 512-byte page with 4-bit ECC, 8-bit */
64static struct nand_ecclayout oob_512_8bit_ecc4 = {
65 .eccbytes = 8,
66 .eccpos = {8, 9, 10, 11, 12, 13, 14, 15},
67 .oobfree = { {0, 5}, {6, 2} },
68};
69
70/* 512-byte page with 4-bit ECC, 16-bit */
71static struct nand_ecclayout oob_512_16bit_ecc4 = {
72 .eccbytes = 8,
73 .eccpos = {8, 9, 10, 11, 12, 13, 14, 15},
74 .oobfree = { {2, 6}, },
75};
76
77/* 2048-byte page size with 4-bit ECC */
78static struct nand_ecclayout oob_2048_ecc4 = {
79 .eccbytes = 32,
80 .eccpos = {
81 8, 9, 10, 11, 12, 13, 14, 15,
82 16, 17, 18, 19, 20, 21, 22, 23,
83 24, 25, 26, 27, 28, 29, 30, 31,
84 32, 33, 34, 35, 36, 37, 38, 39,
85 },
86 .oobfree = { {2, 6}, {40, 24} },
87};
88
89/* 4096-byte page size with 4-bit ECC */
90static struct nand_ecclayout oob_4096_ecc4 = {
91 .eccbytes = 64,
92 .eccpos = {
93 8, 9, 10, 11, 12, 13, 14, 15,
94 16, 17, 18, 19, 20, 21, 22, 23,
95 24, 25, 26, 27, 28, 29, 30, 31,
96 32, 33, 34, 35, 36, 37, 38, 39,
97 40, 41, 42, 43, 44, 45, 46, 47,
98 48, 49, 50, 51, 52, 53, 54, 55,
99 56, 57, 58, 59, 60, 61, 62, 63,
100 64, 65, 66, 67, 68, 69, 70, 71,
101 },
102 .oobfree = { {2, 6}, {72, 56} },
103};
104
105/* 4096-byte page size with 8-bit ECC -- requires 218-byte OOB */
106static struct nand_ecclayout oob_4096_ecc8 = {
107 .eccbytes = 128,
108 .eccpos = {
109 8, 9, 10, 11, 12, 13, 14, 15,
110 16, 17, 18, 19, 20, 21, 22, 23,
111 24, 25, 26, 27, 28, 29, 30, 31,
112 32, 33, 34, 35, 36, 37, 38, 39,
113 40, 41, 42, 43, 44, 45, 46, 47,
114 48, 49, 50, 51, 52, 53, 54, 55,
115 56, 57, 58, 59, 60, 61, 62, 63,
116 64, 65, 66, 67, 68, 69, 70, 71,
117 72, 73, 74, 75, 76, 77, 78, 79,
118 80, 81, 82, 83, 84, 85, 86, 87,
119 88, 89, 90, 91, 92, 93, 94, 95,
120 96, 97, 98, 99, 100, 101, 102, 103,
121 104, 105, 106, 107, 108, 109, 110, 111,
122 112, 113, 114, 115, 116, 117, 118, 119,
123 120, 121, 122, 123, 124, 125, 126, 127,
124 128, 129, 130, 131, 132, 133, 134, 135,
125 },
126 .oobfree = { {2, 6}, {136, 82} },
127};
128
Prabhakar Kushwaha71220f82013-10-04 10:05:36 +0530129/* 8192-byte page size with 4-bit ECC */
130static struct nand_ecclayout oob_8192_ecc4 = {
131 .eccbytes = 128,
132 .eccpos = {
133 8, 9, 10, 11, 12, 13, 14, 15,
134 16, 17, 18, 19, 20, 21, 22, 23,
135 24, 25, 26, 27, 28, 29, 30, 31,
136 32, 33, 34, 35, 36, 37, 38, 39,
137 40, 41, 42, 43, 44, 45, 46, 47,
138 48, 49, 50, 51, 52, 53, 54, 55,
139 56, 57, 58, 59, 60, 61, 62, 63,
140 64, 65, 66, 67, 68, 69, 70, 71,
141 72, 73, 74, 75, 76, 77, 78, 79,
142 80, 81, 82, 83, 84, 85, 86, 87,
143 88, 89, 90, 91, 92, 93, 94, 95,
144 96, 97, 98, 99, 100, 101, 102, 103,
145 104, 105, 106, 107, 108, 109, 110, 111,
146 112, 113, 114, 115, 116, 117, 118, 119,
147 120, 121, 122, 123, 124, 125, 126, 127,
148 128, 129, 130, 131, 132, 133, 134, 135,
149 },
150 .oobfree = { {2, 6}, {136, 208} },
151};
152
153/* 8192-byte page size with 8-bit ECC -- requires 218-byte OOB */
154static struct nand_ecclayout oob_8192_ecc8 = {
155 .eccbytes = 256,
156 .eccpos = {
157 8, 9, 10, 11, 12, 13, 14, 15,
158 16, 17, 18, 19, 20, 21, 22, 23,
159 24, 25, 26, 27, 28, 29, 30, 31,
160 32, 33, 34, 35, 36, 37, 38, 39,
161 40, 41, 42, 43, 44, 45, 46, 47,
162 48, 49, 50, 51, 52, 53, 54, 55,
163 56, 57, 58, 59, 60, 61, 62, 63,
164 64, 65, 66, 67, 68, 69, 70, 71,
165 72, 73, 74, 75, 76, 77, 78, 79,
166 80, 81, 82, 83, 84, 85, 86, 87,
167 88, 89, 90, 91, 92, 93, 94, 95,
168 96, 97, 98, 99, 100, 101, 102, 103,
169 104, 105, 106, 107, 108, 109, 110, 111,
170 112, 113, 114, 115, 116, 117, 118, 119,
171 120, 121, 122, 123, 124, 125, 126, 127,
172 128, 129, 130, 131, 132, 133, 134, 135,
173 136, 137, 138, 139, 140, 141, 142, 143,
174 144, 145, 146, 147, 148, 149, 150, 151,
175 152, 153, 154, 155, 156, 157, 158, 159,
176 160, 161, 162, 163, 164, 165, 166, 167,
177 168, 169, 170, 171, 172, 173, 174, 175,
178 176, 177, 178, 179, 180, 181, 182, 183,
179 184, 185, 186, 187, 188, 189, 190, 191,
180 192, 193, 194, 195, 196, 197, 198, 199,
181 200, 201, 202, 203, 204, 205, 206, 207,
182 208, 209, 210, 211, 212, 213, 214, 215,
183 216, 217, 218, 219, 220, 221, 222, 223,
184 224, 225, 226, 227, 228, 229, 230, 231,
185 232, 233, 234, 235, 236, 237, 238, 239,
186 240, 241, 242, 243, 244, 245, 246, 247,
187 248, 249, 250, 251, 252, 253, 254, 255,
188 256, 257, 258, 259, 260, 261, 262, 263,
189 },
190 .oobfree = { {2, 6}, {264, 80} },
191};
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530192
193/*
194 * Generic flash bbt descriptors
195 */
196static u8 bbt_pattern[] = {'B', 'b', 't', '0' };
197static u8 mirror_pattern[] = {'1', 't', 'b', 'B' };
198
199static struct nand_bbt_descr bbt_main_descr = {
200 .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE |
201 NAND_BBT_2BIT | NAND_BBT_VERSION,
202 .offs = 2, /* 0 on 8-bit small page */
203 .len = 4,
204 .veroffs = 6,
205 .maxblocks = 4,
206 .pattern = bbt_pattern,
207};
208
209static struct nand_bbt_descr bbt_mirror_descr = {
210 .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE |
211 NAND_BBT_2BIT | NAND_BBT_VERSION,
212 .offs = 2, /* 0 on 8-bit small page */
213 .len = 4,
214 .veroffs = 6,
215 .maxblocks = 4,
216 .pattern = mirror_pattern,
217};
218
219/*
220 * Set up the IFC hardware block and page address fields, and the ifc nand
221 * structure addr field to point to the correct IFC buffer in memory
222 */
223static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob)
224{
225 struct nand_chip *chip = mtd->priv;
226 struct fsl_ifc_mtd *priv = chip->priv;
227 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
228 struct fsl_ifc *ifc = ctrl->regs;
229 int buf_num;
230
231 ctrl->page = page_addr;
232
233 /* Program ROW0/COL0 */
Prabhakar Kushwaha1b4175d2014-01-18 12:28:30 +0530234 ifc_out32(&ifc->ifc_nand.row0, page_addr);
235 ifc_out32(&ifc->ifc_nand.col0, (oob ? IFC_NAND_COL_MS : 0) | column);
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530236
237 buf_num = page_addr & priv->bufnum_mask;
238
239 ctrl->addr = priv->vbase + buf_num * (mtd->writesize * 2);
240 ctrl->index = column;
241
242 /* for OOB data point to the second half of the buffer */
243 if (oob)
244 ctrl->index += mtd->writesize;
245}
246
247static int is_blank(struct mtd_info *mtd, struct fsl_ifc_ctrl *ctrl,
248 unsigned int bufnum)
249{
250 struct nand_chip *chip = mtd->priv;
251 struct fsl_ifc_mtd *priv = chip->priv;
252 u8 __iomem *addr = priv->vbase + bufnum * (mtd->writesize * 2);
253 u32 __iomem *main = (u32 *)addr;
254 u8 __iomem *oob = addr + mtd->writesize;
255 int i;
256
257 for (i = 0; i < mtd->writesize / 4; i++) {
258 if (__raw_readl(&main[i]) != 0xffffffff)
259 return 0;
260 }
261
262 for (i = 0; i < chip->ecc.layout->eccbytes; i++) {
263 int pos = chip->ecc.layout->eccpos[i];
264
265 if (__raw_readb(&oob[pos]) != 0xff)
266 return 0;
267 }
268
269 return 1;
270}
271
272/* returns nonzero if entire page is blank */
273static int check_read_ecc(struct mtd_info *mtd, struct fsl_ifc_ctrl *ctrl,
274 u32 *eccstat, unsigned int bufnum)
275{
276 u32 reg = eccstat[bufnum / 4];
Prabhakar Kushwaha5f720b82012-01-20 18:38:14 +0530277 int errors;
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530278
Prabhakar Kushwaha5f720b82012-01-20 18:38:14 +0530279 errors = (reg >> ((3 - bufnum % 4) * 8)) & 15;
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530280
Prabhakar Kushwaha5f720b82012-01-20 18:38:14 +0530281 return errors;
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530282}
283
284/*
285 * execute IFC NAND command and wait for it to complete
286 */
287static int fsl_ifc_run_command(struct mtd_info *mtd)
288{
289 struct nand_chip *chip = mtd->priv;
290 struct fsl_ifc_mtd *priv = chip->priv;
291 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
292 struct fsl_ifc *ifc = ctrl->regs;
Prabhakar Kushwaha5b8388a2014-09-23 09:57:47 +0530293 u32 timeo = (CONFIG_SYS_HZ * 10) / 1000;
294 u32 time_start;
Jaiprakash Singh1d421cc2014-11-27 12:38:12 +0530295 u32 eccstat[4] = {0};
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530296 int i;
297
298 /* set the chip select for NAND Transaction */
Prabhakar Kushwaha1b4175d2014-01-18 12:28:30 +0530299 ifc_out32(&ifc->ifc_nand.nand_csel, ifc_ctrl->cs_nand);
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530300
301 /* start read/write seq */
Prabhakar Kushwaha1b4175d2014-01-18 12:28:30 +0530302 ifc_out32(&ifc->ifc_nand.nandseq_strt,
303 IFC_NAND_SEQ_STRT_FIR_STRT);
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530304
305 /* wait for NAND Machine complete flag or timeout */
Prabhakar Kushwaha5b8388a2014-09-23 09:57:47 +0530306 time_start = get_timer(0);
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530307
Prabhakar Kushwaha5b8388a2014-09-23 09:57:47 +0530308 while (get_timer(time_start) < timeo) {
Prabhakar Kushwaha1b4175d2014-01-18 12:28:30 +0530309 ctrl->status = ifc_in32(&ifc->ifc_nand.nand_evter_stat);
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530310
311 if (ctrl->status & IFC_NAND_EVTER_STAT_OPC)
312 break;
313 }
314
Prabhakar Kushwaha1b4175d2014-01-18 12:28:30 +0530315 ifc_out32(&ifc->ifc_nand.nand_evter_stat, ctrl->status);
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530316
317 if (ctrl->status & IFC_NAND_EVTER_STAT_FTOER)
318 printf("%s: Flash Time Out Error\n", __func__);
319 if (ctrl->status & IFC_NAND_EVTER_STAT_WPER)
320 printf("%s: Write Protect Error\n", __func__);
321
322 if (ctrl->eccread) {
Prabhakar Kushwaha5f720b82012-01-20 18:38:14 +0530323 int errors;
324 int bufnum = ctrl->page & priv->bufnum_mask;
325 int sector = bufnum * chip->ecc.steps;
326 int sector_end = sector + chip->ecc.steps - 1;
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530327
Prabhakar Kushwaha5f720b82012-01-20 18:38:14 +0530328 for (i = sector / 4; i <= sector_end / 4; i++)
Prabhakar Kushwaha1b4175d2014-01-18 12:28:30 +0530329 eccstat[i] = ifc_in32(&ifc->ifc_nand.nand_eccstat[i]);
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530330
Prabhakar Kushwaha5f720b82012-01-20 18:38:14 +0530331 for (i = sector; i <= sector_end; i++) {
332 errors = check_read_ecc(mtd, ctrl, eccstat, i);
333
334 if (errors == 15) {
335 /*
336 * Uncorrectable error.
337 * OK only if the whole page is blank.
338 *
339 * We disable ECCER reporting due to erratum
340 * IFC-A002770 -- so report it now if we
341 * see an uncorrectable error in ECCSTAT.
342 */
343 if (!is_blank(mtd, ctrl, bufnum))
344 ctrl->status |=
345 IFC_NAND_EVTER_STAT_ECCER;
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530346 break;
Prabhakar Kushwaha5f720b82012-01-20 18:38:14 +0530347 }
348
349 mtd->ecc_stats.corrected += errors;
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530350 }
351
352 ctrl->eccread = 0;
353 }
354
355 /* returns 0 on success otherwise non-zero) */
356 return ctrl->status == IFC_NAND_EVTER_STAT_OPC ? 0 : -EIO;
357}
358
359static void fsl_ifc_do_read(struct nand_chip *chip,
360 int oob,
361 struct mtd_info *mtd)
362{
363 struct fsl_ifc_mtd *priv = chip->priv;
364 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
365 struct fsl_ifc *ifc = ctrl->regs;
366
367 /* Program FIR/IFC_NAND_FCR0 for Small/Large page */
368 if (mtd->writesize > 512) {
Prabhakar Kushwaha1b4175d2014-01-18 12:28:30 +0530369 ifc_out32(&ifc->ifc_nand.nand_fir0,
370 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
371 (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP1_SHIFT) |
372 (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP2_SHIFT) |
373 (IFC_FIR_OP_CMD1 << IFC_NAND_FIR0_OP3_SHIFT) |
374 (IFC_FIR_OP_RBCD << IFC_NAND_FIR0_OP4_SHIFT));
375 ifc_out32(&ifc->ifc_nand.nand_fir1, 0x0);
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530376
Prabhakar Kushwaha1b4175d2014-01-18 12:28:30 +0530377 ifc_out32(&ifc->ifc_nand.nand_fcr0,
378 (NAND_CMD_READ0 << IFC_NAND_FCR0_CMD0_SHIFT) |
379 (NAND_CMD_READSTART << IFC_NAND_FCR0_CMD1_SHIFT));
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530380 } else {
Prabhakar Kushwaha1b4175d2014-01-18 12:28:30 +0530381 ifc_out32(&ifc->ifc_nand.nand_fir0,
382 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
383 (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP1_SHIFT) |
384 (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP2_SHIFT) |
385 (IFC_FIR_OP_RBCD << IFC_NAND_FIR0_OP3_SHIFT));
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530386
387 if (oob)
Prabhakar Kushwaha1b4175d2014-01-18 12:28:30 +0530388 ifc_out32(&ifc->ifc_nand.nand_fcr0,
389 NAND_CMD_READOOB << IFC_NAND_FCR0_CMD0_SHIFT);
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530390 else
Prabhakar Kushwaha1b4175d2014-01-18 12:28:30 +0530391 ifc_out32(&ifc->ifc_nand.nand_fcr0,
392 NAND_CMD_READ0 << IFC_NAND_FCR0_CMD0_SHIFT);
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530393 }
394}
395
396/* cmdfunc send commands to the IFC NAND Machine */
397static void fsl_ifc_cmdfunc(struct mtd_info *mtd, unsigned int command,
398 int column, int page_addr)
399{
400 struct nand_chip *chip = mtd->priv;
401 struct fsl_ifc_mtd *priv = chip->priv;
402 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
403 struct fsl_ifc *ifc = ctrl->regs;
404
405 /* clear the read buffer */
406 ctrl->read_bytes = 0;
407 if (command != NAND_CMD_PAGEPROG)
408 ctrl->index = 0;
409
410 switch (command) {
411 /* READ0 read the entire buffer to use hardware ECC. */
412 case NAND_CMD_READ0: {
Prabhakar Kushwaha1b4175d2014-01-18 12:28:30 +0530413 ifc_out32(&ifc->ifc_nand.nand_fbcr, 0);
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530414 set_addr(mtd, 0, page_addr, 0);
415
416 ctrl->read_bytes = mtd->writesize + mtd->oobsize;
417 ctrl->index += column;
418
419 if (chip->ecc.mode == NAND_ECC_HW)
420 ctrl->eccread = 1;
421
422 fsl_ifc_do_read(chip, 0, mtd);
423 fsl_ifc_run_command(mtd);
424 return;
425 }
426
427 /* READOOB reads only the OOB because no ECC is performed. */
428 case NAND_CMD_READOOB:
Prabhakar Kushwaha1b4175d2014-01-18 12:28:30 +0530429 ifc_out32(&ifc->ifc_nand.nand_fbcr, mtd->oobsize - column);
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530430 set_addr(mtd, column, page_addr, 1);
431
432 ctrl->read_bytes = mtd->writesize + mtd->oobsize;
433
434 fsl_ifc_do_read(chip, 1, mtd);
435 fsl_ifc_run_command(mtd);
436
437 return;
438
439 /* READID must read all possible bytes while CEB is active */
440 case NAND_CMD_READID:
Prabhakar Kushwaha807fc702012-04-08 18:57:18 +0000441 case NAND_CMD_PARAM: {
442 int timing = IFC_FIR_OP_RB;
443 if (command == NAND_CMD_PARAM)
444 timing = IFC_FIR_OP_RBCD;
445
Prabhakar Kushwaha1b4175d2014-01-18 12:28:30 +0530446 ifc_out32(&ifc->ifc_nand.nand_fir0,
447 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
448 (IFC_FIR_OP_UA << IFC_NAND_FIR0_OP1_SHIFT) |
449 (timing << IFC_NAND_FIR0_OP2_SHIFT));
450 ifc_out32(&ifc->ifc_nand.nand_fcr0,
451 command << IFC_NAND_FCR0_CMD0_SHIFT);
452 ifc_out32(&ifc->ifc_nand.row3, column);
Prabhakar Kushwaha807fc702012-04-08 18:57:18 +0000453
454 /*
455 * although currently it's 8 bytes for READID, we always read
456 * the maximum 256 bytes(for PARAM)
457 */
Prabhakar Kushwaha1b4175d2014-01-18 12:28:30 +0530458 ifc_out32(&ifc->ifc_nand.nand_fbcr, 256);
Prabhakar Kushwaha807fc702012-04-08 18:57:18 +0000459 ctrl->read_bytes = 256;
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530460
461 set_addr(mtd, 0, 0, 0);
462 fsl_ifc_run_command(mtd);
463 return;
Prabhakar Kushwaha807fc702012-04-08 18:57:18 +0000464 }
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530465
466 /* ERASE1 stores the block and page address */
467 case NAND_CMD_ERASE1:
468 set_addr(mtd, 0, page_addr, 0);
469 return;
470
471 /* ERASE2 uses the block and page address from ERASE1 */
472 case NAND_CMD_ERASE2:
Prabhakar Kushwaha1b4175d2014-01-18 12:28:30 +0530473 ifc_out32(&ifc->ifc_nand.nand_fir0,
474 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
475 (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP1_SHIFT) |
476 (IFC_FIR_OP_CMD1 << IFC_NAND_FIR0_OP2_SHIFT));
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530477
Prabhakar Kushwaha1b4175d2014-01-18 12:28:30 +0530478 ifc_out32(&ifc->ifc_nand.nand_fcr0,
479 (NAND_CMD_ERASE1 << IFC_NAND_FCR0_CMD0_SHIFT) |
480 (NAND_CMD_ERASE2 << IFC_NAND_FCR0_CMD1_SHIFT));
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530481
Prabhakar Kushwaha1b4175d2014-01-18 12:28:30 +0530482 ifc_out32(&ifc->ifc_nand.nand_fbcr, 0);
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530483 ctrl->read_bytes = 0;
484 fsl_ifc_run_command(mtd);
485 return;
486
487 /* SEQIN sets up the addr buffer and all registers except the length */
488 case NAND_CMD_SEQIN: {
489 u32 nand_fcr0;
490 ctrl->column = column;
491 ctrl->oob = 0;
492
493 if (mtd->writesize > 512) {
494 nand_fcr0 =
495 (NAND_CMD_SEQIN << IFC_NAND_FCR0_CMD0_SHIFT) |
Prabhakar Kushwahaed5ac342013-10-03 11:35:35 +0530496 (NAND_CMD_STATUS << IFC_NAND_FCR0_CMD1_SHIFT) |
497 (NAND_CMD_PAGEPROG << IFC_NAND_FCR0_CMD2_SHIFT);
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530498
Prabhakar Kushwaha1b4175d2014-01-18 12:28:30 +0530499 ifc_out32(&ifc->ifc_nand.nand_fir0,
500 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
501 (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP1_SHIFT) |
502 (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP2_SHIFT) |
503 (IFC_FIR_OP_WBCD <<
504 IFC_NAND_FIR0_OP3_SHIFT) |
505 (IFC_FIR_OP_CMD2 << IFC_NAND_FIR0_OP4_SHIFT));
506 ifc_out32(&ifc->ifc_nand.nand_fir1,
507 (IFC_FIR_OP_CW1 << IFC_NAND_FIR1_OP5_SHIFT) |
508 (IFC_FIR_OP_RDSTAT <<
Prabhakar Kushwahaed5ac342013-10-03 11:35:35 +0530509 IFC_NAND_FIR1_OP6_SHIFT) |
Prabhakar Kushwaha1b4175d2014-01-18 12:28:30 +0530510 (IFC_FIR_OP_NOP << IFC_NAND_FIR1_OP7_SHIFT));
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530511 } else {
512 nand_fcr0 = ((NAND_CMD_PAGEPROG <<
513 IFC_NAND_FCR0_CMD1_SHIFT) |
514 (NAND_CMD_SEQIN <<
Prabhakar Kushwahaed5ac342013-10-03 11:35:35 +0530515 IFC_NAND_FCR0_CMD2_SHIFT) |
516 (NAND_CMD_STATUS <<
517 IFC_NAND_FCR0_CMD3_SHIFT));
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530518
Prabhakar Kushwaha1b4175d2014-01-18 12:28:30 +0530519 ifc_out32(&ifc->ifc_nand.nand_fir0,
520 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
521 (IFC_FIR_OP_CMD2 << IFC_NAND_FIR0_OP1_SHIFT) |
522 (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP2_SHIFT) |
523 (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP3_SHIFT) |
524 (IFC_FIR_OP_WBCD << IFC_NAND_FIR0_OP4_SHIFT));
525 ifc_out32(&ifc->ifc_nand.nand_fir1,
526 (IFC_FIR_OP_CMD1 << IFC_NAND_FIR1_OP5_SHIFT) |
527 (IFC_FIR_OP_CW3 << IFC_NAND_FIR1_OP6_SHIFT) |
528 (IFC_FIR_OP_RDSTAT <<
Prabhakar Kushwahaed5ac342013-10-03 11:35:35 +0530529 IFC_NAND_FIR1_OP7_SHIFT) |
Prabhakar Kushwaha1b4175d2014-01-18 12:28:30 +0530530 (IFC_FIR_OP_NOP << IFC_NAND_FIR1_OP8_SHIFT));
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530531
Prabhakar Kushwahad9036122012-01-20 18:39:05 +0530532 if (column >= mtd->writesize)
533 nand_fcr0 |=
534 NAND_CMD_READOOB << IFC_NAND_FCR0_CMD0_SHIFT;
535 else
536 nand_fcr0 |=
537 NAND_CMD_READ0 << IFC_NAND_FCR0_CMD0_SHIFT;
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530538 }
539
Prabhakar Kushwahad9036122012-01-20 18:39:05 +0530540 if (column >= mtd->writesize) {
541 /* OOB area --> READOOB */
542 column -= mtd->writesize;
543 ctrl->oob = 1;
544 }
Prabhakar Kushwaha1b4175d2014-01-18 12:28:30 +0530545 ifc_out32(&ifc->ifc_nand.nand_fcr0, nand_fcr0);
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530546 set_addr(mtd, column, page_addr, ctrl->oob);
547 return;
548 }
549
550 /* PAGEPROG reuses all of the setup from SEQIN and adds the length */
551 case NAND_CMD_PAGEPROG:
552 if (ctrl->oob)
Prabhakar Kushwaha1b4175d2014-01-18 12:28:30 +0530553 ifc_out32(&ifc->ifc_nand.nand_fbcr,
554 ctrl->index - ctrl->column);
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530555 else
Prabhakar Kushwaha1b4175d2014-01-18 12:28:30 +0530556 ifc_out32(&ifc->ifc_nand.nand_fbcr, 0);
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530557
558 fsl_ifc_run_command(mtd);
559 return;
560
561 case NAND_CMD_STATUS:
Prabhakar Kushwaha1b4175d2014-01-18 12:28:30 +0530562 ifc_out32(&ifc->ifc_nand.nand_fir0,
563 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
564 (IFC_FIR_OP_RB << IFC_NAND_FIR0_OP1_SHIFT));
565 ifc_out32(&ifc->ifc_nand.nand_fcr0,
566 NAND_CMD_STATUS << IFC_NAND_FCR0_CMD0_SHIFT);
567 ifc_out32(&ifc->ifc_nand.nand_fbcr, 1);
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530568 set_addr(mtd, 0, 0, 0);
569 ctrl->read_bytes = 1;
570
571 fsl_ifc_run_command(mtd);
572
573 /* Chip sometimes reporting write protect even when it's not */
574 out_8(ctrl->addr, in_8(ctrl->addr) | NAND_STATUS_WP);
575 return;
576
577 case NAND_CMD_RESET:
Prabhakar Kushwaha1b4175d2014-01-18 12:28:30 +0530578 ifc_out32(&ifc->ifc_nand.nand_fir0,
579 IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT);
580 ifc_out32(&ifc->ifc_nand.nand_fcr0,
581 NAND_CMD_RESET << IFC_NAND_FCR0_CMD0_SHIFT);
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530582 fsl_ifc_run_command(mtd);
583 return;
584
585 default:
586 printf("%s: error, unsupported command 0x%x.\n",
587 __func__, command);
588 }
589}
590
591/*
592 * Write buf to the IFC NAND Controller Data Buffer
593 */
594static void fsl_ifc_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
595{
596 struct nand_chip *chip = mtd->priv;
597 struct fsl_ifc_mtd *priv = chip->priv;
598 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
599 unsigned int bufsize = mtd->writesize + mtd->oobsize;
600
601 if (len <= 0) {
602 printf("%s of %d bytes", __func__, len);
603 ctrl->status = 0;
604 return;
605 }
606
607 if ((unsigned int)len > bufsize - ctrl->index) {
608 printf("%s beyond end of buffer "
609 "(%d requested, %u available)\n",
610 __func__, len, bufsize - ctrl->index);
611 len = bufsize - ctrl->index;
612 }
613
614 memcpy_toio(&ctrl->addr[ctrl->index], buf, len);
615 ctrl->index += len;
616}
617
618/*
619 * read a byte from either the IFC hardware buffer if it has any data left
620 * otherwise issue a command to read a single byte.
621 */
622static u8 fsl_ifc_read_byte(struct mtd_info *mtd)
623{
624 struct nand_chip *chip = mtd->priv;
625 struct fsl_ifc_mtd *priv = chip->priv;
626 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
627
628 /* If there are still bytes in the IFC buffer, then use the
629 * next byte. */
630 if (ctrl->index < ctrl->read_bytes)
631 return in_8(&ctrl->addr[ctrl->index++]);
632
633 printf("%s beyond end of buffer\n", __func__);
634 return ERR_BYTE;
635}
636
637/*
638 * Read two bytes from the IFC hardware buffer
639 * read function for 16-bit buswith
640 */
641static uint8_t fsl_ifc_read_byte16(struct mtd_info *mtd)
642{
643 struct nand_chip *chip = mtd->priv;
644 struct fsl_ifc_mtd *priv = chip->priv;
645 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
646 uint16_t data;
647
648 /*
649 * If there are still bytes in the IFC buffer, then use the
650 * next byte.
651 */
652 if (ctrl->index < ctrl->read_bytes) {
Prabhakar Kushwaha1b4175d2014-01-18 12:28:30 +0530653 data = ifc_in16((uint16_t *)&ctrl->
654 addr[ctrl->index]);
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530655 ctrl->index += 2;
656 return (uint8_t)data;
657 }
658
659 printf("%s beyond end of buffer\n", __func__);
660 return ERR_BYTE;
661}
662
663/*
664 * Read from the IFC Controller Data Buffer
665 */
666static void fsl_ifc_read_buf(struct mtd_info *mtd, u8 *buf, int len)
667{
668 struct nand_chip *chip = mtd->priv;
669 struct fsl_ifc_mtd *priv = chip->priv;
670 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
671 int avail;
672
673 if (len < 0)
674 return;
675
676 avail = min((unsigned int)len, ctrl->read_bytes - ctrl->index);
677 memcpy_fromio(buf, &ctrl->addr[ctrl->index], avail);
678 ctrl->index += avail;
679
680 if (len > avail)
681 printf("%s beyond end of buffer "
682 "(%d requested, %d available)\n",
683 __func__, len, avail);
684}
685
Heiko Schocherff94bc42014-06-24 10:10:04 +0200686#if defined(CONFIG_MTD_NAND_VERIFY_WRITE)
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530687/*
688 * Verify buffer against the IFC Controller Data Buffer
689 */
690static int fsl_ifc_verify_buf(struct mtd_info *mtd,
691 const u_char *buf, int len)
692{
693 struct nand_chip *chip = mtd->priv;
694 struct fsl_ifc_mtd *priv = chip->priv;
695 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
696 int i;
697
698 if (len < 0) {
699 printf("%s of %d bytes", __func__, len);
700 return -EINVAL;
701 }
702
703 if ((unsigned int)len > ctrl->read_bytes - ctrl->index) {
704 printf("%s beyond end of buffer "
705 "(%d requested, %u available)\n",
706 __func__, len, ctrl->read_bytes - ctrl->index);
707
708 ctrl->index = ctrl->read_bytes;
709 return -EINVAL;
710 }
711
712 for (i = 0; i < len; i++)
713 if (in_8(&ctrl->addr[ctrl->index + i]) != buf[i])
714 break;
715
716 ctrl->index += len;
717 return i == len && ctrl->status == IFC_NAND_EVTER_STAT_OPC ? 0 : -EIO;
718}
Heiko Schocherff94bc42014-06-24 10:10:04 +0200719#endif
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530720
721/* This function is called after Program and Erase Operations to
722 * check for success or failure.
723 */
724static int fsl_ifc_wait(struct mtd_info *mtd, struct nand_chip *chip)
725{
726 struct fsl_ifc_mtd *priv = chip->priv;
727 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
728 struct fsl_ifc *ifc = ctrl->regs;
729 u32 nand_fsr;
730
731 if (ctrl->status != IFC_NAND_EVTER_STAT_OPC)
732 return NAND_STATUS_FAIL;
733
734 /* Use READ_STATUS command, but wait for the device to be ready */
Prabhakar Kushwaha1b4175d2014-01-18 12:28:30 +0530735 ifc_out32(&ifc->ifc_nand.nand_fir0,
736 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
737 (IFC_FIR_OP_RDSTAT << IFC_NAND_FIR0_OP1_SHIFT));
738 ifc_out32(&ifc->ifc_nand.nand_fcr0, NAND_CMD_STATUS <<
739 IFC_NAND_FCR0_CMD0_SHIFT);
740 ifc_out32(&ifc->ifc_nand.nand_fbcr, 1);
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530741 set_addr(mtd, 0, 0, 0);
742 ctrl->read_bytes = 1;
743
744 fsl_ifc_run_command(mtd);
745
746 if (ctrl->status != IFC_NAND_EVTER_STAT_OPC)
747 return NAND_STATUS_FAIL;
748
Prabhakar Kushwaha1b4175d2014-01-18 12:28:30 +0530749 nand_fsr = ifc_in32(&ifc->ifc_nand.nand_fsr);
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530750
751 /* Chip sometimes reporting write protect even when it's not */
752 nand_fsr = nand_fsr | NAND_STATUS_WP;
753 return nand_fsr;
754}
755
Sergey Lapindfe64e22013-01-14 03:46:50 +0000756static int fsl_ifc_read_page(struct mtd_info *mtd, struct nand_chip *chip,
757 uint8_t *buf, int oob_required, int page)
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530758{
759 struct fsl_ifc_mtd *priv = chip->priv;
760 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
761
762 fsl_ifc_read_buf(mtd, buf, mtd->writesize);
763 fsl_ifc_read_buf(mtd, chip->oob_poi, mtd->oobsize);
764
765 if (ctrl->status != IFC_NAND_EVTER_STAT_OPC)
766 mtd->ecc_stats.failed++;
767
768 return 0;
769}
770
771/* ECC will be calculated automatically, and errors will be detected in
772 * waitfunc.
773 */
Sergey Lapindfe64e22013-01-14 03:46:50 +0000774static int fsl_ifc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
775 const uint8_t *buf, int oob_required)
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530776{
777 fsl_ifc_write_buf(mtd, buf, mtd->writesize);
778 fsl_ifc_write_buf(mtd, chip->oob_poi, mtd->oobsize);
Sergey Lapindfe64e22013-01-14 03:46:50 +0000779
780 return 0;
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530781}
782
783static void fsl_ifc_ctrl_init(void)
784{
785 ifc_ctrl = kzalloc(sizeof(*ifc_ctrl), GFP_KERNEL);
786 if (!ifc_ctrl)
787 return;
788
789 ifc_ctrl->regs = IFC_BASE_ADDR;
790
791 /* clear event registers */
Prabhakar Kushwaha1b4175d2014-01-18 12:28:30 +0530792 ifc_out32(&ifc_ctrl->regs->ifc_nand.nand_evter_stat, ~0U);
793 ifc_out32(&ifc_ctrl->regs->ifc_nand.pgrdcmpl_evt_stat, ~0U);
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530794
795 /* Enable error and event for any detected errors */
Prabhakar Kushwaha1b4175d2014-01-18 12:28:30 +0530796 ifc_out32(&ifc_ctrl->regs->ifc_nand.nand_evter_en,
797 IFC_NAND_EVTER_EN_OPC_EN |
798 IFC_NAND_EVTER_EN_PGRDCMPL_EN |
799 IFC_NAND_EVTER_EN_FTOER_EN |
800 IFC_NAND_EVTER_EN_WPER_EN);
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530801
Prabhakar Kushwaha1b4175d2014-01-18 12:28:30 +0530802 ifc_out32(&ifc_ctrl->regs->ifc_nand.ncfgr, 0x0);
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530803}
804
805static void fsl_ifc_select_chip(struct mtd_info *mtd, int chip)
806{
807}
808
Prabhakar Kushwaha04818bb2014-06-12 12:14:00 +0530809static int fsl_ifc_sram_init(uint32_t ver)
Prabhakar Kushwaha79da5e32012-09-12 22:26:05 +0000810{
811 struct fsl_ifc *ifc = ifc_ctrl->regs;
812 uint32_t cs = 0, csor = 0, csor_8k = 0, csor_ext = 0;
Prabhakar Kushwaha04818bb2014-06-12 12:14:00 +0530813 uint32_t ncfgr = 0;
Prabhakar Kushwaha5b8388a2014-09-23 09:57:47 +0530814 u32 timeo = (CONFIG_SYS_HZ * 10) / 1000;
815 u32 time_start;
Prabhakar Kushwaha79da5e32012-09-12 22:26:05 +0000816
Prabhakar Kushwaha04818bb2014-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 */
Prabhakar Kushwaha5b8388a2014-09-23 09:57:47 +0530822 time_start = get_timer(0);
823 while (get_timer(time_start) < timeo) {
Prabhakar Kushwaha04818bb2014-06-12 12:14:00 +0530824 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 Kushwaha79da5e32012-09-12 22:26:05 +0000834 cs = ifc_ctrl->cs_nand >> IFC_NAND_CSEL_SHIFT;
835
836 /* Save CSOR and CSOR_ext */
Prabhakar Kushwaha1b4175d2014-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 Kushwaha79da5e32012-09-12 22:26:05 +0000839
840 /* chage PageSize 8K and SpareSize 1K*/
841 csor_8k = (csor & ~(CSOR_NAND_PGS_MASK)) | 0x0018C000;
Prabhakar Kushwaha1b4175d2014-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 Kushwaha79da5e32012-09-12 22:26:05 +0000844
845 /* READID */
Prabhakar Kushwaha1b4175d2014-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 Kushwaha79da5e32012-09-12 22:26:05 +0000853
Prabhakar Kushwaha1b4175d2014-01-18 12:28:30 +0530854 ifc_out32(&ifc->ifc_nand.nand_fbcr, 0x0);
Prabhakar Kushwaha79da5e32012-09-12 22:26:05 +0000855
856 /* Program ROW0/COL0 */
Prabhakar Kushwaha1b4175d2014-01-18 12:28:30 +0530857 ifc_out32(&ifc->ifc_nand.row0, 0x0);
858 ifc_out32(&ifc->ifc_nand.col0, 0x0);
Prabhakar Kushwaha79da5e32012-09-12 22:26:05 +0000859
860 /* set the chip select for NAND Transaction */
Prabhakar Kushwaha1b4175d2014-01-18 12:28:30 +0530861 ifc_out32(&ifc->ifc_nand.nand_csel, ifc_ctrl->cs_nand);
Prabhakar Kushwaha79da5e32012-09-12 22:26:05 +0000862
863 /* start read seq */
Prabhakar Kushwaha1b4175d2014-01-18 12:28:30 +0530864 ifc_out32(&ifc->ifc_nand.nandseq_strt, IFC_NAND_SEQ_STRT_FIR_STRT);
Prabhakar Kushwaha79da5e32012-09-12 22:26:05 +0000865
Prabhakar Kushwaha5b8388a2014-09-23 09:57:47 +0530866 time_start = get_timer(0);
Prabhakar Kushwaha79da5e32012-09-12 22:26:05 +0000867
Prabhakar Kushwaha5b8388a2014-09-23 09:57:47 +0530868 while (get_timer(time_start) < timeo) {
Prabhakar Kushwaha1b4175d2014-01-18 12:28:30 +0530869 ifc_ctrl->status = ifc_in32(&ifc->ifc_nand.nand_evter_stat);
Prabhakar Kushwaha79da5e32012-09-12 22:26:05 +0000870
871 if (ifc_ctrl->status & IFC_NAND_EVTER_STAT_OPC)
872 break;
873 }
874
Prabhakar Kushwaha04818bb2014-06-12 12:14:00 +0530875 if (ifc_ctrl->status != IFC_NAND_EVTER_STAT_OPC) {
876 printf("fsl-ifc: Failed to Initialise SRAM\n");
877 return 1;
878 }
879
Prabhakar Kushwaha1b4175d2014-01-18 12:28:30 +0530880 ifc_out32(&ifc->ifc_nand.nand_evter_stat, ifc_ctrl->status);
Prabhakar Kushwaha79da5e32012-09-12 22:26:05 +0000881
882 /* Restore CSOR and CSOR_ext */
Prabhakar Kushwaha1b4175d2014-01-18 12:28:30 +0530883 ifc_out32(&ifc_ctrl->regs->csor_cs[cs].csor, csor);
884 ifc_out32(&ifc_ctrl->regs->csor_cs[cs].csor_ext, csor_ext);
Prabhakar Kushwaha04818bb2014-06-12 12:14:00 +0530885
886 return 0;
Prabhakar Kushwaha79da5e32012-09-12 22:26:05 +0000887}
888
Prabhakar Kushwahaa1b81ab2013-04-04 18:44:06 +0000889static int fsl_ifc_chip_init(int devnum, u8 *addr)
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530890{
Prabhakar Kushwahaa1b81ab2013-04-04 18:44:06 +0000891 struct mtd_info *mtd = &nand_info[devnum];
892 struct nand_chip *nand;
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530893 struct fsl_ifc_mtd *priv;
894 struct nand_ecclayout *layout;
Prabhakar Kushwaha79da5e32012-09-12 22:26:05 +0000895 uint32_t cspr = 0, csor = 0, ver = 0;
Prabhakar Kushwaha04818bb2014-06-12 12:14:00 +0530896 int ret = 0;
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530897
898 if (!ifc_ctrl) {
899 fsl_ifc_ctrl_init();
900 if (!ifc_ctrl)
901 return -1;
902 }
903
904 priv = kzalloc(sizeof(*priv), GFP_KERNEL);
905 if (!priv)
906 return -ENOMEM;
907
908 priv->ctrl = ifc_ctrl;
Prabhakar Kushwahaa1b81ab2013-04-04 18:44:06 +0000909 priv->vbase = addr;
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530910
911 /* Find which chip select it is connected to.
912 */
913 for (priv->bank = 0; priv->bank < MAX_BANKS; priv->bank++) {
Prabhakar Kushwahaa1b81ab2013-04-04 18:44:06 +0000914 phys_addr_t phys_addr = virt_to_phys(addr);
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530915
Prabhakar Kushwaha1b4175d2014-01-18 12:28:30 +0530916 cspr = ifc_in32(&ifc_ctrl->regs->cspr_cs[priv->bank].cspr);
917 csor = ifc_in32(&ifc_ctrl->regs->csor_cs[priv->bank].csor);
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530918
919 if ((cspr & CSPR_V) && (cspr & CSPR_MSEL) == CSPR_MSEL_NAND &&
Prabhakar Kushwahaa1b81ab2013-04-04 18:44:06 +0000920 (cspr & CSPR_BA) == CSPR_PHYS_ADDR(phys_addr)) {
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530921 ifc_ctrl->cs_nand = priv->bank << IFC_NAND_CSEL_SHIFT;
922 break;
923 }
924 }
925
926 if (priv->bank >= MAX_BANKS) {
927 printf("%s: address did not match any "
928 "chip selects\n", __func__);
Prabhakar Kushwaha76d067a2012-04-10 22:48:27 +0000929 kfree(priv);
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530930 return -ENODEV;
931 }
932
Prabhakar Kushwahaa1b81ab2013-04-04 18:44:06 +0000933 nand = &priv->chip;
934 mtd->priv = nand;
935
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530936 ifc_ctrl->chips[priv->bank] = priv;
937
938 /* fill in nand_chip structure */
939 /* set up function call table */
940
941 nand->write_buf = fsl_ifc_write_buf;
942 nand->read_buf = fsl_ifc_read_buf;
Heiko Schocherff94bc42014-06-24 10:10:04 +0200943#if defined(CONFIG_MTD_NAND_VERIFY_WRITE)
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530944 nand->verify_buf = fsl_ifc_verify_buf;
Heiko Schocherff94bc42014-06-24 10:10:04 +0200945#endif
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530946 nand->select_chip = fsl_ifc_select_chip;
947 nand->cmdfunc = fsl_ifc_cmdfunc;
948 nand->waitfunc = fsl_ifc_wait;
949
950 /* set up nand options */
951 nand->bbt_td = &bbt_main_descr;
952 nand->bbt_md = &bbt_mirror_descr;
953
954 /* set up nand options */
Sergey Lapindfe64e22013-01-14 03:46:50 +0000955 nand->options = NAND_NO_SUBPAGE_WRITE;
956 nand->bbt_options = NAND_BBT_USE_FLASH;
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530957
958 if (cspr & CSPR_PORT_SIZE_16) {
959 nand->read_byte = fsl_ifc_read_byte16;
960 nand->options |= NAND_BUSWIDTH_16;
961 } else {
962 nand->read_byte = fsl_ifc_read_byte;
963 }
964
965 nand->controller = &ifc_ctrl->controller;
966 nand->priv = priv;
967
968 nand->ecc.read_page = fsl_ifc_read_page;
969 nand->ecc.write_page = fsl_ifc_write_page;
970
971 /* Hardware generates ECC per 512 Bytes */
972 nand->ecc.size = 512;
973 nand->ecc.bytes = 8;
974
975 switch (csor & CSOR_NAND_PGS_MASK) {
976 case CSOR_NAND_PGS_512:
977 if (nand->options & NAND_BUSWIDTH_16) {
978 layout = &oob_512_16bit_ecc4;
979 } else {
980 layout = &oob_512_8bit_ecc4;
981
982 /* Avoid conflict with bad block marker */
983 bbt_main_descr.offs = 0;
984 bbt_mirror_descr.offs = 0;
985 }
986
Sergey Lapindfe64e22013-01-14 03:46:50 +0000987 nand->ecc.strength = 4;
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530988 priv->bufnum_mask = 15;
989 break;
990
991 case CSOR_NAND_PGS_2K:
992 layout = &oob_2048_ecc4;
Sergey Lapindfe64e22013-01-14 03:46:50 +0000993 nand->ecc.strength = 4;
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530994 priv->bufnum_mask = 3;
995 break;
996
997 case CSOR_NAND_PGS_4K:
998 if ((csor & CSOR_NAND_ECC_MODE_MASK) ==
999 CSOR_NAND_ECC_MODE_4) {
1000 layout = &oob_4096_ecc4;
Sergey Lapindfe64e22013-01-14 03:46:50 +00001001 nand->ecc.strength = 4;
Dipen Dudhat52f90da2011-03-22 09:27:39 +05301002 } else {
1003 layout = &oob_4096_ecc8;
Sergey Lapindfe64e22013-01-14 03:46:50 +00001004 nand->ecc.strength = 8;
Dipen Dudhat52f90da2011-03-22 09:27:39 +05301005 nand->ecc.bytes = 16;
1006 }
1007
1008 priv->bufnum_mask = 1;
1009 break;
1010
Prabhakar Kushwaha71220f82013-10-04 10:05:36 +05301011 case CSOR_NAND_PGS_8K:
1012 if ((csor & CSOR_NAND_ECC_MODE_MASK) ==
1013 CSOR_NAND_ECC_MODE_4) {
1014 layout = &oob_8192_ecc4;
1015 nand->ecc.strength = 4;
1016 } else {
1017 layout = &oob_8192_ecc8;
1018 nand->ecc.strength = 8;
1019 nand->ecc.bytes = 16;
1020 }
1021
1022 priv->bufnum_mask = 0;
1023 break;
1024
1025
Dipen Dudhat52f90da2011-03-22 09:27:39 +05301026 default:
1027 printf("ifc nand: bad csor %#x: bad page size\n", csor);
1028 return -ENODEV;
1029 }
1030
1031 /* Must also set CSOR_NAND_ECC_ENC_EN if DEC_EN set */
1032 if (csor & CSOR_NAND_ECC_DEC_EN) {
1033 nand->ecc.mode = NAND_ECC_HW;
1034 nand->ecc.layout = layout;
1035 } else {
1036 nand->ecc.mode = NAND_ECC_SOFT;
1037 }
1038
Prabhakar Kushwaha1b4175d2014-01-18 12:28:30 +05301039 ver = ifc_in32(&ifc_ctrl->regs->ifc_rev);
Prabhakar Kushwaha04818bb2014-06-12 12:14:00 +05301040 if (ver >= FSL_IFC_V1_1_0)
1041 ret = fsl_ifc_sram_init(ver);
1042 if (ret)
1043 return ret;
Prabhakar Kushwaha79da5e32012-09-12 22:26:05 +00001044
Prabhakar Kushwaha591dd192014-06-14 08:48:19 +05301045 if (ver >= FSL_IFC_V2_0_0)
1046 priv->bufnum_mask = (priv->bufnum_mask * 2) + 1;
1047
Prabhakar Kushwahaa1b81ab2013-04-04 18:44:06 +00001048 ret = nand_scan_ident(mtd, 1, NULL);
1049 if (ret)
1050 return ret;
1051
1052 ret = nand_scan_tail(mtd);
1053 if (ret)
1054 return ret;
1055
1056 ret = nand_register(devnum);
1057 if (ret)
1058 return ret;
Dipen Dudhat52f90da2011-03-22 09:27:39 +05301059 return 0;
1060}
Prabhakar Kushwahaa1b81ab2013-04-04 18:44:06 +00001061
1062#ifndef CONFIG_SYS_NAND_BASE_LIST
1063#define CONFIG_SYS_NAND_BASE_LIST { CONFIG_SYS_NAND_BASE }
1064#endif
1065
1066static unsigned long base_address[CONFIG_SYS_MAX_NAND_DEVICE] =
1067 CONFIG_SYS_NAND_BASE_LIST;
1068
1069void board_nand_init(void)
1070{
1071 int i;
1072
1073 for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++)
1074 fsl_ifc_chip_init(i, (u8 *)base_address[i]);
1075}