blob: 79fa88b22f975082bf6edd09cedfec71f4c8ca38 [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 */
Jaiprakash Singhdd888062015-03-20 19:28:27 -070049 struct fsl_ifc regs;
Dipen Dudhat9eae0832011-03-22 09:27:39 +053050 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;
Jaiprakash Singhdd888062015-03-20 19:28:27 -0700228 struct fsl_ifc_runtime *ifc = ctrl->regs.rregs;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530229 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;
Jaiprakash Singhdd888062015-03-20 19:28:27 -0700292 struct fsl_ifc_runtime *ifc = ctrl->regs.rregs;
Prabhakar Kushwahad7550e12014-09-23 09:57:47 +0530293 u32 timeo = (CONFIG_SYS_HZ * 10) / 1000;
294 u32 time_start;
Scott Wood70365492015-03-19 09:20:49 -0700295 u32 eccstat[8] = {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
Scott Wood70365492015-03-19 09:20:49 -0700328 for (i = sector / 4; i <= sector_end / 4; i++) {
329 if (i >= ARRAY_SIZE(eccstat)) {
330 printf("%s: eccstat too small for %d\n",
331 __func__, i);
332 return -EIO;
333 }
334
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530335 eccstat[i] = ifc_in32(&ifc->ifc_nand.nand_eccstat[i]);
Scott Wood70365492015-03-19 09:20:49 -0700336 }
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530337
Prabhakar Kushwahacdd045d2012-01-20 18:38:14 +0530338 for (i = sector; i <= sector_end; i++) {
339 errors = check_read_ecc(mtd, ctrl, eccstat, i);
340
341 if (errors == 15) {
342 /*
343 * Uncorrectable error.
344 * OK only if the whole page is blank.
345 *
346 * We disable ECCER reporting due to erratum
347 * IFC-A002770 -- so report it now if we
348 * see an uncorrectable error in ECCSTAT.
349 */
350 if (!is_blank(mtd, ctrl, bufnum))
351 ctrl->status |=
352 IFC_NAND_EVTER_STAT_ECCER;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530353 break;
Prabhakar Kushwahacdd045d2012-01-20 18:38:14 +0530354 }
355
356 mtd->ecc_stats.corrected += errors;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530357 }
358
359 ctrl->eccread = 0;
360 }
361
362 /* returns 0 on success otherwise non-zero) */
363 return ctrl->status == IFC_NAND_EVTER_STAT_OPC ? 0 : -EIO;
364}
365
366static void fsl_ifc_do_read(struct nand_chip *chip,
367 int oob,
368 struct mtd_info *mtd)
369{
370 struct fsl_ifc_mtd *priv = chip->priv;
371 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
Jaiprakash Singhdd888062015-03-20 19:28:27 -0700372 struct fsl_ifc_runtime *ifc = ctrl->regs.rregs;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530373
374 /* Program FIR/IFC_NAND_FCR0 for Small/Large page */
375 if (mtd->writesize > 512) {
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530376 ifc_out32(&ifc->ifc_nand.nand_fir0,
377 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
378 (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP1_SHIFT) |
379 (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP2_SHIFT) |
380 (IFC_FIR_OP_CMD1 << IFC_NAND_FIR0_OP3_SHIFT) |
381 (IFC_FIR_OP_RBCD << IFC_NAND_FIR0_OP4_SHIFT));
382 ifc_out32(&ifc->ifc_nand.nand_fir1, 0x0);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530383
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530384 ifc_out32(&ifc->ifc_nand.nand_fcr0,
385 (NAND_CMD_READ0 << IFC_NAND_FCR0_CMD0_SHIFT) |
386 (NAND_CMD_READSTART << IFC_NAND_FCR0_CMD1_SHIFT));
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530387 } else {
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530388 ifc_out32(&ifc->ifc_nand.nand_fir0,
389 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
390 (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP1_SHIFT) |
391 (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP2_SHIFT) |
392 (IFC_FIR_OP_RBCD << IFC_NAND_FIR0_OP3_SHIFT));
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530393
394 if (oob)
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530395 ifc_out32(&ifc->ifc_nand.nand_fcr0,
396 NAND_CMD_READOOB << IFC_NAND_FCR0_CMD0_SHIFT);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530397 else
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530398 ifc_out32(&ifc->ifc_nand.nand_fcr0,
399 NAND_CMD_READ0 << IFC_NAND_FCR0_CMD0_SHIFT);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530400 }
401}
402
403/* cmdfunc send commands to the IFC NAND Machine */
404static void fsl_ifc_cmdfunc(struct mtd_info *mtd, unsigned int command,
405 int column, int page_addr)
406{
407 struct nand_chip *chip = mtd->priv;
408 struct fsl_ifc_mtd *priv = chip->priv;
409 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
Jaiprakash Singhdd888062015-03-20 19:28:27 -0700410 struct fsl_ifc_runtime *ifc = ctrl->regs.rregs;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530411
412 /* clear the read buffer */
413 ctrl->read_bytes = 0;
414 if (command != NAND_CMD_PAGEPROG)
415 ctrl->index = 0;
416
417 switch (command) {
418 /* READ0 read the entire buffer to use hardware ECC. */
419 case NAND_CMD_READ0: {
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530420 ifc_out32(&ifc->ifc_nand.nand_fbcr, 0);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530421 set_addr(mtd, 0, page_addr, 0);
422
423 ctrl->read_bytes = mtd->writesize + mtd->oobsize;
424 ctrl->index += column;
425
426 if (chip->ecc.mode == NAND_ECC_HW)
427 ctrl->eccread = 1;
428
429 fsl_ifc_do_read(chip, 0, mtd);
430 fsl_ifc_run_command(mtd);
431 return;
432 }
433
434 /* READOOB reads only the OOB because no ECC is performed. */
435 case NAND_CMD_READOOB:
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530436 ifc_out32(&ifc->ifc_nand.nand_fbcr, mtd->oobsize - column);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530437 set_addr(mtd, column, page_addr, 1);
438
439 ctrl->read_bytes = mtd->writesize + mtd->oobsize;
440
441 fsl_ifc_do_read(chip, 1, mtd);
442 fsl_ifc_run_command(mtd);
443
444 return;
445
446 /* READID must read all possible bytes while CEB is active */
447 case NAND_CMD_READID:
Prabhakar Kushwahaf31cf532012-04-08 18:57:18 +0000448 case NAND_CMD_PARAM: {
449 int timing = IFC_FIR_OP_RB;
450 if (command == NAND_CMD_PARAM)
451 timing = IFC_FIR_OP_RBCD;
452
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530453 ifc_out32(&ifc->ifc_nand.nand_fir0,
454 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
455 (IFC_FIR_OP_UA << IFC_NAND_FIR0_OP1_SHIFT) |
456 (timing << IFC_NAND_FIR0_OP2_SHIFT));
457 ifc_out32(&ifc->ifc_nand.nand_fcr0,
458 command << IFC_NAND_FCR0_CMD0_SHIFT);
459 ifc_out32(&ifc->ifc_nand.row3, column);
Prabhakar Kushwahaf31cf532012-04-08 18:57:18 +0000460
461 /*
462 * although currently it's 8 bytes for READID, we always read
463 * the maximum 256 bytes(for PARAM)
464 */
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530465 ifc_out32(&ifc->ifc_nand.nand_fbcr, 256);
Prabhakar Kushwahaf31cf532012-04-08 18:57:18 +0000466 ctrl->read_bytes = 256;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530467
468 set_addr(mtd, 0, 0, 0);
469 fsl_ifc_run_command(mtd);
470 return;
Prabhakar Kushwahaf31cf532012-04-08 18:57:18 +0000471 }
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530472
473 /* ERASE1 stores the block and page address */
474 case NAND_CMD_ERASE1:
475 set_addr(mtd, 0, page_addr, 0);
476 return;
477
478 /* ERASE2 uses the block and page address from ERASE1 */
479 case NAND_CMD_ERASE2:
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530480 ifc_out32(&ifc->ifc_nand.nand_fir0,
481 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
482 (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP1_SHIFT) |
483 (IFC_FIR_OP_CMD1 << IFC_NAND_FIR0_OP2_SHIFT));
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530484
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530485 ifc_out32(&ifc->ifc_nand.nand_fcr0,
486 (NAND_CMD_ERASE1 << IFC_NAND_FCR0_CMD0_SHIFT) |
487 (NAND_CMD_ERASE2 << IFC_NAND_FCR0_CMD1_SHIFT));
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530488
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530489 ifc_out32(&ifc->ifc_nand.nand_fbcr, 0);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530490 ctrl->read_bytes = 0;
491 fsl_ifc_run_command(mtd);
492 return;
493
494 /* SEQIN sets up the addr buffer and all registers except the length */
495 case NAND_CMD_SEQIN: {
496 u32 nand_fcr0;
497 ctrl->column = column;
498 ctrl->oob = 0;
499
500 if (mtd->writesize > 512) {
501 nand_fcr0 =
502 (NAND_CMD_SEQIN << IFC_NAND_FCR0_CMD0_SHIFT) |
Prabhakar Kushwaha18e6bde2013-10-03 11:35:35 +0530503 (NAND_CMD_STATUS << IFC_NAND_FCR0_CMD1_SHIFT) |
504 (NAND_CMD_PAGEPROG << IFC_NAND_FCR0_CMD2_SHIFT);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530505
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530506 ifc_out32(&ifc->ifc_nand.nand_fir0,
507 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
508 (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP1_SHIFT) |
509 (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP2_SHIFT) |
510 (IFC_FIR_OP_WBCD <<
511 IFC_NAND_FIR0_OP3_SHIFT) |
512 (IFC_FIR_OP_CMD2 << IFC_NAND_FIR0_OP4_SHIFT));
513 ifc_out32(&ifc->ifc_nand.nand_fir1,
514 (IFC_FIR_OP_CW1 << IFC_NAND_FIR1_OP5_SHIFT) |
515 (IFC_FIR_OP_RDSTAT <<
Prabhakar Kushwaha18e6bde2013-10-03 11:35:35 +0530516 IFC_NAND_FIR1_OP6_SHIFT) |
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530517 (IFC_FIR_OP_NOP << IFC_NAND_FIR1_OP7_SHIFT));
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530518 } else {
519 nand_fcr0 = ((NAND_CMD_PAGEPROG <<
520 IFC_NAND_FCR0_CMD1_SHIFT) |
521 (NAND_CMD_SEQIN <<
Prabhakar Kushwaha18e6bde2013-10-03 11:35:35 +0530522 IFC_NAND_FCR0_CMD2_SHIFT) |
523 (NAND_CMD_STATUS <<
524 IFC_NAND_FCR0_CMD3_SHIFT));
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530525
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530526 ifc_out32(&ifc->ifc_nand.nand_fir0,
527 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
528 (IFC_FIR_OP_CMD2 << IFC_NAND_FIR0_OP1_SHIFT) |
529 (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP2_SHIFT) |
530 (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP3_SHIFT) |
531 (IFC_FIR_OP_WBCD << IFC_NAND_FIR0_OP4_SHIFT));
532 ifc_out32(&ifc->ifc_nand.nand_fir1,
533 (IFC_FIR_OP_CMD1 << IFC_NAND_FIR1_OP5_SHIFT) |
534 (IFC_FIR_OP_CW3 << IFC_NAND_FIR1_OP6_SHIFT) |
535 (IFC_FIR_OP_RDSTAT <<
Prabhakar Kushwaha18e6bde2013-10-03 11:35:35 +0530536 IFC_NAND_FIR1_OP7_SHIFT) |
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530537 (IFC_FIR_OP_NOP << IFC_NAND_FIR1_OP8_SHIFT));
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530538
Prabhakar Kushwaha0ed5e772012-01-20 18:39:05 +0530539 if (column >= mtd->writesize)
540 nand_fcr0 |=
541 NAND_CMD_READOOB << IFC_NAND_FCR0_CMD0_SHIFT;
542 else
543 nand_fcr0 |=
544 NAND_CMD_READ0 << IFC_NAND_FCR0_CMD0_SHIFT;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530545 }
546
Prabhakar Kushwaha0ed5e772012-01-20 18:39:05 +0530547 if (column >= mtd->writesize) {
548 /* OOB area --> READOOB */
549 column -= mtd->writesize;
550 ctrl->oob = 1;
551 }
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530552 ifc_out32(&ifc->ifc_nand.nand_fcr0, nand_fcr0);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530553 set_addr(mtd, column, page_addr, ctrl->oob);
554 return;
555 }
556
557 /* PAGEPROG reuses all of the setup from SEQIN and adds the length */
558 case NAND_CMD_PAGEPROG:
559 if (ctrl->oob)
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530560 ifc_out32(&ifc->ifc_nand.nand_fbcr,
561 ctrl->index - ctrl->column);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530562 else
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530563 ifc_out32(&ifc->ifc_nand.nand_fbcr, 0);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530564
565 fsl_ifc_run_command(mtd);
566 return;
567
568 case NAND_CMD_STATUS:
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530569 ifc_out32(&ifc->ifc_nand.nand_fir0,
570 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
571 (IFC_FIR_OP_RB << IFC_NAND_FIR0_OP1_SHIFT));
572 ifc_out32(&ifc->ifc_nand.nand_fcr0,
573 NAND_CMD_STATUS << IFC_NAND_FCR0_CMD0_SHIFT);
574 ifc_out32(&ifc->ifc_nand.nand_fbcr, 1);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530575 set_addr(mtd, 0, 0, 0);
576 ctrl->read_bytes = 1;
577
578 fsl_ifc_run_command(mtd);
579
580 /* Chip sometimes reporting write protect even when it's not */
581 out_8(ctrl->addr, in_8(ctrl->addr) | NAND_STATUS_WP);
582 return;
583
584 case NAND_CMD_RESET:
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530585 ifc_out32(&ifc->ifc_nand.nand_fir0,
586 IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT);
587 ifc_out32(&ifc->ifc_nand.nand_fcr0,
588 NAND_CMD_RESET << IFC_NAND_FCR0_CMD0_SHIFT);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530589 fsl_ifc_run_command(mtd);
590 return;
591
592 default:
593 printf("%s: error, unsupported command 0x%x.\n",
594 __func__, command);
595 }
596}
597
598/*
599 * Write buf to the IFC NAND Controller Data Buffer
600 */
601static void fsl_ifc_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
602{
603 struct nand_chip *chip = mtd->priv;
604 struct fsl_ifc_mtd *priv = chip->priv;
605 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
606 unsigned int bufsize = mtd->writesize + mtd->oobsize;
607
608 if (len <= 0) {
609 printf("%s of %d bytes", __func__, len);
610 ctrl->status = 0;
611 return;
612 }
613
614 if ((unsigned int)len > bufsize - ctrl->index) {
615 printf("%s beyond end of buffer "
616 "(%d requested, %u available)\n",
617 __func__, len, bufsize - ctrl->index);
618 len = bufsize - ctrl->index;
619 }
620
621 memcpy_toio(&ctrl->addr[ctrl->index], buf, len);
622 ctrl->index += len;
623}
624
625/*
626 * read a byte from either the IFC hardware buffer if it has any data left
627 * otherwise issue a command to read a single byte.
628 */
629static u8 fsl_ifc_read_byte(struct mtd_info *mtd)
630{
631 struct nand_chip *chip = mtd->priv;
632 struct fsl_ifc_mtd *priv = chip->priv;
633 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
634
635 /* If there are still bytes in the IFC buffer, then use the
636 * next byte. */
637 if (ctrl->index < ctrl->read_bytes)
638 return in_8(&ctrl->addr[ctrl->index++]);
639
640 printf("%s beyond end of buffer\n", __func__);
641 return ERR_BYTE;
642}
643
644/*
645 * Read two bytes from the IFC hardware buffer
646 * read function for 16-bit buswith
647 */
648static uint8_t fsl_ifc_read_byte16(struct mtd_info *mtd)
649{
650 struct nand_chip *chip = mtd->priv;
651 struct fsl_ifc_mtd *priv = chip->priv;
652 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
653 uint16_t data;
654
655 /*
656 * If there are still bytes in the IFC buffer, then use the
657 * next byte.
658 */
659 if (ctrl->index < ctrl->read_bytes) {
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530660 data = ifc_in16((uint16_t *)&ctrl->
661 addr[ctrl->index]);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530662 ctrl->index += 2;
663 return (uint8_t)data;
664 }
665
666 printf("%s beyond end of buffer\n", __func__);
667 return ERR_BYTE;
668}
669
670/*
671 * Read from the IFC Controller Data Buffer
672 */
673static void fsl_ifc_read_buf(struct mtd_info *mtd, u8 *buf, int len)
674{
675 struct nand_chip *chip = mtd->priv;
676 struct fsl_ifc_mtd *priv = chip->priv;
677 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
678 int avail;
679
680 if (len < 0)
681 return;
682
683 avail = min((unsigned int)len, ctrl->read_bytes - ctrl->index);
684 memcpy_fromio(buf, &ctrl->addr[ctrl->index], avail);
685 ctrl->index += avail;
686
687 if (len > avail)
688 printf("%s beyond end of buffer "
689 "(%d requested, %d available)\n",
690 __func__, len, avail);
691}
692
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530693/* This function is called after Program and Erase Operations to
694 * check for success or failure.
695 */
696static int fsl_ifc_wait(struct mtd_info *mtd, struct nand_chip *chip)
697{
698 struct fsl_ifc_mtd *priv = chip->priv;
699 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
Jaiprakash Singhdd888062015-03-20 19:28:27 -0700700 struct fsl_ifc_runtime *ifc = ctrl->regs.rregs;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530701 u32 nand_fsr;
702
703 if (ctrl->status != IFC_NAND_EVTER_STAT_OPC)
704 return NAND_STATUS_FAIL;
705
706 /* Use READ_STATUS command, but wait for the device to be ready */
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530707 ifc_out32(&ifc->ifc_nand.nand_fir0,
708 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
709 (IFC_FIR_OP_RDSTAT << IFC_NAND_FIR0_OP1_SHIFT));
710 ifc_out32(&ifc->ifc_nand.nand_fcr0, NAND_CMD_STATUS <<
711 IFC_NAND_FCR0_CMD0_SHIFT);
712 ifc_out32(&ifc->ifc_nand.nand_fbcr, 1);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530713 set_addr(mtd, 0, 0, 0);
714 ctrl->read_bytes = 1;
715
716 fsl_ifc_run_command(mtd);
717
718 if (ctrl->status != IFC_NAND_EVTER_STAT_OPC)
719 return NAND_STATUS_FAIL;
720
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530721 nand_fsr = ifc_in32(&ifc->ifc_nand.nand_fsr);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530722
723 /* Chip sometimes reporting write protect even when it's not */
724 nand_fsr = nand_fsr | NAND_STATUS_WP;
725 return nand_fsr;
726}
727
Sergey Lapin3a38a552013-01-14 03:46:50 +0000728static int fsl_ifc_read_page(struct mtd_info *mtd, struct nand_chip *chip,
729 uint8_t *buf, int oob_required, int page)
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530730{
731 struct fsl_ifc_mtd *priv = chip->priv;
732 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
733
734 fsl_ifc_read_buf(mtd, buf, mtd->writesize);
735 fsl_ifc_read_buf(mtd, chip->oob_poi, mtd->oobsize);
736
737 if (ctrl->status != IFC_NAND_EVTER_STAT_OPC)
738 mtd->ecc_stats.failed++;
739
740 return 0;
741}
742
743/* ECC will be calculated automatically, and errors will be detected in
744 * waitfunc.
745 */
Sergey Lapin3a38a552013-01-14 03:46:50 +0000746static int fsl_ifc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
747 const uint8_t *buf, int oob_required)
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530748{
749 fsl_ifc_write_buf(mtd, buf, mtd->writesize);
750 fsl_ifc_write_buf(mtd, chip->oob_poi, mtd->oobsize);
Sergey Lapin3a38a552013-01-14 03:46:50 +0000751
752 return 0;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530753}
754
755static void fsl_ifc_ctrl_init(void)
756{
Jaiprakash Singhdd888062015-03-20 19:28:27 -0700757 uint32_t ver = 0;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530758 ifc_ctrl = kzalloc(sizeof(*ifc_ctrl), GFP_KERNEL);
759 if (!ifc_ctrl)
760 return;
761
Jaiprakash Singhdd888062015-03-20 19:28:27 -0700762 ifc_ctrl->regs.gregs = IFC_FCM_BASE_ADDR;
763
764 ver = ifc_in32(&ifc_ctrl->regs.gregs->ifc_rev);
765 if (ver >= FSL_IFC_V2_0_0)
766 ifc_ctrl->regs.rregs =
767 (void *)CONFIG_SYS_IFC_ADDR + IFC_RREGS_64KOFFSET;
768 else
769 ifc_ctrl->regs.rregs =
770 (void *)CONFIG_SYS_IFC_ADDR + IFC_RREGS_4KOFFSET;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530771
772 /* clear event registers */
Jaiprakash Singhdd888062015-03-20 19:28:27 -0700773 ifc_out32(&ifc_ctrl->regs.rregs->ifc_nand.nand_evter_stat, ~0U);
774 ifc_out32(&ifc_ctrl->regs.rregs->ifc_nand.pgrdcmpl_evt_stat, ~0U);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530775
776 /* Enable error and event for any detected errors */
Jaiprakash Singhdd888062015-03-20 19:28:27 -0700777 ifc_out32(&ifc_ctrl->regs.rregs->ifc_nand.nand_evter_en,
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530778 IFC_NAND_EVTER_EN_OPC_EN |
779 IFC_NAND_EVTER_EN_PGRDCMPL_EN |
780 IFC_NAND_EVTER_EN_FTOER_EN |
781 IFC_NAND_EVTER_EN_WPER_EN);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530782
Jaiprakash Singhdd888062015-03-20 19:28:27 -0700783 ifc_out32(&ifc_ctrl->regs.rregs->ifc_nand.ncfgr, 0x0);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530784}
785
786static void fsl_ifc_select_chip(struct mtd_info *mtd, int chip)
787{
788}
789
Prabhakar Kushwaha82efc812014-06-12 12:14:00 +0530790static int fsl_ifc_sram_init(uint32_t ver)
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000791{
Jaiprakash Singhdd888062015-03-20 19:28:27 -0700792 struct fsl_ifc_runtime *ifc = ifc_ctrl->regs.rregs;
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000793 uint32_t cs = 0, csor = 0, csor_8k = 0, csor_ext = 0;
Prabhakar Kushwaha82efc812014-06-12 12:14:00 +0530794 uint32_t ncfgr = 0;
Prabhakar Kushwahad7550e12014-09-23 09:57:47 +0530795 u32 timeo = (CONFIG_SYS_HZ * 10) / 1000;
796 u32 time_start;
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000797
Prabhakar Kushwaha82efc812014-06-12 12:14:00 +0530798 if (ver > FSL_IFC_V1_1_0) {
799 ncfgr = ifc_in32(&ifc->ifc_nand.ncfgr);
800 ifc_out32(&ifc->ifc_nand.ncfgr, ncfgr | IFC_NAND_SRAM_INIT_EN);
801
802 /* wait for SRAM_INIT bit to be clear or timeout */
Prabhakar Kushwahad7550e12014-09-23 09:57:47 +0530803 time_start = get_timer(0);
804 while (get_timer(time_start) < timeo) {
Prabhakar Kushwaha82efc812014-06-12 12:14:00 +0530805 ifc_ctrl->status =
806 ifc_in32(&ifc->ifc_nand.nand_evter_stat);
807
808 if (!(ifc_ctrl->status & IFC_NAND_SRAM_INIT_EN))
809 return 0;
810 }
811 printf("fsl-ifc: Failed to Initialise SRAM\n");
812 return 1;
813 }
814
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000815 cs = ifc_ctrl->cs_nand >> IFC_NAND_CSEL_SHIFT;
816
817 /* Save CSOR and CSOR_ext */
Jaiprakash Singhdd888062015-03-20 19:28:27 -0700818 csor = ifc_in32(&ifc_ctrl->regs.gregs->csor_cs[cs].csor);
819 csor_ext = ifc_in32(&ifc_ctrl->regs.gregs->csor_cs[cs].csor_ext);
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000820
821 /* chage PageSize 8K and SpareSize 1K*/
822 csor_8k = (csor & ~(CSOR_NAND_PGS_MASK)) | 0x0018C000;
Jaiprakash Singhdd888062015-03-20 19:28:27 -0700823 ifc_out32(&ifc_ctrl->regs.gregs->csor_cs[cs].csor, csor_8k);
824 ifc_out32(&ifc_ctrl->regs.gregs->csor_cs[cs].csor_ext, 0x0000400);
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000825
826 /* READID */
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530827 ifc_out32(&ifc->ifc_nand.nand_fir0,
828 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
829 (IFC_FIR_OP_UA << IFC_NAND_FIR0_OP1_SHIFT) |
830 (IFC_FIR_OP_RB << IFC_NAND_FIR0_OP2_SHIFT));
831 ifc_out32(&ifc->ifc_nand.nand_fcr0,
832 NAND_CMD_READID << IFC_NAND_FCR0_CMD0_SHIFT);
833 ifc_out32(&ifc->ifc_nand.row3, 0x0);
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000834
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530835 ifc_out32(&ifc->ifc_nand.nand_fbcr, 0x0);
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000836
837 /* Program ROW0/COL0 */
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530838 ifc_out32(&ifc->ifc_nand.row0, 0x0);
839 ifc_out32(&ifc->ifc_nand.col0, 0x0);
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000840
841 /* set the chip select for NAND Transaction */
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530842 ifc_out32(&ifc->ifc_nand.nand_csel, ifc_ctrl->cs_nand);
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000843
844 /* start read seq */
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530845 ifc_out32(&ifc->ifc_nand.nandseq_strt, IFC_NAND_SEQ_STRT_FIR_STRT);
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000846
Prabhakar Kushwahad7550e12014-09-23 09:57:47 +0530847 time_start = get_timer(0);
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000848
Prabhakar Kushwahad7550e12014-09-23 09:57:47 +0530849 while (get_timer(time_start) < timeo) {
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530850 ifc_ctrl->status = ifc_in32(&ifc->ifc_nand.nand_evter_stat);
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000851
852 if (ifc_ctrl->status & IFC_NAND_EVTER_STAT_OPC)
853 break;
854 }
855
Prabhakar Kushwaha82efc812014-06-12 12:14:00 +0530856 if (ifc_ctrl->status != IFC_NAND_EVTER_STAT_OPC) {
857 printf("fsl-ifc: Failed to Initialise SRAM\n");
858 return 1;
859 }
860
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530861 ifc_out32(&ifc->ifc_nand.nand_evter_stat, ifc_ctrl->status);
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000862
863 /* Restore CSOR and CSOR_ext */
Jaiprakash Singhdd888062015-03-20 19:28:27 -0700864 ifc_out32(&ifc_ctrl->regs.gregs->csor_cs[cs].csor, csor);
865 ifc_out32(&ifc_ctrl->regs.gregs->csor_cs[cs].csor_ext, csor_ext);
Prabhakar Kushwaha82efc812014-06-12 12:14:00 +0530866
867 return 0;
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000868}
869
Prabhakar Kushwaha895d0392013-04-04 18:44:06 +0000870static int fsl_ifc_chip_init(int devnum, u8 *addr)
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530871{
Prabhakar Kushwaha895d0392013-04-04 18:44:06 +0000872 struct mtd_info *mtd = &nand_info[devnum];
873 struct nand_chip *nand;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530874 struct fsl_ifc_mtd *priv;
875 struct nand_ecclayout *layout;
Jaiprakash Singhdd888062015-03-20 19:28:27 -0700876 struct fsl_ifc_fcm *gregs = NULL;
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000877 uint32_t cspr = 0, csor = 0, ver = 0;
Prabhakar Kushwaha82efc812014-06-12 12:14:00 +0530878 int ret = 0;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530879
880 if (!ifc_ctrl) {
881 fsl_ifc_ctrl_init();
882 if (!ifc_ctrl)
883 return -1;
884 }
885
886 priv = kzalloc(sizeof(*priv), GFP_KERNEL);
887 if (!priv)
888 return -ENOMEM;
889
890 priv->ctrl = ifc_ctrl;
Prabhakar Kushwaha895d0392013-04-04 18:44:06 +0000891 priv->vbase = addr;
Jaiprakash Singhdd888062015-03-20 19:28:27 -0700892 gregs = ifc_ctrl->regs.gregs;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530893
894 /* Find which chip select it is connected to.
895 */
896 for (priv->bank = 0; priv->bank < MAX_BANKS; priv->bank++) {
Prabhakar Kushwaha895d0392013-04-04 18:44:06 +0000897 phys_addr_t phys_addr = virt_to_phys(addr);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530898
Jaiprakash Singhdd888062015-03-20 19:28:27 -0700899 cspr = ifc_in32(&gregs->cspr_cs[priv->bank].cspr);
900 csor = ifc_in32(&gregs->csor_cs[priv->bank].csor);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530901
902 if ((cspr & CSPR_V) && (cspr & CSPR_MSEL) == CSPR_MSEL_NAND &&
Prabhakar Kushwaha895d0392013-04-04 18:44:06 +0000903 (cspr & CSPR_BA) == CSPR_PHYS_ADDR(phys_addr)) {
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530904 ifc_ctrl->cs_nand = priv->bank << IFC_NAND_CSEL_SHIFT;
905 break;
906 }
907 }
908
909 if (priv->bank >= MAX_BANKS) {
910 printf("%s: address did not match any "
911 "chip selects\n", __func__);
Prabhakar Kushwahaae25e882012-04-10 22:48:27 +0000912 kfree(priv);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530913 return -ENODEV;
914 }
915
Prabhakar Kushwaha895d0392013-04-04 18:44:06 +0000916 nand = &priv->chip;
917 mtd->priv = nand;
918
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530919 ifc_ctrl->chips[priv->bank] = priv;
920
921 /* fill in nand_chip structure */
922 /* set up function call table */
923
924 nand->write_buf = fsl_ifc_write_buf;
925 nand->read_buf = fsl_ifc_read_buf;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530926 nand->select_chip = fsl_ifc_select_chip;
927 nand->cmdfunc = fsl_ifc_cmdfunc;
928 nand->waitfunc = fsl_ifc_wait;
929
930 /* set up nand options */
931 nand->bbt_td = &bbt_main_descr;
932 nand->bbt_md = &bbt_mirror_descr;
933
934 /* set up nand options */
Sergey Lapin3a38a552013-01-14 03:46:50 +0000935 nand->options = NAND_NO_SUBPAGE_WRITE;
936 nand->bbt_options = NAND_BBT_USE_FLASH;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530937
938 if (cspr & CSPR_PORT_SIZE_16) {
939 nand->read_byte = fsl_ifc_read_byte16;
940 nand->options |= NAND_BUSWIDTH_16;
941 } else {
942 nand->read_byte = fsl_ifc_read_byte;
943 }
944
945 nand->controller = &ifc_ctrl->controller;
946 nand->priv = priv;
947
948 nand->ecc.read_page = fsl_ifc_read_page;
949 nand->ecc.write_page = fsl_ifc_write_page;
950
951 /* Hardware generates ECC per 512 Bytes */
952 nand->ecc.size = 512;
953 nand->ecc.bytes = 8;
954
955 switch (csor & CSOR_NAND_PGS_MASK) {
956 case CSOR_NAND_PGS_512:
957 if (nand->options & NAND_BUSWIDTH_16) {
958 layout = &oob_512_16bit_ecc4;
959 } else {
960 layout = &oob_512_8bit_ecc4;
961
962 /* Avoid conflict with bad block marker */
963 bbt_main_descr.offs = 0;
964 bbt_mirror_descr.offs = 0;
965 }
966
Sergey Lapin3a38a552013-01-14 03:46:50 +0000967 nand->ecc.strength = 4;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530968 priv->bufnum_mask = 15;
969 break;
970
971 case CSOR_NAND_PGS_2K:
972 layout = &oob_2048_ecc4;
Sergey Lapin3a38a552013-01-14 03:46:50 +0000973 nand->ecc.strength = 4;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530974 priv->bufnum_mask = 3;
975 break;
976
977 case CSOR_NAND_PGS_4K:
978 if ((csor & CSOR_NAND_ECC_MODE_MASK) ==
979 CSOR_NAND_ECC_MODE_4) {
980 layout = &oob_4096_ecc4;
Sergey Lapin3a38a552013-01-14 03:46:50 +0000981 nand->ecc.strength = 4;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530982 } else {
983 layout = &oob_4096_ecc8;
Sergey Lapin3a38a552013-01-14 03:46:50 +0000984 nand->ecc.strength = 8;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530985 nand->ecc.bytes = 16;
986 }
987
988 priv->bufnum_mask = 1;
989 break;
990
Prabhakar Kushwahaa3aaf1d2013-10-04 10:05:36 +0530991 case CSOR_NAND_PGS_8K:
992 if ((csor & CSOR_NAND_ECC_MODE_MASK) ==
993 CSOR_NAND_ECC_MODE_4) {
994 layout = &oob_8192_ecc4;
995 nand->ecc.strength = 4;
996 } else {
997 layout = &oob_8192_ecc8;
998 nand->ecc.strength = 8;
999 nand->ecc.bytes = 16;
1000 }
1001
1002 priv->bufnum_mask = 0;
1003 break;
1004
1005
Dipen Dudhat9eae0832011-03-22 09:27:39 +05301006 default:
1007 printf("ifc nand: bad csor %#x: bad page size\n", csor);
1008 return -ENODEV;
1009 }
1010
1011 /* Must also set CSOR_NAND_ECC_ENC_EN if DEC_EN set */
1012 if (csor & CSOR_NAND_ECC_DEC_EN) {
1013 nand->ecc.mode = NAND_ECC_HW;
1014 nand->ecc.layout = layout;
1015 } else {
1016 nand->ecc.mode = NAND_ECC_SOFT;
1017 }
1018
Jaiprakash Singhdd888062015-03-20 19:28:27 -07001019 ver = ifc_in32(&gregs->ifc_rev);
Prabhakar Kushwaha82efc812014-06-12 12:14:00 +05301020 if (ver >= FSL_IFC_V1_1_0)
1021 ret = fsl_ifc_sram_init(ver);
1022 if (ret)
1023 return ret;
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +00001024
Prabhakar Kushwaha5c23a822014-06-14 08:48:19 +05301025 if (ver >= FSL_IFC_V2_0_0)
1026 priv->bufnum_mask = (priv->bufnum_mask * 2) + 1;
1027
Prabhakar Kushwaha895d0392013-04-04 18:44:06 +00001028 ret = nand_scan_ident(mtd, 1, NULL);
1029 if (ret)
1030 return ret;
1031
1032 ret = nand_scan_tail(mtd);
1033 if (ret)
1034 return ret;
1035
1036 ret = nand_register(devnum);
1037 if (ret)
1038 return ret;
Dipen Dudhat9eae0832011-03-22 09:27:39 +05301039 return 0;
1040}
Prabhakar Kushwaha895d0392013-04-04 18:44:06 +00001041
1042#ifndef CONFIG_SYS_NAND_BASE_LIST
1043#define CONFIG_SYS_NAND_BASE_LIST { CONFIG_SYS_NAND_BASE }
1044#endif
1045
1046static unsigned long base_address[CONFIG_SYS_MAX_NAND_DEVICE] =
1047 CONFIG_SYS_NAND_BASE_LIST;
1048
1049void board_nand_init(void)
1050{
1051 int i;
1052
1053 for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++)
1054 fsl_ifc_chip_init(i, (u8 *)base_address[i]);
1055}