blob: 7903eebd537c595eb9b6af01459983d94cf9ea79 [file] [log] [blame]
Dipen Dudhat9eae0832011-03-22 09:27:39 +05301/* Integrated Flash Controller NAND Machine Driver
2 *
Prabhakar Kushwahacdd045d2012-01-20 18:38:14 +05303 * Copyright (c) 2012 Freescale Semiconductor, Inc
Dipen Dudhat9eae0832011-03-22 09:27:39 +05304 *
5 * Authors: Dipen Dudhat <Dipen.Dudhat@freescale.com>
6 *
Wolfgang Denkd79de1d2013-07-08 09:37:19 +02007 * SPDX-License-Identifier: GPL-2.0+
Dipen Dudhat9eae0832011-03-22 09:27:39 +05308 */
9
10#include <common.h>
11#include <malloc.h>
Prabhakar Kushwaha895d0392013-04-04 18:44:06 +000012#include <nand.h>
Dipen Dudhat9eae0832011-03-22 09:27:39 +053013
14#include <linux/mtd/mtd.h>
15#include <linux/mtd/nand.h>
16#include <linux/mtd/nand_ecc.h>
17
18#include <asm/io.h>
19#include <asm/errno.h>
York Sun37562f62013-10-22 12:39:02 -070020#include <fsl_ifc.h>
Dipen Dudhat9eae0832011-03-22 09:27:39 +053021
Prabhakar Kushwahaa8759642014-06-12 09:13:08 +053022#ifndef CONFIG_SYS_FSL_IFC_BANK_COUNT
23#define CONFIG_SYS_FSL_IFC_BANK_COUNT 4
24#endif
25
Prabhakar Kushwahaa8759642014-06-12 09:13:08 +053026#define MAX_BANKS CONFIG_SYS_FSL_IFC_BANK_COUNT
Dipen Dudhat9eae0832011-03-22 09:27:39 +053027#define ERR_BYTE 0xFF /* Value returned for read bytes
28 when read failed */
Dipen Dudhat9eae0832011-03-22 09:27:39 +053029
30struct fsl_ifc_ctrl;
31
32/* mtd information per set */
33struct fsl_ifc_mtd {
Dipen Dudhat9eae0832011-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 Kushwahaa3aaf1d2013-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 Dudhat9eae0832011-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 Kushwaha62908c22014-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 Dudhat9eae0832011-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 Kushwahacdd045d2012-01-20 18:38:14 +0530277 int errors;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530278
Prabhakar Kushwahacdd045d2012-01-20 18:38:14 +0530279 errors = (reg >> ((3 - bufnum % 4) * 8)) & 15;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530280
Prabhakar Kushwahacdd045d2012-01-20 18:38:14 +0530281 return errors;
Dipen Dudhat9eae0832011-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 Kushwahad7550e12014-09-23 09:57:47 +0530293 u32 timeo = (CONFIG_SYS_HZ * 10) / 1000;
294 u32 time_start;
Jaiprakash Singh175f8df2014-11-27 12:38:12 +0530295 u32 eccstat[4] = {0};
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530296 int i;
297
298 /* set the chip select for NAND Transaction */
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530299 ifc_out32(&ifc->ifc_nand.nand_csel, ifc_ctrl->cs_nand);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530300
301 /* start read/write seq */
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530302 ifc_out32(&ifc->ifc_nand.nandseq_strt,
303 IFC_NAND_SEQ_STRT_FIR_STRT);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530304
305 /* wait for NAND Machine complete flag or timeout */
Prabhakar Kushwahad7550e12014-09-23 09:57:47 +0530306 time_start = get_timer(0);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530307
Prabhakar Kushwahad7550e12014-09-23 09:57:47 +0530308 while (get_timer(time_start) < timeo) {
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530309 ctrl->status = ifc_in32(&ifc->ifc_nand.nand_evter_stat);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530310
311 if (ctrl->status & IFC_NAND_EVTER_STAT_OPC)
312 break;
313 }
314
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530315 ifc_out32(&ifc->ifc_nand.nand_evter_stat, ctrl->status);
Dipen Dudhat9eae0832011-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 Kushwahacdd045d2012-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 Dudhat9eae0832011-03-22 09:27:39 +0530327
Prabhakar Kushwahacdd045d2012-01-20 18:38:14 +0530328 for (i = sector / 4; i <= sector_end / 4; i++)
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530329 eccstat[i] = ifc_in32(&ifc->ifc_nand.nand_eccstat[i]);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530330
Prabhakar Kushwahacdd045d2012-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 Dudhat9eae0832011-03-22 09:27:39 +0530346 break;
Prabhakar Kushwahacdd045d2012-01-20 18:38:14 +0530347 }
348
349 mtd->ecc_stats.corrected += errors;
Dipen Dudhat9eae0832011-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 Kushwaha62908c22014-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 Dudhat9eae0832011-03-22 09:27:39 +0530376
Prabhakar Kushwaha62908c22014-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 Dudhat9eae0832011-03-22 09:27:39 +0530380 } else {
Prabhakar Kushwaha62908c22014-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 Dudhat9eae0832011-03-22 09:27:39 +0530386
387 if (oob)
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530388 ifc_out32(&ifc->ifc_nand.nand_fcr0,
389 NAND_CMD_READOOB << IFC_NAND_FCR0_CMD0_SHIFT);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530390 else
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530391 ifc_out32(&ifc->ifc_nand.nand_fcr0,
392 NAND_CMD_READ0 << IFC_NAND_FCR0_CMD0_SHIFT);
Dipen Dudhat9eae0832011-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 Kushwaha62908c22014-01-18 12:28:30 +0530413 ifc_out32(&ifc->ifc_nand.nand_fbcr, 0);
Dipen Dudhat9eae0832011-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 Kushwaha62908c22014-01-18 12:28:30 +0530429 ifc_out32(&ifc->ifc_nand.nand_fbcr, mtd->oobsize - column);
Dipen Dudhat9eae0832011-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 Kushwahaf31cf532012-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 Kushwaha62908c22014-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 Kushwahaf31cf532012-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 Kushwaha62908c22014-01-18 12:28:30 +0530458 ifc_out32(&ifc->ifc_nand.nand_fbcr, 256);
Prabhakar Kushwahaf31cf532012-04-08 18:57:18 +0000459 ctrl->read_bytes = 256;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530460
461 set_addr(mtd, 0, 0, 0);
462 fsl_ifc_run_command(mtd);
463 return;
Prabhakar Kushwahaf31cf532012-04-08 18:57:18 +0000464 }
Dipen Dudhat9eae0832011-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 Kushwaha62908c22014-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 Dudhat9eae0832011-03-22 09:27:39 +0530477
Prabhakar Kushwaha62908c22014-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 Dudhat9eae0832011-03-22 09:27:39 +0530481
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530482 ifc_out32(&ifc->ifc_nand.nand_fbcr, 0);
Dipen Dudhat9eae0832011-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 Kushwaha18e6bde2013-10-03 11:35:35 +0530496 (NAND_CMD_STATUS << IFC_NAND_FCR0_CMD1_SHIFT) |
497 (NAND_CMD_PAGEPROG << IFC_NAND_FCR0_CMD2_SHIFT);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530498
Prabhakar Kushwaha62908c22014-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 Kushwaha18e6bde2013-10-03 11:35:35 +0530509 IFC_NAND_FIR1_OP6_SHIFT) |
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530510 (IFC_FIR_OP_NOP << IFC_NAND_FIR1_OP7_SHIFT));
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530511 } else {
512 nand_fcr0 = ((NAND_CMD_PAGEPROG <<
513 IFC_NAND_FCR0_CMD1_SHIFT) |
514 (NAND_CMD_SEQIN <<
Prabhakar Kushwaha18e6bde2013-10-03 11:35:35 +0530515 IFC_NAND_FCR0_CMD2_SHIFT) |
516 (NAND_CMD_STATUS <<
517 IFC_NAND_FCR0_CMD3_SHIFT));
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530518
Prabhakar Kushwaha62908c22014-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 Kushwaha18e6bde2013-10-03 11:35:35 +0530529 IFC_NAND_FIR1_OP7_SHIFT) |
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530530 (IFC_FIR_OP_NOP << IFC_NAND_FIR1_OP8_SHIFT));
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530531
Prabhakar Kushwaha0ed5e772012-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 Dudhat9eae0832011-03-22 09:27:39 +0530538 }
539
Prabhakar Kushwaha0ed5e772012-01-20 18:39:05 +0530540 if (column >= mtd->writesize) {
541 /* OOB area --> READOOB */
542 column -= mtd->writesize;
543 ctrl->oob = 1;
544 }
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530545 ifc_out32(&ifc->ifc_nand.nand_fcr0, nand_fcr0);
Dipen Dudhat9eae0832011-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 Kushwaha62908c22014-01-18 12:28:30 +0530553 ifc_out32(&ifc->ifc_nand.nand_fbcr,
554 ctrl->index - ctrl->column);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530555 else
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530556 ifc_out32(&ifc->ifc_nand.nand_fbcr, 0);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530557
558 fsl_ifc_run_command(mtd);
559 return;
560
561 case NAND_CMD_STATUS:
Prabhakar Kushwaha62908c22014-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 Dudhat9eae0832011-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 Kushwaha62908c22014-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 Dudhat9eae0832011-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 Kushwaha62908c22014-01-18 12:28:30 +0530653 data = ifc_in16((uint16_t *)&ctrl->
654 addr[ctrl->index]);
Dipen Dudhat9eae0832011-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
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530686/* This function is called after Program and Erase Operations to
687 * check for success or failure.
688 */
689static int fsl_ifc_wait(struct mtd_info *mtd, struct nand_chip *chip)
690{
691 struct fsl_ifc_mtd *priv = chip->priv;
692 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
693 struct fsl_ifc *ifc = ctrl->regs;
694 u32 nand_fsr;
695
696 if (ctrl->status != IFC_NAND_EVTER_STAT_OPC)
697 return NAND_STATUS_FAIL;
698
699 /* Use READ_STATUS command, but wait for the device to be ready */
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530700 ifc_out32(&ifc->ifc_nand.nand_fir0,
701 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
702 (IFC_FIR_OP_RDSTAT << IFC_NAND_FIR0_OP1_SHIFT));
703 ifc_out32(&ifc->ifc_nand.nand_fcr0, NAND_CMD_STATUS <<
704 IFC_NAND_FCR0_CMD0_SHIFT);
705 ifc_out32(&ifc->ifc_nand.nand_fbcr, 1);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530706 set_addr(mtd, 0, 0, 0);
707 ctrl->read_bytes = 1;
708
709 fsl_ifc_run_command(mtd);
710
711 if (ctrl->status != IFC_NAND_EVTER_STAT_OPC)
712 return NAND_STATUS_FAIL;
713
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530714 nand_fsr = ifc_in32(&ifc->ifc_nand.nand_fsr);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530715
716 /* Chip sometimes reporting write protect even when it's not */
717 nand_fsr = nand_fsr | NAND_STATUS_WP;
718 return nand_fsr;
719}
720
Sergey Lapin3a38a552013-01-14 03:46:50 +0000721static int fsl_ifc_read_page(struct mtd_info *mtd, struct nand_chip *chip,
722 uint8_t *buf, int oob_required, int page)
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530723{
724 struct fsl_ifc_mtd *priv = chip->priv;
725 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
726
727 fsl_ifc_read_buf(mtd, buf, mtd->writesize);
728 fsl_ifc_read_buf(mtd, chip->oob_poi, mtd->oobsize);
729
730 if (ctrl->status != IFC_NAND_EVTER_STAT_OPC)
731 mtd->ecc_stats.failed++;
732
733 return 0;
734}
735
736/* ECC will be calculated automatically, and errors will be detected in
737 * waitfunc.
738 */
Sergey Lapin3a38a552013-01-14 03:46:50 +0000739static int fsl_ifc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
740 const uint8_t *buf, int oob_required)
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530741{
742 fsl_ifc_write_buf(mtd, buf, mtd->writesize);
743 fsl_ifc_write_buf(mtd, chip->oob_poi, mtd->oobsize);
Sergey Lapin3a38a552013-01-14 03:46:50 +0000744
745 return 0;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530746}
747
748static void fsl_ifc_ctrl_init(void)
749{
750 ifc_ctrl = kzalloc(sizeof(*ifc_ctrl), GFP_KERNEL);
751 if (!ifc_ctrl)
752 return;
753
754 ifc_ctrl->regs = IFC_BASE_ADDR;
755
756 /* clear event registers */
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530757 ifc_out32(&ifc_ctrl->regs->ifc_nand.nand_evter_stat, ~0U);
758 ifc_out32(&ifc_ctrl->regs->ifc_nand.pgrdcmpl_evt_stat, ~0U);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530759
760 /* Enable error and event for any detected errors */
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530761 ifc_out32(&ifc_ctrl->regs->ifc_nand.nand_evter_en,
762 IFC_NAND_EVTER_EN_OPC_EN |
763 IFC_NAND_EVTER_EN_PGRDCMPL_EN |
764 IFC_NAND_EVTER_EN_FTOER_EN |
765 IFC_NAND_EVTER_EN_WPER_EN);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530766
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530767 ifc_out32(&ifc_ctrl->regs->ifc_nand.ncfgr, 0x0);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530768}
769
770static void fsl_ifc_select_chip(struct mtd_info *mtd, int chip)
771{
772}
773
Prabhakar Kushwaha82efc812014-06-12 12:14:00 +0530774static int fsl_ifc_sram_init(uint32_t ver)
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000775{
776 struct fsl_ifc *ifc = ifc_ctrl->regs;
777 uint32_t cs = 0, csor = 0, csor_8k = 0, csor_ext = 0;
Prabhakar Kushwaha82efc812014-06-12 12:14:00 +0530778 uint32_t ncfgr = 0;
Prabhakar Kushwahad7550e12014-09-23 09:57:47 +0530779 u32 timeo = (CONFIG_SYS_HZ * 10) / 1000;
780 u32 time_start;
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000781
Prabhakar Kushwaha82efc812014-06-12 12:14:00 +0530782 if (ver > FSL_IFC_V1_1_0) {
783 ncfgr = ifc_in32(&ifc->ifc_nand.ncfgr);
784 ifc_out32(&ifc->ifc_nand.ncfgr, ncfgr | IFC_NAND_SRAM_INIT_EN);
785
786 /* wait for SRAM_INIT bit to be clear or timeout */
Prabhakar Kushwahad7550e12014-09-23 09:57:47 +0530787 time_start = get_timer(0);
788 while (get_timer(time_start) < timeo) {
Prabhakar Kushwaha82efc812014-06-12 12:14:00 +0530789 ifc_ctrl->status =
790 ifc_in32(&ifc->ifc_nand.nand_evter_stat);
791
792 if (!(ifc_ctrl->status & IFC_NAND_SRAM_INIT_EN))
793 return 0;
794 }
795 printf("fsl-ifc: Failed to Initialise SRAM\n");
796 return 1;
797 }
798
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000799 cs = ifc_ctrl->cs_nand >> IFC_NAND_CSEL_SHIFT;
800
801 /* Save CSOR and CSOR_ext */
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530802 csor = ifc_in32(&ifc_ctrl->regs->csor_cs[cs].csor);
803 csor_ext = ifc_in32(&ifc_ctrl->regs->csor_cs[cs].csor_ext);
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000804
805 /* chage PageSize 8K and SpareSize 1K*/
806 csor_8k = (csor & ~(CSOR_NAND_PGS_MASK)) | 0x0018C000;
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530807 ifc_out32(&ifc_ctrl->regs->csor_cs[cs].csor, csor_8k);
808 ifc_out32(&ifc_ctrl->regs->csor_cs[cs].csor_ext, 0x0000400);
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000809
810 /* READID */
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530811 ifc_out32(&ifc->ifc_nand.nand_fir0,
812 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
813 (IFC_FIR_OP_UA << IFC_NAND_FIR0_OP1_SHIFT) |
814 (IFC_FIR_OP_RB << IFC_NAND_FIR0_OP2_SHIFT));
815 ifc_out32(&ifc->ifc_nand.nand_fcr0,
816 NAND_CMD_READID << IFC_NAND_FCR0_CMD0_SHIFT);
817 ifc_out32(&ifc->ifc_nand.row3, 0x0);
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000818
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530819 ifc_out32(&ifc->ifc_nand.nand_fbcr, 0x0);
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000820
821 /* Program ROW0/COL0 */
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530822 ifc_out32(&ifc->ifc_nand.row0, 0x0);
823 ifc_out32(&ifc->ifc_nand.col0, 0x0);
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000824
825 /* set the chip select for NAND Transaction */
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530826 ifc_out32(&ifc->ifc_nand.nand_csel, ifc_ctrl->cs_nand);
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000827
828 /* start read seq */
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530829 ifc_out32(&ifc->ifc_nand.nandseq_strt, IFC_NAND_SEQ_STRT_FIR_STRT);
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000830
Prabhakar Kushwahad7550e12014-09-23 09:57:47 +0530831 time_start = get_timer(0);
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000832
Prabhakar Kushwahad7550e12014-09-23 09:57:47 +0530833 while (get_timer(time_start) < timeo) {
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530834 ifc_ctrl->status = ifc_in32(&ifc->ifc_nand.nand_evter_stat);
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000835
836 if (ifc_ctrl->status & IFC_NAND_EVTER_STAT_OPC)
837 break;
838 }
839
Prabhakar Kushwaha82efc812014-06-12 12:14:00 +0530840 if (ifc_ctrl->status != IFC_NAND_EVTER_STAT_OPC) {
841 printf("fsl-ifc: Failed to Initialise SRAM\n");
842 return 1;
843 }
844
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530845 ifc_out32(&ifc->ifc_nand.nand_evter_stat, ifc_ctrl->status);
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000846
847 /* Restore CSOR and CSOR_ext */
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530848 ifc_out32(&ifc_ctrl->regs->csor_cs[cs].csor, csor);
849 ifc_out32(&ifc_ctrl->regs->csor_cs[cs].csor_ext, csor_ext);
Prabhakar Kushwaha82efc812014-06-12 12:14:00 +0530850
851 return 0;
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000852}
853
Prabhakar Kushwaha895d0392013-04-04 18:44:06 +0000854static int fsl_ifc_chip_init(int devnum, u8 *addr)
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530855{
Prabhakar Kushwaha895d0392013-04-04 18:44:06 +0000856 struct mtd_info *mtd = &nand_info[devnum];
857 struct nand_chip *nand;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530858 struct fsl_ifc_mtd *priv;
859 struct nand_ecclayout *layout;
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000860 uint32_t cspr = 0, csor = 0, ver = 0;
Prabhakar Kushwaha82efc812014-06-12 12:14:00 +0530861 int ret = 0;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530862
863 if (!ifc_ctrl) {
864 fsl_ifc_ctrl_init();
865 if (!ifc_ctrl)
866 return -1;
867 }
868
869 priv = kzalloc(sizeof(*priv), GFP_KERNEL);
870 if (!priv)
871 return -ENOMEM;
872
873 priv->ctrl = ifc_ctrl;
Prabhakar Kushwaha895d0392013-04-04 18:44:06 +0000874 priv->vbase = addr;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530875
876 /* Find which chip select it is connected to.
877 */
878 for (priv->bank = 0; priv->bank < MAX_BANKS; priv->bank++) {
Prabhakar Kushwaha895d0392013-04-04 18:44:06 +0000879 phys_addr_t phys_addr = virt_to_phys(addr);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530880
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530881 cspr = ifc_in32(&ifc_ctrl->regs->cspr_cs[priv->bank].cspr);
882 csor = ifc_in32(&ifc_ctrl->regs->csor_cs[priv->bank].csor);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530883
884 if ((cspr & CSPR_V) && (cspr & CSPR_MSEL) == CSPR_MSEL_NAND &&
Prabhakar Kushwaha895d0392013-04-04 18:44:06 +0000885 (cspr & CSPR_BA) == CSPR_PHYS_ADDR(phys_addr)) {
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530886 ifc_ctrl->cs_nand = priv->bank << IFC_NAND_CSEL_SHIFT;
887 break;
888 }
889 }
890
891 if (priv->bank >= MAX_BANKS) {
892 printf("%s: address did not match any "
893 "chip selects\n", __func__);
Prabhakar Kushwahaae25e882012-04-10 22:48:27 +0000894 kfree(priv);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530895 return -ENODEV;
896 }
897
Prabhakar Kushwaha895d0392013-04-04 18:44:06 +0000898 nand = &priv->chip;
899 mtd->priv = nand;
900
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530901 ifc_ctrl->chips[priv->bank] = priv;
902
903 /* fill in nand_chip structure */
904 /* set up function call table */
905
906 nand->write_buf = fsl_ifc_write_buf;
907 nand->read_buf = fsl_ifc_read_buf;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530908 nand->select_chip = fsl_ifc_select_chip;
909 nand->cmdfunc = fsl_ifc_cmdfunc;
910 nand->waitfunc = fsl_ifc_wait;
911
912 /* set up nand options */
913 nand->bbt_td = &bbt_main_descr;
914 nand->bbt_md = &bbt_mirror_descr;
915
916 /* set up nand options */
Sergey Lapin3a38a552013-01-14 03:46:50 +0000917 nand->options = NAND_NO_SUBPAGE_WRITE;
918 nand->bbt_options = NAND_BBT_USE_FLASH;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530919
920 if (cspr & CSPR_PORT_SIZE_16) {
921 nand->read_byte = fsl_ifc_read_byte16;
922 nand->options |= NAND_BUSWIDTH_16;
923 } else {
924 nand->read_byte = fsl_ifc_read_byte;
925 }
926
927 nand->controller = &ifc_ctrl->controller;
928 nand->priv = priv;
929
930 nand->ecc.read_page = fsl_ifc_read_page;
931 nand->ecc.write_page = fsl_ifc_write_page;
932
933 /* Hardware generates ECC per 512 Bytes */
934 nand->ecc.size = 512;
935 nand->ecc.bytes = 8;
936
937 switch (csor & CSOR_NAND_PGS_MASK) {
938 case CSOR_NAND_PGS_512:
939 if (nand->options & NAND_BUSWIDTH_16) {
940 layout = &oob_512_16bit_ecc4;
941 } else {
942 layout = &oob_512_8bit_ecc4;
943
944 /* Avoid conflict with bad block marker */
945 bbt_main_descr.offs = 0;
946 bbt_mirror_descr.offs = 0;
947 }
948
Sergey Lapin3a38a552013-01-14 03:46:50 +0000949 nand->ecc.strength = 4;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530950 priv->bufnum_mask = 15;
951 break;
952
953 case CSOR_NAND_PGS_2K:
954 layout = &oob_2048_ecc4;
Sergey Lapin3a38a552013-01-14 03:46:50 +0000955 nand->ecc.strength = 4;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530956 priv->bufnum_mask = 3;
957 break;
958
959 case CSOR_NAND_PGS_4K:
960 if ((csor & CSOR_NAND_ECC_MODE_MASK) ==
961 CSOR_NAND_ECC_MODE_4) {
962 layout = &oob_4096_ecc4;
Sergey Lapin3a38a552013-01-14 03:46:50 +0000963 nand->ecc.strength = 4;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530964 } else {
965 layout = &oob_4096_ecc8;
Sergey Lapin3a38a552013-01-14 03:46:50 +0000966 nand->ecc.strength = 8;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530967 nand->ecc.bytes = 16;
968 }
969
970 priv->bufnum_mask = 1;
971 break;
972
Prabhakar Kushwahaa3aaf1d2013-10-04 10:05:36 +0530973 case CSOR_NAND_PGS_8K:
974 if ((csor & CSOR_NAND_ECC_MODE_MASK) ==
975 CSOR_NAND_ECC_MODE_4) {
976 layout = &oob_8192_ecc4;
977 nand->ecc.strength = 4;
978 } else {
979 layout = &oob_8192_ecc8;
980 nand->ecc.strength = 8;
981 nand->ecc.bytes = 16;
982 }
983
984 priv->bufnum_mask = 0;
985 break;
986
987
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530988 default:
989 printf("ifc nand: bad csor %#x: bad page size\n", csor);
990 return -ENODEV;
991 }
992
993 /* Must also set CSOR_NAND_ECC_ENC_EN if DEC_EN set */
994 if (csor & CSOR_NAND_ECC_DEC_EN) {
995 nand->ecc.mode = NAND_ECC_HW;
996 nand->ecc.layout = layout;
997 } else {
998 nand->ecc.mode = NAND_ECC_SOFT;
999 }
1000
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +05301001 ver = ifc_in32(&ifc_ctrl->regs->ifc_rev);
Prabhakar Kushwaha82efc812014-06-12 12:14:00 +05301002 if (ver >= FSL_IFC_V1_1_0)
1003 ret = fsl_ifc_sram_init(ver);
1004 if (ret)
1005 return ret;
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +00001006
Prabhakar Kushwaha5c23a822014-06-14 08:48:19 +05301007 if (ver >= FSL_IFC_V2_0_0)
1008 priv->bufnum_mask = (priv->bufnum_mask * 2) + 1;
1009
Prabhakar Kushwaha895d0392013-04-04 18:44:06 +00001010 ret = nand_scan_ident(mtd, 1, NULL);
1011 if (ret)
1012 return ret;
1013
1014 ret = nand_scan_tail(mtd);
1015 if (ret)
1016 return ret;
1017
1018 ret = nand_register(devnum);
1019 if (ret)
1020 return ret;
Dipen Dudhat9eae0832011-03-22 09:27:39 +05301021 return 0;
1022}
Prabhakar Kushwaha895d0392013-04-04 18:44:06 +00001023
1024#ifndef CONFIG_SYS_NAND_BASE_LIST
1025#define CONFIG_SYS_NAND_BASE_LIST { CONFIG_SYS_NAND_BASE }
1026#endif
1027
1028static unsigned long base_address[CONFIG_SYS_MAX_NAND_DEVICE] =
1029 CONFIG_SYS_NAND_BASE_LIST;
1030
1031void board_nand_init(void)
1032{
1033 int i;
1034
1035 for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++)
1036 fsl_ifc_chip_init(i, (u8 *)base_address[i]);
1037}