blob: 280e14e24a00290d56784639e88dd22907e3f5d7 [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 Kushwaha79da5e32012-09-12 22:26:05 +000026#define FSL_IFC_V1_1_0 0x01010000
Prabhakar Kushwaha3bab3d82014-06-12 09:13:08 +053027#define MAX_BANKS CONFIG_SYS_FSL_IFC_BANK_COUNT
Dipen Dudhat52f90da2011-03-22 09:27:39 +053028#define ERR_BYTE 0xFF /* Value returned for read bytes
29 when read failed */
30#define IFC_TIMEOUT_MSECS 10 /* Maximum number of mSecs to wait for IFC
31 NAND Machine */
32
33struct fsl_ifc_ctrl;
34
35/* mtd information per set */
36struct fsl_ifc_mtd {
Dipen Dudhat52f90da2011-03-22 09:27:39 +053037 struct nand_chip chip;
38 struct fsl_ifc_ctrl *ctrl;
39
40 struct device *dev;
41 int bank; /* Chip select bank number */
42 unsigned int bufnum_mask; /* bufnum = page & bufnum_mask */
43 u8 __iomem *vbase; /* Chip select base virtual address */
44};
45
46/* overview of the fsl ifc controller */
47struct fsl_ifc_ctrl {
48 struct nand_hw_control controller;
49 struct fsl_ifc_mtd *chips[MAX_BANKS];
50
51 /* device info */
52 struct fsl_ifc *regs;
53 uint8_t __iomem *addr; /* Address of assigned IFC buffer */
54 unsigned int cs_nand; /* On which chipsel NAND is connected */
55 unsigned int page; /* Last page written to / read from */
56 unsigned int read_bytes; /* Number of bytes read during command */
57 unsigned int column; /* Saved column from SEQIN */
58 unsigned int index; /* Pointer to next byte to 'read' */
59 unsigned int status; /* status read from NEESR after last op */
60 unsigned int oob; /* Non zero if operating on OOB data */
61 unsigned int eccread; /* Non zero for a full-page ECC read */
62};
63
64static struct fsl_ifc_ctrl *ifc_ctrl;
65
66/* 512-byte page with 4-bit ECC, 8-bit */
67static struct nand_ecclayout oob_512_8bit_ecc4 = {
68 .eccbytes = 8,
69 .eccpos = {8, 9, 10, 11, 12, 13, 14, 15},
70 .oobfree = { {0, 5}, {6, 2} },
71};
72
73/* 512-byte page with 4-bit ECC, 16-bit */
74static struct nand_ecclayout oob_512_16bit_ecc4 = {
75 .eccbytes = 8,
76 .eccpos = {8, 9, 10, 11, 12, 13, 14, 15},
77 .oobfree = { {2, 6}, },
78};
79
80/* 2048-byte page size with 4-bit ECC */
81static struct nand_ecclayout oob_2048_ecc4 = {
82 .eccbytes = 32,
83 .eccpos = {
84 8, 9, 10, 11, 12, 13, 14, 15,
85 16, 17, 18, 19, 20, 21, 22, 23,
86 24, 25, 26, 27, 28, 29, 30, 31,
87 32, 33, 34, 35, 36, 37, 38, 39,
88 },
89 .oobfree = { {2, 6}, {40, 24} },
90};
91
92/* 4096-byte page size with 4-bit ECC */
93static struct nand_ecclayout oob_4096_ecc4 = {
94 .eccbytes = 64,
95 .eccpos = {
96 8, 9, 10, 11, 12, 13, 14, 15,
97 16, 17, 18, 19, 20, 21, 22, 23,
98 24, 25, 26, 27, 28, 29, 30, 31,
99 32, 33, 34, 35, 36, 37, 38, 39,
100 40, 41, 42, 43, 44, 45, 46, 47,
101 48, 49, 50, 51, 52, 53, 54, 55,
102 56, 57, 58, 59, 60, 61, 62, 63,
103 64, 65, 66, 67, 68, 69, 70, 71,
104 },
105 .oobfree = { {2, 6}, {72, 56} },
106};
107
108/* 4096-byte page size with 8-bit ECC -- requires 218-byte OOB */
109static struct nand_ecclayout oob_4096_ecc8 = {
110 .eccbytes = 128,
111 .eccpos = {
112 8, 9, 10, 11, 12, 13, 14, 15,
113 16, 17, 18, 19, 20, 21, 22, 23,
114 24, 25, 26, 27, 28, 29, 30, 31,
115 32, 33, 34, 35, 36, 37, 38, 39,
116 40, 41, 42, 43, 44, 45, 46, 47,
117 48, 49, 50, 51, 52, 53, 54, 55,
118 56, 57, 58, 59, 60, 61, 62, 63,
119 64, 65, 66, 67, 68, 69, 70, 71,
120 72, 73, 74, 75, 76, 77, 78, 79,
121 80, 81, 82, 83, 84, 85, 86, 87,
122 88, 89, 90, 91, 92, 93, 94, 95,
123 96, 97, 98, 99, 100, 101, 102, 103,
124 104, 105, 106, 107, 108, 109, 110, 111,
125 112, 113, 114, 115, 116, 117, 118, 119,
126 120, 121, 122, 123, 124, 125, 126, 127,
127 128, 129, 130, 131, 132, 133, 134, 135,
128 },
129 .oobfree = { {2, 6}, {136, 82} },
130};
131
Prabhakar Kushwaha71220f82013-10-04 10:05:36 +0530132/* 8192-byte page size with 4-bit ECC */
133static struct nand_ecclayout oob_8192_ecc4 = {
134 .eccbytes = 128,
135 .eccpos = {
136 8, 9, 10, 11, 12, 13, 14, 15,
137 16, 17, 18, 19, 20, 21, 22, 23,
138 24, 25, 26, 27, 28, 29, 30, 31,
139 32, 33, 34, 35, 36, 37, 38, 39,
140 40, 41, 42, 43, 44, 45, 46, 47,
141 48, 49, 50, 51, 52, 53, 54, 55,
142 56, 57, 58, 59, 60, 61, 62, 63,
143 64, 65, 66, 67, 68, 69, 70, 71,
144 72, 73, 74, 75, 76, 77, 78, 79,
145 80, 81, 82, 83, 84, 85, 86, 87,
146 88, 89, 90, 91, 92, 93, 94, 95,
147 96, 97, 98, 99, 100, 101, 102, 103,
148 104, 105, 106, 107, 108, 109, 110, 111,
149 112, 113, 114, 115, 116, 117, 118, 119,
150 120, 121, 122, 123, 124, 125, 126, 127,
151 128, 129, 130, 131, 132, 133, 134, 135,
152 },
153 .oobfree = { {2, 6}, {136, 208} },
154};
155
156/* 8192-byte page size with 8-bit ECC -- requires 218-byte OOB */
157static struct nand_ecclayout oob_8192_ecc8 = {
158 .eccbytes = 256,
159 .eccpos = {
160 8, 9, 10, 11, 12, 13, 14, 15,
161 16, 17, 18, 19, 20, 21, 22, 23,
162 24, 25, 26, 27, 28, 29, 30, 31,
163 32, 33, 34, 35, 36, 37, 38, 39,
164 40, 41, 42, 43, 44, 45, 46, 47,
165 48, 49, 50, 51, 52, 53, 54, 55,
166 56, 57, 58, 59, 60, 61, 62, 63,
167 64, 65, 66, 67, 68, 69, 70, 71,
168 72, 73, 74, 75, 76, 77, 78, 79,
169 80, 81, 82, 83, 84, 85, 86, 87,
170 88, 89, 90, 91, 92, 93, 94, 95,
171 96, 97, 98, 99, 100, 101, 102, 103,
172 104, 105, 106, 107, 108, 109, 110, 111,
173 112, 113, 114, 115, 116, 117, 118, 119,
174 120, 121, 122, 123, 124, 125, 126, 127,
175 128, 129, 130, 131, 132, 133, 134, 135,
176 136, 137, 138, 139, 140, 141, 142, 143,
177 144, 145, 146, 147, 148, 149, 150, 151,
178 152, 153, 154, 155, 156, 157, 158, 159,
179 160, 161, 162, 163, 164, 165, 166, 167,
180 168, 169, 170, 171, 172, 173, 174, 175,
181 176, 177, 178, 179, 180, 181, 182, 183,
182 184, 185, 186, 187, 188, 189, 190, 191,
183 192, 193, 194, 195, 196, 197, 198, 199,
184 200, 201, 202, 203, 204, 205, 206, 207,
185 208, 209, 210, 211, 212, 213, 214, 215,
186 216, 217, 218, 219, 220, 221, 222, 223,
187 224, 225, 226, 227, 228, 229, 230, 231,
188 232, 233, 234, 235, 236, 237, 238, 239,
189 240, 241, 242, 243, 244, 245, 246, 247,
190 248, 249, 250, 251, 252, 253, 254, 255,
191 256, 257, 258, 259, 260, 261, 262, 263,
192 },
193 .oobfree = { {2, 6}, {264, 80} },
194};
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530195
196/*
197 * Generic flash bbt descriptors
198 */
199static u8 bbt_pattern[] = {'B', 'b', 't', '0' };
200static u8 mirror_pattern[] = {'1', 't', 'b', 'B' };
201
202static struct nand_bbt_descr bbt_main_descr = {
203 .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE |
204 NAND_BBT_2BIT | NAND_BBT_VERSION,
205 .offs = 2, /* 0 on 8-bit small page */
206 .len = 4,
207 .veroffs = 6,
208 .maxblocks = 4,
209 .pattern = bbt_pattern,
210};
211
212static struct nand_bbt_descr bbt_mirror_descr = {
213 .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE |
214 NAND_BBT_2BIT | NAND_BBT_VERSION,
215 .offs = 2, /* 0 on 8-bit small page */
216 .len = 4,
217 .veroffs = 6,
218 .maxblocks = 4,
219 .pattern = mirror_pattern,
220};
221
222/*
223 * Set up the IFC hardware block and page address fields, and the ifc nand
224 * structure addr field to point to the correct IFC buffer in memory
225 */
226static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob)
227{
228 struct nand_chip *chip = mtd->priv;
229 struct fsl_ifc_mtd *priv = chip->priv;
230 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
231 struct fsl_ifc *ifc = ctrl->regs;
232 int buf_num;
233
234 ctrl->page = page_addr;
235
236 /* Program ROW0/COL0 */
Prabhakar Kushwaha1b4175d2014-01-18 12:28:30 +0530237 ifc_out32(&ifc->ifc_nand.row0, page_addr);
238 ifc_out32(&ifc->ifc_nand.col0, (oob ? IFC_NAND_COL_MS : 0) | column);
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530239
240 buf_num = page_addr & priv->bufnum_mask;
241
242 ctrl->addr = priv->vbase + buf_num * (mtd->writesize * 2);
243 ctrl->index = column;
244
245 /* for OOB data point to the second half of the buffer */
246 if (oob)
247 ctrl->index += mtd->writesize;
248}
249
250static int is_blank(struct mtd_info *mtd, struct fsl_ifc_ctrl *ctrl,
251 unsigned int bufnum)
252{
253 struct nand_chip *chip = mtd->priv;
254 struct fsl_ifc_mtd *priv = chip->priv;
255 u8 __iomem *addr = priv->vbase + bufnum * (mtd->writesize * 2);
256 u32 __iomem *main = (u32 *)addr;
257 u8 __iomem *oob = addr + mtd->writesize;
258 int i;
259
260 for (i = 0; i < mtd->writesize / 4; i++) {
261 if (__raw_readl(&main[i]) != 0xffffffff)
262 return 0;
263 }
264
265 for (i = 0; i < chip->ecc.layout->eccbytes; i++) {
266 int pos = chip->ecc.layout->eccpos[i];
267
268 if (__raw_readb(&oob[pos]) != 0xff)
269 return 0;
270 }
271
272 return 1;
273}
274
275/* returns nonzero if entire page is blank */
276static int check_read_ecc(struct mtd_info *mtd, struct fsl_ifc_ctrl *ctrl,
277 u32 *eccstat, unsigned int bufnum)
278{
279 u32 reg = eccstat[bufnum / 4];
Prabhakar Kushwaha5f720b82012-01-20 18:38:14 +0530280 int errors;
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530281
Prabhakar Kushwaha5f720b82012-01-20 18:38:14 +0530282 errors = (reg >> ((3 - bufnum % 4) * 8)) & 15;
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530283
Prabhakar Kushwaha5f720b82012-01-20 18:38:14 +0530284 return errors;
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530285}
286
287/*
288 * execute IFC NAND command and wait for it to complete
289 */
290static int fsl_ifc_run_command(struct mtd_info *mtd)
291{
292 struct nand_chip *chip = mtd->priv;
293 struct fsl_ifc_mtd *priv = chip->priv;
294 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
295 struct fsl_ifc *ifc = ctrl->regs;
296 long long end_tick;
297 u32 eccstat[4];
298 int i;
299
300 /* set the chip select for NAND Transaction */
Prabhakar Kushwaha1b4175d2014-01-18 12:28:30 +0530301 ifc_out32(&ifc->ifc_nand.nand_csel, ifc_ctrl->cs_nand);
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530302
303 /* start read/write seq */
Prabhakar Kushwaha1b4175d2014-01-18 12:28:30 +0530304 ifc_out32(&ifc->ifc_nand.nandseq_strt,
305 IFC_NAND_SEQ_STRT_FIR_STRT);
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530306
307 /* wait for NAND Machine complete flag or timeout */
308 end_tick = usec2ticks(IFC_TIMEOUT_MSECS * 1000) + get_ticks();
309
310 while (end_tick > get_ticks()) {
Prabhakar Kushwaha1b4175d2014-01-18 12:28:30 +0530311 ctrl->status = ifc_in32(&ifc->ifc_nand.nand_evter_stat);
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530312
313 if (ctrl->status & IFC_NAND_EVTER_STAT_OPC)
314 break;
315 }
316
Prabhakar Kushwaha1b4175d2014-01-18 12:28:30 +0530317 ifc_out32(&ifc->ifc_nand.nand_evter_stat, ctrl->status);
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530318
319 if (ctrl->status & IFC_NAND_EVTER_STAT_FTOER)
320 printf("%s: Flash Time Out Error\n", __func__);
321 if (ctrl->status & IFC_NAND_EVTER_STAT_WPER)
322 printf("%s: Write Protect Error\n", __func__);
323
324 if (ctrl->eccread) {
Prabhakar Kushwaha5f720b82012-01-20 18:38:14 +0530325 int errors;
326 int bufnum = ctrl->page & priv->bufnum_mask;
327 int sector = bufnum * chip->ecc.steps;
328 int sector_end = sector + chip->ecc.steps - 1;
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530329
Prabhakar Kushwaha5f720b82012-01-20 18:38:14 +0530330 for (i = sector / 4; i <= sector_end / 4; i++)
Prabhakar Kushwaha1b4175d2014-01-18 12:28:30 +0530331 eccstat[i] = ifc_in32(&ifc->ifc_nand.nand_eccstat[i]);
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530332
Prabhakar Kushwaha5f720b82012-01-20 18:38:14 +0530333 for (i = sector; i <= sector_end; i++) {
334 errors = check_read_ecc(mtd, ctrl, eccstat, i);
335
336 if (errors == 15) {
337 /*
338 * Uncorrectable error.
339 * OK only if the whole page is blank.
340 *
341 * We disable ECCER reporting due to erratum
342 * IFC-A002770 -- so report it now if we
343 * see an uncorrectable error in ECCSTAT.
344 */
345 if (!is_blank(mtd, ctrl, bufnum))
346 ctrl->status |=
347 IFC_NAND_EVTER_STAT_ECCER;
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530348 break;
Prabhakar Kushwaha5f720b82012-01-20 18:38:14 +0530349 }
350
351 mtd->ecc_stats.corrected += errors;
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530352 }
353
354 ctrl->eccread = 0;
355 }
356
357 /* returns 0 on success otherwise non-zero) */
358 return ctrl->status == IFC_NAND_EVTER_STAT_OPC ? 0 : -EIO;
359}
360
361static void fsl_ifc_do_read(struct nand_chip *chip,
362 int oob,
363 struct mtd_info *mtd)
364{
365 struct fsl_ifc_mtd *priv = chip->priv;
366 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
367 struct fsl_ifc *ifc = ctrl->regs;
368
369 /* Program FIR/IFC_NAND_FCR0 for Small/Large page */
370 if (mtd->writesize > 512) {
Prabhakar Kushwaha1b4175d2014-01-18 12:28:30 +0530371 ifc_out32(&ifc->ifc_nand.nand_fir0,
372 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
373 (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP1_SHIFT) |
374 (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP2_SHIFT) |
375 (IFC_FIR_OP_CMD1 << IFC_NAND_FIR0_OP3_SHIFT) |
376 (IFC_FIR_OP_RBCD << IFC_NAND_FIR0_OP4_SHIFT));
377 ifc_out32(&ifc->ifc_nand.nand_fir1, 0x0);
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530378
Prabhakar Kushwaha1b4175d2014-01-18 12:28:30 +0530379 ifc_out32(&ifc->ifc_nand.nand_fcr0,
380 (NAND_CMD_READ0 << IFC_NAND_FCR0_CMD0_SHIFT) |
381 (NAND_CMD_READSTART << IFC_NAND_FCR0_CMD1_SHIFT));
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530382 } else {
Prabhakar Kushwaha1b4175d2014-01-18 12:28:30 +0530383 ifc_out32(&ifc->ifc_nand.nand_fir0,
384 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
385 (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP1_SHIFT) |
386 (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP2_SHIFT) |
387 (IFC_FIR_OP_RBCD << IFC_NAND_FIR0_OP3_SHIFT));
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530388
389 if (oob)
Prabhakar Kushwaha1b4175d2014-01-18 12:28:30 +0530390 ifc_out32(&ifc->ifc_nand.nand_fcr0,
391 NAND_CMD_READOOB << IFC_NAND_FCR0_CMD0_SHIFT);
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530392 else
Prabhakar Kushwaha1b4175d2014-01-18 12:28:30 +0530393 ifc_out32(&ifc->ifc_nand.nand_fcr0,
394 NAND_CMD_READ0 << IFC_NAND_FCR0_CMD0_SHIFT);
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530395 }
396}
397
398/* cmdfunc send commands to the IFC NAND Machine */
399static void fsl_ifc_cmdfunc(struct mtd_info *mtd, unsigned int command,
400 int column, int page_addr)
401{
402 struct nand_chip *chip = mtd->priv;
403 struct fsl_ifc_mtd *priv = chip->priv;
404 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
405 struct fsl_ifc *ifc = ctrl->regs;
406
407 /* clear the read buffer */
408 ctrl->read_bytes = 0;
409 if (command != NAND_CMD_PAGEPROG)
410 ctrl->index = 0;
411
412 switch (command) {
413 /* READ0 read the entire buffer to use hardware ECC. */
414 case NAND_CMD_READ0: {
Prabhakar Kushwaha1b4175d2014-01-18 12:28:30 +0530415 ifc_out32(&ifc->ifc_nand.nand_fbcr, 0);
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530416 set_addr(mtd, 0, page_addr, 0);
417
418 ctrl->read_bytes = mtd->writesize + mtd->oobsize;
419 ctrl->index += column;
420
421 if (chip->ecc.mode == NAND_ECC_HW)
422 ctrl->eccread = 1;
423
424 fsl_ifc_do_read(chip, 0, mtd);
425 fsl_ifc_run_command(mtd);
426 return;
427 }
428
429 /* READOOB reads only the OOB because no ECC is performed. */
430 case NAND_CMD_READOOB:
Prabhakar Kushwaha1b4175d2014-01-18 12:28:30 +0530431 ifc_out32(&ifc->ifc_nand.nand_fbcr, mtd->oobsize - column);
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530432 set_addr(mtd, column, page_addr, 1);
433
434 ctrl->read_bytes = mtd->writesize + mtd->oobsize;
435
436 fsl_ifc_do_read(chip, 1, mtd);
437 fsl_ifc_run_command(mtd);
438
439 return;
440
441 /* READID must read all possible bytes while CEB is active */
442 case NAND_CMD_READID:
Prabhakar Kushwaha807fc702012-04-08 18:57:18 +0000443 case NAND_CMD_PARAM: {
444 int timing = IFC_FIR_OP_RB;
445 if (command == NAND_CMD_PARAM)
446 timing = IFC_FIR_OP_RBCD;
447
Prabhakar Kushwaha1b4175d2014-01-18 12:28:30 +0530448 ifc_out32(&ifc->ifc_nand.nand_fir0,
449 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
450 (IFC_FIR_OP_UA << IFC_NAND_FIR0_OP1_SHIFT) |
451 (timing << IFC_NAND_FIR0_OP2_SHIFT));
452 ifc_out32(&ifc->ifc_nand.nand_fcr0,
453 command << IFC_NAND_FCR0_CMD0_SHIFT);
454 ifc_out32(&ifc->ifc_nand.row3, column);
Prabhakar Kushwaha807fc702012-04-08 18:57:18 +0000455
456 /*
457 * although currently it's 8 bytes for READID, we always read
458 * the maximum 256 bytes(for PARAM)
459 */
Prabhakar Kushwaha1b4175d2014-01-18 12:28:30 +0530460 ifc_out32(&ifc->ifc_nand.nand_fbcr, 256);
Prabhakar Kushwaha807fc702012-04-08 18:57:18 +0000461 ctrl->read_bytes = 256;
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530462
463 set_addr(mtd, 0, 0, 0);
464 fsl_ifc_run_command(mtd);
465 return;
Prabhakar Kushwaha807fc702012-04-08 18:57:18 +0000466 }
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530467
468 /* ERASE1 stores the block and page address */
469 case NAND_CMD_ERASE1:
470 set_addr(mtd, 0, page_addr, 0);
471 return;
472
473 /* ERASE2 uses the block and page address from ERASE1 */
474 case NAND_CMD_ERASE2:
Prabhakar Kushwaha1b4175d2014-01-18 12:28:30 +0530475 ifc_out32(&ifc->ifc_nand.nand_fir0,
476 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
477 (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP1_SHIFT) |
478 (IFC_FIR_OP_CMD1 << IFC_NAND_FIR0_OP2_SHIFT));
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530479
Prabhakar Kushwaha1b4175d2014-01-18 12:28:30 +0530480 ifc_out32(&ifc->ifc_nand.nand_fcr0,
481 (NAND_CMD_ERASE1 << IFC_NAND_FCR0_CMD0_SHIFT) |
482 (NAND_CMD_ERASE2 << IFC_NAND_FCR0_CMD1_SHIFT));
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530483
Prabhakar Kushwaha1b4175d2014-01-18 12:28:30 +0530484 ifc_out32(&ifc->ifc_nand.nand_fbcr, 0);
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530485 ctrl->read_bytes = 0;
486 fsl_ifc_run_command(mtd);
487 return;
488
489 /* SEQIN sets up the addr buffer and all registers except the length */
490 case NAND_CMD_SEQIN: {
491 u32 nand_fcr0;
492 ctrl->column = column;
493 ctrl->oob = 0;
494
495 if (mtd->writesize > 512) {
496 nand_fcr0 =
497 (NAND_CMD_SEQIN << IFC_NAND_FCR0_CMD0_SHIFT) |
Prabhakar Kushwahaed5ac342013-10-03 11:35:35 +0530498 (NAND_CMD_STATUS << IFC_NAND_FCR0_CMD1_SHIFT) |
499 (NAND_CMD_PAGEPROG << IFC_NAND_FCR0_CMD2_SHIFT);
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530500
Prabhakar Kushwaha1b4175d2014-01-18 12:28:30 +0530501 ifc_out32(&ifc->ifc_nand.nand_fir0,
502 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
503 (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP1_SHIFT) |
504 (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP2_SHIFT) |
505 (IFC_FIR_OP_WBCD <<
506 IFC_NAND_FIR0_OP3_SHIFT) |
507 (IFC_FIR_OP_CMD2 << IFC_NAND_FIR0_OP4_SHIFT));
508 ifc_out32(&ifc->ifc_nand.nand_fir1,
509 (IFC_FIR_OP_CW1 << IFC_NAND_FIR1_OP5_SHIFT) |
510 (IFC_FIR_OP_RDSTAT <<
Prabhakar Kushwahaed5ac342013-10-03 11:35:35 +0530511 IFC_NAND_FIR1_OP6_SHIFT) |
Prabhakar Kushwaha1b4175d2014-01-18 12:28:30 +0530512 (IFC_FIR_OP_NOP << IFC_NAND_FIR1_OP7_SHIFT));
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530513 } else {
514 nand_fcr0 = ((NAND_CMD_PAGEPROG <<
515 IFC_NAND_FCR0_CMD1_SHIFT) |
516 (NAND_CMD_SEQIN <<
Prabhakar Kushwahaed5ac342013-10-03 11:35:35 +0530517 IFC_NAND_FCR0_CMD2_SHIFT) |
518 (NAND_CMD_STATUS <<
519 IFC_NAND_FCR0_CMD3_SHIFT));
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530520
Prabhakar Kushwaha1b4175d2014-01-18 12:28:30 +0530521 ifc_out32(&ifc->ifc_nand.nand_fir0,
522 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
523 (IFC_FIR_OP_CMD2 << IFC_NAND_FIR0_OP1_SHIFT) |
524 (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP2_SHIFT) |
525 (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP3_SHIFT) |
526 (IFC_FIR_OP_WBCD << IFC_NAND_FIR0_OP4_SHIFT));
527 ifc_out32(&ifc->ifc_nand.nand_fir1,
528 (IFC_FIR_OP_CMD1 << IFC_NAND_FIR1_OP5_SHIFT) |
529 (IFC_FIR_OP_CW3 << IFC_NAND_FIR1_OP6_SHIFT) |
530 (IFC_FIR_OP_RDSTAT <<
Prabhakar Kushwahaed5ac342013-10-03 11:35:35 +0530531 IFC_NAND_FIR1_OP7_SHIFT) |
Prabhakar Kushwaha1b4175d2014-01-18 12:28:30 +0530532 (IFC_FIR_OP_NOP << IFC_NAND_FIR1_OP8_SHIFT));
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530533
Prabhakar Kushwahad9036122012-01-20 18:39:05 +0530534 if (column >= mtd->writesize)
535 nand_fcr0 |=
536 NAND_CMD_READOOB << IFC_NAND_FCR0_CMD0_SHIFT;
537 else
538 nand_fcr0 |=
539 NAND_CMD_READ0 << IFC_NAND_FCR0_CMD0_SHIFT;
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530540 }
541
Prabhakar Kushwahad9036122012-01-20 18:39:05 +0530542 if (column >= mtd->writesize) {
543 /* OOB area --> READOOB */
544 column -= mtd->writesize;
545 ctrl->oob = 1;
546 }
Prabhakar Kushwaha1b4175d2014-01-18 12:28:30 +0530547 ifc_out32(&ifc->ifc_nand.nand_fcr0, nand_fcr0);
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530548 set_addr(mtd, column, page_addr, ctrl->oob);
549 return;
550 }
551
552 /* PAGEPROG reuses all of the setup from SEQIN and adds the length */
553 case NAND_CMD_PAGEPROG:
554 if (ctrl->oob)
Prabhakar Kushwaha1b4175d2014-01-18 12:28:30 +0530555 ifc_out32(&ifc->ifc_nand.nand_fbcr,
556 ctrl->index - ctrl->column);
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530557 else
Prabhakar Kushwaha1b4175d2014-01-18 12:28:30 +0530558 ifc_out32(&ifc->ifc_nand.nand_fbcr, 0);
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530559
560 fsl_ifc_run_command(mtd);
561 return;
562
563 case NAND_CMD_STATUS:
Prabhakar Kushwaha1b4175d2014-01-18 12:28:30 +0530564 ifc_out32(&ifc->ifc_nand.nand_fir0,
565 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
566 (IFC_FIR_OP_RB << IFC_NAND_FIR0_OP1_SHIFT));
567 ifc_out32(&ifc->ifc_nand.nand_fcr0,
568 NAND_CMD_STATUS << IFC_NAND_FCR0_CMD0_SHIFT);
569 ifc_out32(&ifc->ifc_nand.nand_fbcr, 1);
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530570 set_addr(mtd, 0, 0, 0);
571 ctrl->read_bytes = 1;
572
573 fsl_ifc_run_command(mtd);
574
575 /* Chip sometimes reporting write protect even when it's not */
576 out_8(ctrl->addr, in_8(ctrl->addr) | NAND_STATUS_WP);
577 return;
578
579 case NAND_CMD_RESET:
Prabhakar Kushwaha1b4175d2014-01-18 12:28:30 +0530580 ifc_out32(&ifc->ifc_nand.nand_fir0,
581 IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT);
582 ifc_out32(&ifc->ifc_nand.nand_fcr0,
583 NAND_CMD_RESET << IFC_NAND_FCR0_CMD0_SHIFT);
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530584 fsl_ifc_run_command(mtd);
585 return;
586
587 default:
588 printf("%s: error, unsupported command 0x%x.\n",
589 __func__, command);
590 }
591}
592
593/*
594 * Write buf to the IFC NAND Controller Data Buffer
595 */
596static void fsl_ifc_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
597{
598 struct nand_chip *chip = mtd->priv;
599 struct fsl_ifc_mtd *priv = chip->priv;
600 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
601 unsigned int bufsize = mtd->writesize + mtd->oobsize;
602
603 if (len <= 0) {
604 printf("%s of %d bytes", __func__, len);
605 ctrl->status = 0;
606 return;
607 }
608
609 if ((unsigned int)len > bufsize - ctrl->index) {
610 printf("%s beyond end of buffer "
611 "(%d requested, %u available)\n",
612 __func__, len, bufsize - ctrl->index);
613 len = bufsize - ctrl->index;
614 }
615
616 memcpy_toio(&ctrl->addr[ctrl->index], buf, len);
617 ctrl->index += len;
618}
619
620/*
621 * read a byte from either the IFC hardware buffer if it has any data left
622 * otherwise issue a command to read a single byte.
623 */
624static u8 fsl_ifc_read_byte(struct mtd_info *mtd)
625{
626 struct nand_chip *chip = mtd->priv;
627 struct fsl_ifc_mtd *priv = chip->priv;
628 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
629
630 /* If there are still bytes in the IFC buffer, then use the
631 * next byte. */
632 if (ctrl->index < ctrl->read_bytes)
633 return in_8(&ctrl->addr[ctrl->index++]);
634
635 printf("%s beyond end of buffer\n", __func__);
636 return ERR_BYTE;
637}
638
639/*
640 * Read two bytes from the IFC hardware buffer
641 * read function for 16-bit buswith
642 */
643static uint8_t fsl_ifc_read_byte16(struct mtd_info *mtd)
644{
645 struct nand_chip *chip = mtd->priv;
646 struct fsl_ifc_mtd *priv = chip->priv;
647 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
648 uint16_t data;
649
650 /*
651 * If there are still bytes in the IFC buffer, then use the
652 * next byte.
653 */
654 if (ctrl->index < ctrl->read_bytes) {
Prabhakar Kushwaha1b4175d2014-01-18 12:28:30 +0530655 data = ifc_in16((uint16_t *)&ctrl->
656 addr[ctrl->index]);
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530657 ctrl->index += 2;
658 return (uint8_t)data;
659 }
660
661 printf("%s beyond end of buffer\n", __func__);
662 return ERR_BYTE;
663}
664
665/*
666 * Read from the IFC Controller Data Buffer
667 */
668static void fsl_ifc_read_buf(struct mtd_info *mtd, u8 *buf, int len)
669{
670 struct nand_chip *chip = mtd->priv;
671 struct fsl_ifc_mtd *priv = chip->priv;
672 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
673 int avail;
674
675 if (len < 0)
676 return;
677
678 avail = min((unsigned int)len, ctrl->read_bytes - ctrl->index);
679 memcpy_fromio(buf, &ctrl->addr[ctrl->index], avail);
680 ctrl->index += avail;
681
682 if (len > avail)
683 printf("%s beyond end of buffer "
684 "(%d requested, %d available)\n",
685 __func__, len, avail);
686}
687
688/*
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}
720
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 Kushwaha79da5e32012-09-12 22:26:05 +0000814 long long end_tick;
815
Prabhakar Kushwaha04818bb2014-06-12 12:14:00 +0530816 if (ver > FSL_IFC_V1_1_0) {
817 ncfgr = ifc_in32(&ifc->ifc_nand.ncfgr);
818 ifc_out32(&ifc->ifc_nand.ncfgr, ncfgr | IFC_NAND_SRAM_INIT_EN);
819
820 /* wait for SRAM_INIT bit to be clear or timeout */
821 end_tick = usec2ticks(IFC_TIMEOUT_MSECS * 1000) + get_ticks();
822 while (end_tick > get_ticks()) {
823 ifc_ctrl->status =
824 ifc_in32(&ifc->ifc_nand.nand_evter_stat);
825
826 if (!(ifc_ctrl->status & IFC_NAND_SRAM_INIT_EN))
827 return 0;
828 }
829 printf("fsl-ifc: Failed to Initialise SRAM\n");
830 return 1;
831 }
832
Prabhakar Kushwaha79da5e32012-09-12 22:26:05 +0000833 cs = ifc_ctrl->cs_nand >> IFC_NAND_CSEL_SHIFT;
834
835 /* Save CSOR and CSOR_ext */
Prabhakar Kushwaha1b4175d2014-01-18 12:28:30 +0530836 csor = ifc_in32(&ifc_ctrl->regs->csor_cs[cs].csor);
837 csor_ext = ifc_in32(&ifc_ctrl->regs->csor_cs[cs].csor_ext);
Prabhakar Kushwaha79da5e32012-09-12 22:26:05 +0000838
839 /* chage PageSize 8K and SpareSize 1K*/
840 csor_8k = (csor & ~(CSOR_NAND_PGS_MASK)) | 0x0018C000;
Prabhakar Kushwaha1b4175d2014-01-18 12:28:30 +0530841 ifc_out32(&ifc_ctrl->regs->csor_cs[cs].csor, csor_8k);
842 ifc_out32(&ifc_ctrl->regs->csor_cs[cs].csor_ext, 0x0000400);
Prabhakar Kushwaha79da5e32012-09-12 22:26:05 +0000843
844 /* READID */
Prabhakar Kushwaha1b4175d2014-01-18 12:28:30 +0530845 ifc_out32(&ifc->ifc_nand.nand_fir0,
846 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
847 (IFC_FIR_OP_UA << IFC_NAND_FIR0_OP1_SHIFT) |
848 (IFC_FIR_OP_RB << IFC_NAND_FIR0_OP2_SHIFT));
849 ifc_out32(&ifc->ifc_nand.nand_fcr0,
850 NAND_CMD_READID << IFC_NAND_FCR0_CMD0_SHIFT);
851 ifc_out32(&ifc->ifc_nand.row3, 0x0);
Prabhakar Kushwaha79da5e32012-09-12 22:26:05 +0000852
Prabhakar Kushwaha1b4175d2014-01-18 12:28:30 +0530853 ifc_out32(&ifc->ifc_nand.nand_fbcr, 0x0);
Prabhakar Kushwaha79da5e32012-09-12 22:26:05 +0000854
855 /* Program ROW0/COL0 */
Prabhakar Kushwaha1b4175d2014-01-18 12:28:30 +0530856 ifc_out32(&ifc->ifc_nand.row0, 0x0);
857 ifc_out32(&ifc->ifc_nand.col0, 0x0);
Prabhakar Kushwaha79da5e32012-09-12 22:26:05 +0000858
859 /* set the chip select for NAND Transaction */
Prabhakar Kushwaha1b4175d2014-01-18 12:28:30 +0530860 ifc_out32(&ifc->ifc_nand.nand_csel, ifc_ctrl->cs_nand);
Prabhakar Kushwaha79da5e32012-09-12 22:26:05 +0000861
862 /* start read seq */
Prabhakar Kushwaha1b4175d2014-01-18 12:28:30 +0530863 ifc_out32(&ifc->ifc_nand.nandseq_strt, IFC_NAND_SEQ_STRT_FIR_STRT);
Prabhakar Kushwaha79da5e32012-09-12 22:26:05 +0000864
865 /* wait for NAND Machine complete flag or timeout */
866 end_tick = usec2ticks(IFC_TIMEOUT_MSECS * 1000) + get_ticks();
867
868 while (end_tick > get_ticks()) {
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;
943 nand->verify_buf = fsl_ifc_verify_buf;
944 nand->select_chip = fsl_ifc_select_chip;
945 nand->cmdfunc = fsl_ifc_cmdfunc;
946 nand->waitfunc = fsl_ifc_wait;
947
948 /* set up nand options */
949 nand->bbt_td = &bbt_main_descr;
950 nand->bbt_md = &bbt_mirror_descr;
951
952 /* set up nand options */
Sergey Lapindfe64e22013-01-14 03:46:50 +0000953 nand->options = NAND_NO_SUBPAGE_WRITE;
954 nand->bbt_options = NAND_BBT_USE_FLASH;
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530955
956 if (cspr & CSPR_PORT_SIZE_16) {
957 nand->read_byte = fsl_ifc_read_byte16;
958 nand->options |= NAND_BUSWIDTH_16;
959 } else {
960 nand->read_byte = fsl_ifc_read_byte;
961 }
962
963 nand->controller = &ifc_ctrl->controller;
964 nand->priv = priv;
965
966 nand->ecc.read_page = fsl_ifc_read_page;
967 nand->ecc.write_page = fsl_ifc_write_page;
968
969 /* Hardware generates ECC per 512 Bytes */
970 nand->ecc.size = 512;
971 nand->ecc.bytes = 8;
972
973 switch (csor & CSOR_NAND_PGS_MASK) {
974 case CSOR_NAND_PGS_512:
975 if (nand->options & NAND_BUSWIDTH_16) {
976 layout = &oob_512_16bit_ecc4;
977 } else {
978 layout = &oob_512_8bit_ecc4;
979
980 /* Avoid conflict with bad block marker */
981 bbt_main_descr.offs = 0;
982 bbt_mirror_descr.offs = 0;
983 }
984
Sergey Lapindfe64e22013-01-14 03:46:50 +0000985 nand->ecc.strength = 4;
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530986 priv->bufnum_mask = 15;
987 break;
988
989 case CSOR_NAND_PGS_2K:
990 layout = &oob_2048_ecc4;
Sergey Lapindfe64e22013-01-14 03:46:50 +0000991 nand->ecc.strength = 4;
Dipen Dudhat52f90da2011-03-22 09:27:39 +0530992 priv->bufnum_mask = 3;
993 break;
994
995 case CSOR_NAND_PGS_4K:
996 if ((csor & CSOR_NAND_ECC_MODE_MASK) ==
997 CSOR_NAND_ECC_MODE_4) {
998 layout = &oob_4096_ecc4;
Sergey Lapindfe64e22013-01-14 03:46:50 +0000999 nand->ecc.strength = 4;
Dipen Dudhat52f90da2011-03-22 09:27:39 +05301000 } else {
1001 layout = &oob_4096_ecc8;
Sergey Lapindfe64e22013-01-14 03:46:50 +00001002 nand->ecc.strength = 8;
Dipen Dudhat52f90da2011-03-22 09:27:39 +05301003 nand->ecc.bytes = 16;
1004 }
1005
1006 priv->bufnum_mask = 1;
1007 break;
1008
Prabhakar Kushwaha71220f82013-10-04 10:05:36 +05301009 case CSOR_NAND_PGS_8K:
1010 if ((csor & CSOR_NAND_ECC_MODE_MASK) ==
1011 CSOR_NAND_ECC_MODE_4) {
1012 layout = &oob_8192_ecc4;
1013 nand->ecc.strength = 4;
1014 } else {
1015 layout = &oob_8192_ecc8;
1016 nand->ecc.strength = 8;
1017 nand->ecc.bytes = 16;
1018 }
1019
1020 priv->bufnum_mask = 0;
1021 break;
1022
1023
Dipen Dudhat52f90da2011-03-22 09:27:39 +05301024 default:
1025 printf("ifc nand: bad csor %#x: bad page size\n", csor);
1026 return -ENODEV;
1027 }
1028
1029 /* Must also set CSOR_NAND_ECC_ENC_EN if DEC_EN set */
1030 if (csor & CSOR_NAND_ECC_DEC_EN) {
1031 nand->ecc.mode = NAND_ECC_HW;
1032 nand->ecc.layout = layout;
1033 } else {
1034 nand->ecc.mode = NAND_ECC_SOFT;
1035 }
1036
Prabhakar Kushwaha1b4175d2014-01-18 12:28:30 +05301037 ver = ifc_in32(&ifc_ctrl->regs->ifc_rev);
Prabhakar Kushwaha04818bb2014-06-12 12:14:00 +05301038 if (ver >= FSL_IFC_V1_1_0)
1039 ret = fsl_ifc_sram_init(ver);
1040 if (ret)
1041 return ret;
Prabhakar Kushwaha79da5e32012-09-12 22:26:05 +00001042
Prabhakar Kushwahaa1b81ab2013-04-04 18:44:06 +00001043 ret = nand_scan_ident(mtd, 1, NULL);
1044 if (ret)
1045 return ret;
1046
1047 ret = nand_scan_tail(mtd);
1048 if (ret)
1049 return ret;
1050
1051 ret = nand_register(devnum);
1052 if (ret)
1053 return ret;
Dipen Dudhat52f90da2011-03-22 09:27:39 +05301054 return 0;
1055}
Prabhakar Kushwahaa1b81ab2013-04-04 18:44:06 +00001056
1057#ifndef CONFIG_SYS_NAND_BASE_LIST
1058#define CONFIG_SYS_NAND_BASE_LIST { CONFIG_SYS_NAND_BASE }
1059#endif
1060
1061static unsigned long base_address[CONFIG_SYS_MAX_NAND_DEVICE] =
1062 CONFIG_SYS_NAND_BASE_LIST;
1063
1064void board_nand_init(void)
1065{
1066 int i;
1067
1068 for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++)
1069 fsl_ifc_chip_init(i, (u8 *)base_address[i]);
1070}