blob: a47226bd2158106bb4efaa2eac556faad82c60af [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Dipen Dudhat9eae0832011-03-22 09:27:39 +05302/* Integrated Flash Controller NAND Machine Driver
3 *
Prabhakar Kushwahacdd045d2012-01-20 18:38:14 +05304 * Copyright (c) 2012 Freescale Semiconductor, Inc
Dipen Dudhat9eae0832011-03-22 09:27:39 +05305 *
6 * Authors: Dipen Dudhat <Dipen.Dudhat@freescale.com>
Dipen Dudhat9eae0832011-03-22 09:27:39 +05307 */
8
9#include <common.h>
10#include <malloc.h>
Prabhakar Kushwaha895d0392013-04-04 18:44:06 +000011#include <nand.h>
Dipen Dudhat9eae0832011-03-22 09:27:39 +053012
13#include <linux/mtd/mtd.h>
Masahiro Yamada2b7a8732017-11-30 13:45:24 +090014#include <linux/mtd/rawnand.h>
Dipen Dudhat9eae0832011-03-22 09:27:39 +053015#include <linux/mtd/nand_ecc.h>
16
17#include <asm/io.h>
Masahiro Yamada56a931c2016-09-21 11:28:55 +090018#include <linux/errno.h>
York Sun37562f62013-10-22 12:39:02 -070019#include <fsl_ifc.h>
Dipen Dudhat9eae0832011-03-22 09:27:39 +053020
Prabhakar Kushwahaa8759642014-06-12 09:13:08 +053021#ifndef CONFIG_SYS_FSL_IFC_BANK_COUNT
22#define CONFIG_SYS_FSL_IFC_BANK_COUNT 4
23#endif
24
Prabhakar Kushwahaa8759642014-06-12 09:13:08 +053025#define MAX_BANKS CONFIG_SYS_FSL_IFC_BANK_COUNT
Dipen Dudhat9eae0832011-03-22 09:27:39 +053026#define ERR_BYTE 0xFF /* Value returned for read bytes
27 when read failed */
Dipen Dudhat9eae0832011-03-22 09:27:39 +053028
29struct fsl_ifc_ctrl;
30
31/* mtd information per set */
32struct fsl_ifc_mtd {
Dipen Dudhat9eae0832011-03-22 09:27:39 +053033 struct nand_chip chip;
34 struct fsl_ifc_ctrl *ctrl;
35
36 struct device *dev;
37 int bank; /* Chip select bank number */
38 unsigned int bufnum_mask; /* bufnum = page & bufnum_mask */
39 u8 __iomem *vbase; /* Chip select base virtual address */
40};
41
42/* overview of the fsl ifc controller */
43struct fsl_ifc_ctrl {
44 struct nand_hw_control controller;
45 struct fsl_ifc_mtd *chips[MAX_BANKS];
46
47 /* device info */
Jaiprakash Singhdd888062015-03-20 19:28:27 -070048 struct fsl_ifc regs;
Scott Wood3ea94ed2015-06-26 19:03:26 -050049 void __iomem *addr; /* Address of assigned IFC buffer */
Dipen Dudhat9eae0832011-03-22 09:27:39 +053050 unsigned int page; /* Last page written to / read from */
51 unsigned int read_bytes; /* Number of bytes read during command */
52 unsigned int column; /* Saved column from SEQIN */
53 unsigned int index; /* Pointer to next byte to 'read' */
54 unsigned int status; /* status read from NEESR after last op */
55 unsigned int oob; /* Non zero if operating on OOB data */
56 unsigned int eccread; /* Non zero for a full-page ECC read */
57};
58
59static struct fsl_ifc_ctrl *ifc_ctrl;
60
61/* 512-byte page with 4-bit ECC, 8-bit */
62static struct nand_ecclayout oob_512_8bit_ecc4 = {
63 .eccbytes = 8,
64 .eccpos = {8, 9, 10, 11, 12, 13, 14, 15},
65 .oobfree = { {0, 5}, {6, 2} },
66};
67
68/* 512-byte page with 4-bit ECC, 16-bit */
69static struct nand_ecclayout oob_512_16bit_ecc4 = {
70 .eccbytes = 8,
71 .eccpos = {8, 9, 10, 11, 12, 13, 14, 15},
72 .oobfree = { {2, 6}, },
73};
74
75/* 2048-byte page size with 4-bit ECC */
76static struct nand_ecclayout oob_2048_ecc4 = {
77 .eccbytes = 32,
78 .eccpos = {
79 8, 9, 10, 11, 12, 13, 14, 15,
80 16, 17, 18, 19, 20, 21, 22, 23,
81 24, 25, 26, 27, 28, 29, 30, 31,
82 32, 33, 34, 35, 36, 37, 38, 39,
83 },
84 .oobfree = { {2, 6}, {40, 24} },
85};
86
87/* 4096-byte page size with 4-bit ECC */
88static struct nand_ecclayout oob_4096_ecc4 = {
89 .eccbytes = 64,
90 .eccpos = {
91 8, 9, 10, 11, 12, 13, 14, 15,
92 16, 17, 18, 19, 20, 21, 22, 23,
93 24, 25, 26, 27, 28, 29, 30, 31,
94 32, 33, 34, 35, 36, 37, 38, 39,
95 40, 41, 42, 43, 44, 45, 46, 47,
96 48, 49, 50, 51, 52, 53, 54, 55,
97 56, 57, 58, 59, 60, 61, 62, 63,
98 64, 65, 66, 67, 68, 69, 70, 71,
99 },
100 .oobfree = { {2, 6}, {72, 56} },
101};
102
103/* 4096-byte page size with 8-bit ECC -- requires 218-byte OOB */
104static struct nand_ecclayout oob_4096_ecc8 = {
105 .eccbytes = 128,
106 .eccpos = {
107 8, 9, 10, 11, 12, 13, 14, 15,
108 16, 17, 18, 19, 20, 21, 22, 23,
109 24, 25, 26, 27, 28, 29, 30, 31,
110 32, 33, 34, 35, 36, 37, 38, 39,
111 40, 41, 42, 43, 44, 45, 46, 47,
112 48, 49, 50, 51, 52, 53, 54, 55,
113 56, 57, 58, 59, 60, 61, 62, 63,
114 64, 65, 66, 67, 68, 69, 70, 71,
115 72, 73, 74, 75, 76, 77, 78, 79,
116 80, 81, 82, 83, 84, 85, 86, 87,
117 88, 89, 90, 91, 92, 93, 94, 95,
118 96, 97, 98, 99, 100, 101, 102, 103,
119 104, 105, 106, 107, 108, 109, 110, 111,
120 112, 113, 114, 115, 116, 117, 118, 119,
121 120, 121, 122, 123, 124, 125, 126, 127,
122 128, 129, 130, 131, 132, 133, 134, 135,
123 },
124 .oobfree = { {2, 6}, {136, 82} },
125};
126
Prabhakar Kushwahaa3aaf1d2013-10-04 10:05:36 +0530127/* 8192-byte page size with 4-bit ECC */
128static struct nand_ecclayout oob_8192_ecc4 = {
129 .eccbytes = 128,
130 .eccpos = {
131 8, 9, 10, 11, 12, 13, 14, 15,
132 16, 17, 18, 19, 20, 21, 22, 23,
133 24, 25, 26, 27, 28, 29, 30, 31,
134 32, 33, 34, 35, 36, 37, 38, 39,
135 40, 41, 42, 43, 44, 45, 46, 47,
136 48, 49, 50, 51, 52, 53, 54, 55,
137 56, 57, 58, 59, 60, 61, 62, 63,
138 64, 65, 66, 67, 68, 69, 70, 71,
139 72, 73, 74, 75, 76, 77, 78, 79,
140 80, 81, 82, 83, 84, 85, 86, 87,
141 88, 89, 90, 91, 92, 93, 94, 95,
142 96, 97, 98, 99, 100, 101, 102, 103,
143 104, 105, 106, 107, 108, 109, 110, 111,
144 112, 113, 114, 115, 116, 117, 118, 119,
145 120, 121, 122, 123, 124, 125, 126, 127,
146 128, 129, 130, 131, 132, 133, 134, 135,
147 },
148 .oobfree = { {2, 6}, {136, 208} },
149};
150
151/* 8192-byte page size with 8-bit ECC -- requires 218-byte OOB */
152static struct nand_ecclayout oob_8192_ecc8 = {
153 .eccbytes = 256,
154 .eccpos = {
155 8, 9, 10, 11, 12, 13, 14, 15,
156 16, 17, 18, 19, 20, 21, 22, 23,
157 24, 25, 26, 27, 28, 29, 30, 31,
158 32, 33, 34, 35, 36, 37, 38, 39,
159 40, 41, 42, 43, 44, 45, 46, 47,
160 48, 49, 50, 51, 52, 53, 54, 55,
161 56, 57, 58, 59, 60, 61, 62, 63,
162 64, 65, 66, 67, 68, 69, 70, 71,
163 72, 73, 74, 75, 76, 77, 78, 79,
164 80, 81, 82, 83, 84, 85, 86, 87,
165 88, 89, 90, 91, 92, 93, 94, 95,
166 96, 97, 98, 99, 100, 101, 102, 103,
167 104, 105, 106, 107, 108, 109, 110, 111,
168 112, 113, 114, 115, 116, 117, 118, 119,
169 120, 121, 122, 123, 124, 125, 126, 127,
170 128, 129, 130, 131, 132, 133, 134, 135,
171 136, 137, 138, 139, 140, 141, 142, 143,
172 144, 145, 146, 147, 148, 149, 150, 151,
173 152, 153, 154, 155, 156, 157, 158, 159,
174 160, 161, 162, 163, 164, 165, 166, 167,
175 168, 169, 170, 171, 172, 173, 174, 175,
176 176, 177, 178, 179, 180, 181, 182, 183,
177 184, 185, 186, 187, 188, 189, 190, 191,
178 192, 193, 194, 195, 196, 197, 198, 199,
179 200, 201, 202, 203, 204, 205, 206, 207,
180 208, 209, 210, 211, 212, 213, 214, 215,
181 216, 217, 218, 219, 220, 221, 222, 223,
182 224, 225, 226, 227, 228, 229, 230, 231,
183 232, 233, 234, 235, 236, 237, 238, 239,
184 240, 241, 242, 243, 244, 245, 246, 247,
185 248, 249, 250, 251, 252, 253, 254, 255,
186 256, 257, 258, 259, 260, 261, 262, 263,
187 },
188 .oobfree = { {2, 6}, {264, 80} },
189};
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530190
191/*
192 * Generic flash bbt descriptors
193 */
194static u8 bbt_pattern[] = {'B', 'b', 't', '0' };
195static u8 mirror_pattern[] = {'1', 't', 'b', 'B' };
196
197static struct nand_bbt_descr bbt_main_descr = {
198 .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE |
199 NAND_BBT_2BIT | NAND_BBT_VERSION,
200 .offs = 2, /* 0 on 8-bit small page */
201 .len = 4,
202 .veroffs = 6,
203 .maxblocks = 4,
204 .pattern = bbt_pattern,
205};
206
207static struct nand_bbt_descr bbt_mirror_descr = {
208 .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE |
209 NAND_BBT_2BIT | NAND_BBT_VERSION,
210 .offs = 2, /* 0 on 8-bit small page */
211 .len = 4,
212 .veroffs = 6,
213 .maxblocks = 4,
214 .pattern = mirror_pattern,
215};
216
217/*
218 * Set up the IFC hardware block and page address fields, and the ifc nand
219 * structure addr field to point to the correct IFC buffer in memory
220 */
221static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob)
222{
Scott Wood17fed142016-05-30 13:57:56 -0500223 struct nand_chip *chip = mtd_to_nand(mtd);
224 struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530225 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
Jaiprakash Singhdd888062015-03-20 19:28:27 -0700226 struct fsl_ifc_runtime *ifc = ctrl->regs.rregs;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530227 int buf_num;
228
229 ctrl->page = page_addr;
230
231 /* Program ROW0/COL0 */
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530232 ifc_out32(&ifc->ifc_nand.row0, page_addr);
233 ifc_out32(&ifc->ifc_nand.col0, (oob ? IFC_NAND_COL_MS : 0) | column);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530234
235 buf_num = page_addr & priv->bufnum_mask;
236
237 ctrl->addr = priv->vbase + buf_num * (mtd->writesize * 2);
238 ctrl->index = column;
239
240 /* for OOB data point to the second half of the buffer */
241 if (oob)
242 ctrl->index += mtd->writesize;
243}
244
245static int is_blank(struct mtd_info *mtd, struct fsl_ifc_ctrl *ctrl,
246 unsigned int bufnum)
247{
Scott Wood17fed142016-05-30 13:57:56 -0500248 struct nand_chip *chip = mtd_to_nand(mtd);
249 struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530250 u8 __iomem *addr = priv->vbase + bufnum * (mtd->writesize * 2);
251 u32 __iomem *main = (u32 *)addr;
252 u8 __iomem *oob = addr + mtd->writesize;
253 int i;
254
255 for (i = 0; i < mtd->writesize / 4; i++) {
256 if (__raw_readl(&main[i]) != 0xffffffff)
257 return 0;
258 }
259
260 for (i = 0; i < chip->ecc.layout->eccbytes; i++) {
261 int pos = chip->ecc.layout->eccpos[i];
262
263 if (__raw_readb(&oob[pos]) != 0xff)
264 return 0;
265 }
266
267 return 1;
268}
269
270/* returns nonzero if entire page is blank */
271static int check_read_ecc(struct mtd_info *mtd, struct fsl_ifc_ctrl *ctrl,
Jagdish Gediya83fbe912018-03-24 02:55:51 +0530272 u32 eccstat, unsigned int bufnum)
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530273{
Jagdish Gediya83fbe912018-03-24 02:55:51 +0530274 return (eccstat >> ((3 - bufnum % 4) * 8)) & 15;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530275}
276
277/*
278 * execute IFC NAND command and wait for it to complete
279 */
280static int fsl_ifc_run_command(struct mtd_info *mtd)
281{
Scott Wood17fed142016-05-30 13:57:56 -0500282 struct nand_chip *chip = mtd_to_nand(mtd);
283 struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530284 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
Jaiprakash Singhdd888062015-03-20 19:28:27 -0700285 struct fsl_ifc_runtime *ifc = ctrl->regs.rregs;
Prabhakar Kushwahad7550e12014-09-23 09:57:47 +0530286 u32 timeo = (CONFIG_SYS_HZ * 10) / 1000;
287 u32 time_start;
Jagdish Gediya83fbe912018-03-24 02:55:51 +0530288 u32 eccstat;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530289 int i;
290
291 /* set the chip select for NAND Transaction */
Kurt Kanzenbach1f161f82017-10-20 11:44:25 +0200292 ifc_out32(&ifc->ifc_nand.nand_csel, priv->bank << IFC_NAND_CSEL_SHIFT);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530293
294 /* start read/write seq */
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530295 ifc_out32(&ifc->ifc_nand.nandseq_strt,
296 IFC_NAND_SEQ_STRT_FIR_STRT);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530297
298 /* wait for NAND Machine complete flag or timeout */
Prabhakar Kushwahad7550e12014-09-23 09:57:47 +0530299 time_start = get_timer(0);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530300
Prabhakar Kushwahad7550e12014-09-23 09:57:47 +0530301 while (get_timer(time_start) < timeo) {
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530302 ctrl->status = ifc_in32(&ifc->ifc_nand.nand_evter_stat);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530303
304 if (ctrl->status & IFC_NAND_EVTER_STAT_OPC)
305 break;
306 }
307
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530308 ifc_out32(&ifc->ifc_nand.nand_evter_stat, ctrl->status);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530309
310 if (ctrl->status & IFC_NAND_EVTER_STAT_FTOER)
311 printf("%s: Flash Time Out Error\n", __func__);
312 if (ctrl->status & IFC_NAND_EVTER_STAT_WPER)
313 printf("%s: Write Protect Error\n", __func__);
314
315 if (ctrl->eccread) {
Prabhakar Kushwahacdd045d2012-01-20 18:38:14 +0530316 int errors;
317 int bufnum = ctrl->page & priv->bufnum_mask;
Jagdish Gediya83fbe912018-03-24 02:55:51 +0530318 int sector_start = bufnum * chip->ecc.steps;
319 int sector_end = sector_start + chip->ecc.steps - 1;
320 u32 *eccstat_regs;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530321
Jagdish Gediya83fbe912018-03-24 02:55:51 +0530322 eccstat_regs = ifc->ifc_nand.nand_eccstat;
323 eccstat = ifc_in32(&eccstat_regs[sector_start / 4]);
Scott Wood70365492015-03-19 09:20:49 -0700324
Jagdish Gediya83fbe912018-03-24 02:55:51 +0530325 for (i = sector_start; i <= sector_end; i++) {
326 if ((i != sector_start) && !(i % 4))
327 eccstat = ifc_in32(&eccstat_regs[i / 4]);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530328
Prabhakar Kushwahacdd045d2012-01-20 18:38:14 +0530329 errors = check_read_ecc(mtd, ctrl, eccstat, i);
330
331 if (errors == 15) {
332 /*
333 * Uncorrectable error.
334 * OK only if the whole page is blank.
335 *
336 * We disable ECCER reporting due to erratum
337 * IFC-A002770 -- so report it now if we
338 * see an uncorrectable error in ECCSTAT.
339 */
340 if (!is_blank(mtd, ctrl, bufnum))
341 ctrl->status |=
342 IFC_NAND_EVTER_STAT_ECCER;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530343 break;
Prabhakar Kushwahacdd045d2012-01-20 18:38:14 +0530344 }
345
346 mtd->ecc_stats.corrected += errors;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530347 }
348
349 ctrl->eccread = 0;
350 }
351
352 /* returns 0 on success otherwise non-zero) */
353 return ctrl->status == IFC_NAND_EVTER_STAT_OPC ? 0 : -EIO;
354}
355
356static void fsl_ifc_do_read(struct nand_chip *chip,
357 int oob,
358 struct mtd_info *mtd)
359{
Scott Wood17fed142016-05-30 13:57:56 -0500360 struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530361 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
Jaiprakash Singhdd888062015-03-20 19:28:27 -0700362 struct fsl_ifc_runtime *ifc = ctrl->regs.rregs;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530363
364 /* Program FIR/IFC_NAND_FCR0 for Small/Large page */
365 if (mtd->writesize > 512) {
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530366 ifc_out32(&ifc->ifc_nand.nand_fir0,
367 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
368 (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP1_SHIFT) |
369 (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP2_SHIFT) |
370 (IFC_FIR_OP_CMD1 << IFC_NAND_FIR0_OP3_SHIFT) |
371 (IFC_FIR_OP_RBCD << IFC_NAND_FIR0_OP4_SHIFT));
372 ifc_out32(&ifc->ifc_nand.nand_fir1, 0x0);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530373
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530374 ifc_out32(&ifc->ifc_nand.nand_fcr0,
375 (NAND_CMD_READ0 << IFC_NAND_FCR0_CMD0_SHIFT) |
376 (NAND_CMD_READSTART << IFC_NAND_FCR0_CMD1_SHIFT));
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530377 } else {
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530378 ifc_out32(&ifc->ifc_nand.nand_fir0,
379 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
380 (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP1_SHIFT) |
381 (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP2_SHIFT) |
382 (IFC_FIR_OP_RBCD << IFC_NAND_FIR0_OP3_SHIFT));
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530383
384 if (oob)
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530385 ifc_out32(&ifc->ifc_nand.nand_fcr0,
386 NAND_CMD_READOOB << IFC_NAND_FCR0_CMD0_SHIFT);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530387 else
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530388 ifc_out32(&ifc->ifc_nand.nand_fcr0,
389 NAND_CMD_READ0 << IFC_NAND_FCR0_CMD0_SHIFT);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530390 }
391}
392
393/* cmdfunc send commands to the IFC NAND Machine */
394static void fsl_ifc_cmdfunc(struct mtd_info *mtd, unsigned int command,
395 int column, int page_addr)
396{
Scott Wood17fed142016-05-30 13:57:56 -0500397 struct nand_chip *chip = mtd_to_nand(mtd);
398 struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530399 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
Jaiprakash Singhdd888062015-03-20 19:28:27 -0700400 struct fsl_ifc_runtime *ifc = ctrl->regs.rregs;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530401
402 /* clear the read buffer */
403 ctrl->read_bytes = 0;
404 if (command != NAND_CMD_PAGEPROG)
405 ctrl->index = 0;
406
407 switch (command) {
408 /* READ0 read the entire buffer to use hardware ECC. */
409 case NAND_CMD_READ0: {
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530410 ifc_out32(&ifc->ifc_nand.nand_fbcr, 0);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530411 set_addr(mtd, 0, page_addr, 0);
412
413 ctrl->read_bytes = mtd->writesize + mtd->oobsize;
414 ctrl->index += column;
415
416 if (chip->ecc.mode == NAND_ECC_HW)
417 ctrl->eccread = 1;
418
419 fsl_ifc_do_read(chip, 0, mtd);
420 fsl_ifc_run_command(mtd);
421 return;
422 }
423
424 /* READOOB reads only the OOB because no ECC is performed. */
425 case NAND_CMD_READOOB:
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530426 ifc_out32(&ifc->ifc_nand.nand_fbcr, mtd->oobsize - column);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530427 set_addr(mtd, column, page_addr, 1);
428
429 ctrl->read_bytes = mtd->writesize + mtd->oobsize;
430
431 fsl_ifc_do_read(chip, 1, mtd);
432 fsl_ifc_run_command(mtd);
433
434 return;
435
436 /* READID must read all possible bytes while CEB is active */
437 case NAND_CMD_READID:
Prabhakar Kushwahaf31cf532012-04-08 18:57:18 +0000438 case NAND_CMD_PARAM: {
439 int timing = IFC_FIR_OP_RB;
440 if (command == NAND_CMD_PARAM)
441 timing = IFC_FIR_OP_RBCD;
442
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530443 ifc_out32(&ifc->ifc_nand.nand_fir0,
444 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
445 (IFC_FIR_OP_UA << IFC_NAND_FIR0_OP1_SHIFT) |
446 (timing << IFC_NAND_FIR0_OP2_SHIFT));
447 ifc_out32(&ifc->ifc_nand.nand_fcr0,
448 command << IFC_NAND_FCR0_CMD0_SHIFT);
449 ifc_out32(&ifc->ifc_nand.row3, column);
Prabhakar Kushwahaf31cf532012-04-08 18:57:18 +0000450
451 /*
452 * although currently it's 8 bytes for READID, we always read
453 * the maximum 256 bytes(for PARAM)
454 */
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530455 ifc_out32(&ifc->ifc_nand.nand_fbcr, 256);
Prabhakar Kushwahaf31cf532012-04-08 18:57:18 +0000456 ctrl->read_bytes = 256;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530457
458 set_addr(mtd, 0, 0, 0);
459 fsl_ifc_run_command(mtd);
460 return;
Prabhakar Kushwahaf31cf532012-04-08 18:57:18 +0000461 }
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530462
463 /* ERASE1 stores the block and page address */
464 case NAND_CMD_ERASE1:
465 set_addr(mtd, 0, page_addr, 0);
466 return;
467
468 /* ERASE2 uses the block and page address from ERASE1 */
469 case NAND_CMD_ERASE2:
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530470 ifc_out32(&ifc->ifc_nand.nand_fir0,
471 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
472 (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP1_SHIFT) |
473 (IFC_FIR_OP_CMD1 << IFC_NAND_FIR0_OP2_SHIFT));
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530474
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530475 ifc_out32(&ifc->ifc_nand.nand_fcr0,
476 (NAND_CMD_ERASE1 << IFC_NAND_FCR0_CMD0_SHIFT) |
477 (NAND_CMD_ERASE2 << IFC_NAND_FCR0_CMD1_SHIFT));
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530478
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530479 ifc_out32(&ifc->ifc_nand.nand_fbcr, 0);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530480 ctrl->read_bytes = 0;
481 fsl_ifc_run_command(mtd);
482 return;
483
484 /* SEQIN sets up the addr buffer and all registers except the length */
485 case NAND_CMD_SEQIN: {
486 u32 nand_fcr0;
487 ctrl->column = column;
488 ctrl->oob = 0;
489
490 if (mtd->writesize > 512) {
491 nand_fcr0 =
492 (NAND_CMD_SEQIN << IFC_NAND_FCR0_CMD0_SHIFT) |
Prabhakar Kushwaha18e6bde2013-10-03 11:35:35 +0530493 (NAND_CMD_STATUS << IFC_NAND_FCR0_CMD1_SHIFT) |
494 (NAND_CMD_PAGEPROG << IFC_NAND_FCR0_CMD2_SHIFT);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530495
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530496 ifc_out32(&ifc->ifc_nand.nand_fir0,
497 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
498 (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP1_SHIFT) |
499 (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP2_SHIFT) |
500 (IFC_FIR_OP_WBCD <<
501 IFC_NAND_FIR0_OP3_SHIFT) |
502 (IFC_FIR_OP_CMD2 << IFC_NAND_FIR0_OP4_SHIFT));
503 ifc_out32(&ifc->ifc_nand.nand_fir1,
504 (IFC_FIR_OP_CW1 << IFC_NAND_FIR1_OP5_SHIFT) |
505 (IFC_FIR_OP_RDSTAT <<
Prabhakar Kushwaha18e6bde2013-10-03 11:35:35 +0530506 IFC_NAND_FIR1_OP6_SHIFT) |
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530507 (IFC_FIR_OP_NOP << IFC_NAND_FIR1_OP7_SHIFT));
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530508 } else {
509 nand_fcr0 = ((NAND_CMD_PAGEPROG <<
510 IFC_NAND_FCR0_CMD1_SHIFT) |
511 (NAND_CMD_SEQIN <<
Prabhakar Kushwaha18e6bde2013-10-03 11:35:35 +0530512 IFC_NAND_FCR0_CMD2_SHIFT) |
513 (NAND_CMD_STATUS <<
514 IFC_NAND_FCR0_CMD3_SHIFT));
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530515
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530516 ifc_out32(&ifc->ifc_nand.nand_fir0,
517 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
518 (IFC_FIR_OP_CMD2 << IFC_NAND_FIR0_OP1_SHIFT) |
519 (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP2_SHIFT) |
520 (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP3_SHIFT) |
521 (IFC_FIR_OP_WBCD << IFC_NAND_FIR0_OP4_SHIFT));
522 ifc_out32(&ifc->ifc_nand.nand_fir1,
523 (IFC_FIR_OP_CMD1 << IFC_NAND_FIR1_OP5_SHIFT) |
524 (IFC_FIR_OP_CW3 << IFC_NAND_FIR1_OP6_SHIFT) |
525 (IFC_FIR_OP_RDSTAT <<
Prabhakar Kushwaha18e6bde2013-10-03 11:35:35 +0530526 IFC_NAND_FIR1_OP7_SHIFT) |
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530527 (IFC_FIR_OP_NOP << IFC_NAND_FIR1_OP8_SHIFT));
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530528
Prabhakar Kushwaha0ed5e772012-01-20 18:39:05 +0530529 if (column >= mtd->writesize)
530 nand_fcr0 |=
531 NAND_CMD_READOOB << IFC_NAND_FCR0_CMD0_SHIFT;
532 else
533 nand_fcr0 |=
534 NAND_CMD_READ0 << IFC_NAND_FCR0_CMD0_SHIFT;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530535 }
536
Prabhakar Kushwaha0ed5e772012-01-20 18:39:05 +0530537 if (column >= mtd->writesize) {
538 /* OOB area --> READOOB */
539 column -= mtd->writesize;
540 ctrl->oob = 1;
541 }
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530542 ifc_out32(&ifc->ifc_nand.nand_fcr0, nand_fcr0);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530543 set_addr(mtd, column, page_addr, ctrl->oob);
544 return;
545 }
546
547 /* PAGEPROG reuses all of the setup from SEQIN and adds the length */
548 case NAND_CMD_PAGEPROG:
549 if (ctrl->oob)
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530550 ifc_out32(&ifc->ifc_nand.nand_fbcr,
551 ctrl->index - ctrl->column);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530552 else
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530553 ifc_out32(&ifc->ifc_nand.nand_fbcr, 0);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530554
555 fsl_ifc_run_command(mtd);
556 return;
557
558 case NAND_CMD_STATUS:
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530559 ifc_out32(&ifc->ifc_nand.nand_fir0,
560 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
561 (IFC_FIR_OP_RB << IFC_NAND_FIR0_OP1_SHIFT));
562 ifc_out32(&ifc->ifc_nand.nand_fcr0,
563 NAND_CMD_STATUS << IFC_NAND_FCR0_CMD0_SHIFT);
564 ifc_out32(&ifc->ifc_nand.nand_fbcr, 1);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530565 set_addr(mtd, 0, 0, 0);
566 ctrl->read_bytes = 1;
567
568 fsl_ifc_run_command(mtd);
569
Scott Wood3ea94ed2015-06-26 19:03:26 -0500570 /*
571 * The chip always seems to report that it is
572 * write-protected, even when it is not.
573 */
574 if (chip->options & NAND_BUSWIDTH_16)
575 ifc_out16(ctrl->addr,
576 ifc_in16(ctrl->addr) | NAND_STATUS_WP);
577 else
578 out_8(ctrl->addr, in_8(ctrl->addr) | NAND_STATUS_WP);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530579 return;
580
581 case NAND_CMD_RESET:
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530582 ifc_out32(&ifc->ifc_nand.nand_fir0,
583 IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT);
584 ifc_out32(&ifc->ifc_nand.nand_fcr0,
585 NAND_CMD_RESET << IFC_NAND_FCR0_CMD0_SHIFT);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530586 fsl_ifc_run_command(mtd);
587 return;
588
589 default:
590 printf("%s: error, unsupported command 0x%x.\n",
591 __func__, command);
592 }
593}
594
595/*
596 * Write buf to the IFC NAND Controller Data Buffer
597 */
598static void fsl_ifc_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
599{
Scott Wood17fed142016-05-30 13:57:56 -0500600 struct nand_chip *chip = mtd_to_nand(mtd);
601 struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530602 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
603 unsigned int bufsize = mtd->writesize + mtd->oobsize;
604
605 if (len <= 0) {
606 printf("%s of %d bytes", __func__, len);
607 ctrl->status = 0;
608 return;
609 }
610
611 if ((unsigned int)len > bufsize - ctrl->index) {
612 printf("%s beyond end of buffer "
613 "(%d requested, %u available)\n",
614 __func__, len, bufsize - ctrl->index);
615 len = bufsize - ctrl->index;
616 }
617
Scott Wood3ea94ed2015-06-26 19:03:26 -0500618 memcpy_toio(ctrl->addr + ctrl->index, buf, len);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530619 ctrl->index += len;
620}
621
622/*
623 * read a byte from either the IFC hardware buffer if it has any data left
624 * otherwise issue a command to read a single byte.
625 */
626static u8 fsl_ifc_read_byte(struct mtd_info *mtd)
627{
Scott Wood17fed142016-05-30 13:57:56 -0500628 struct nand_chip *chip = mtd_to_nand(mtd);
629 struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530630 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
Scott Wood3ea94ed2015-06-26 19:03:26 -0500631 unsigned int offset;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530632
Scott Wood3ea94ed2015-06-26 19:03:26 -0500633 /*
634 * If there are still bytes in the IFC buffer, then use the
635 * next byte.
636 */
637 if (ctrl->index < ctrl->read_bytes) {
638 offset = ctrl->index++;
639 return in_8(ctrl->addr + offset);
640 }
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530641
642 printf("%s beyond end of buffer\n", __func__);
643 return ERR_BYTE;
644}
645
646/*
647 * Read two bytes from the IFC hardware buffer
648 * read function for 16-bit buswith
649 */
650static uint8_t fsl_ifc_read_byte16(struct mtd_info *mtd)
651{
Scott Wood17fed142016-05-30 13:57:56 -0500652 struct nand_chip *chip = mtd_to_nand(mtd);
653 struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530654 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
655 uint16_t data;
656
657 /*
658 * If there are still bytes in the IFC buffer, then use the
659 * next byte.
660 */
661 if (ctrl->index < ctrl->read_bytes) {
Scott Wood3ea94ed2015-06-26 19:03:26 -0500662 data = ifc_in16(ctrl->addr + ctrl->index);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530663 ctrl->index += 2;
664 return (uint8_t)data;
665 }
666
667 printf("%s beyond end of buffer\n", __func__);
668 return ERR_BYTE;
669}
670
671/*
672 * Read from the IFC Controller Data Buffer
673 */
674static void fsl_ifc_read_buf(struct mtd_info *mtd, u8 *buf, int len)
675{
Scott Wood17fed142016-05-30 13:57:56 -0500676 struct nand_chip *chip = mtd_to_nand(mtd);
677 struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530678 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
679 int avail;
680
681 if (len < 0)
682 return;
683
684 avail = min((unsigned int)len, ctrl->read_bytes - ctrl->index);
Scott Wood3ea94ed2015-06-26 19:03:26 -0500685 memcpy_fromio(buf, ctrl->addr + ctrl->index, avail);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530686 ctrl->index += avail;
687
688 if (len > avail)
689 printf("%s beyond end of buffer "
690 "(%d requested, %d available)\n",
691 __func__, len, avail);
692}
693
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530694/* This function is called after Program and Erase Operations to
695 * check for success or failure.
696 */
697static int fsl_ifc_wait(struct mtd_info *mtd, struct nand_chip *chip)
698{
Scott Wood17fed142016-05-30 13:57:56 -0500699 struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530700 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
Jaiprakash Singhdd888062015-03-20 19:28:27 -0700701 struct fsl_ifc_runtime *ifc = ctrl->regs.rregs;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530702 u32 nand_fsr;
Jagdish Gediya997f04a2018-05-02 01:20:57 +0530703 int status;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530704
705 if (ctrl->status != IFC_NAND_EVTER_STAT_OPC)
706 return NAND_STATUS_FAIL;
707
708 /* Use READ_STATUS command, but wait for the device to be ready */
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530709 ifc_out32(&ifc->ifc_nand.nand_fir0,
710 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
711 (IFC_FIR_OP_RDSTAT << IFC_NAND_FIR0_OP1_SHIFT));
712 ifc_out32(&ifc->ifc_nand.nand_fcr0, NAND_CMD_STATUS <<
713 IFC_NAND_FCR0_CMD0_SHIFT);
714 ifc_out32(&ifc->ifc_nand.nand_fbcr, 1);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530715 set_addr(mtd, 0, 0, 0);
716 ctrl->read_bytes = 1;
717
718 fsl_ifc_run_command(mtd);
719
720 if (ctrl->status != IFC_NAND_EVTER_STAT_OPC)
721 return NAND_STATUS_FAIL;
722
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530723 nand_fsr = ifc_in32(&ifc->ifc_nand.nand_fsr);
Jagdish Gediya997f04a2018-05-02 01:20:57 +0530724 status = nand_fsr >> 24;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530725
726 /* Chip sometimes reporting write protect even when it's not */
Jagdish Gediya997f04a2018-05-02 01:20:57 +0530727 return status | NAND_STATUS_WP;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530728}
729
Sergey Lapin3a38a552013-01-14 03:46:50 +0000730static int fsl_ifc_read_page(struct mtd_info *mtd, struct nand_chip *chip,
731 uint8_t *buf, int oob_required, int page)
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530732{
Scott Wood17fed142016-05-30 13:57:56 -0500733 struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530734 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
735
736 fsl_ifc_read_buf(mtd, buf, mtd->writesize);
737 fsl_ifc_read_buf(mtd, chip->oob_poi, mtd->oobsize);
738
739 if (ctrl->status != IFC_NAND_EVTER_STAT_OPC)
740 mtd->ecc_stats.failed++;
741
742 return 0;
743}
744
745/* ECC will be calculated automatically, and errors will be detected in
746 * waitfunc.
747 */
Sergey Lapin3a38a552013-01-14 03:46:50 +0000748static int fsl_ifc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
Scott Wood46e13102016-05-30 13:57:57 -0500749 const uint8_t *buf, int oob_required, int page)
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530750{
751 fsl_ifc_write_buf(mtd, buf, mtd->writesize);
752 fsl_ifc_write_buf(mtd, chip->oob_poi, mtd->oobsize);
Sergey Lapin3a38a552013-01-14 03:46:50 +0000753
754 return 0;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530755}
756
757static void fsl_ifc_ctrl_init(void)
758{
Jaiprakash Singhdd888062015-03-20 19:28:27 -0700759 uint32_t ver = 0;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530760 ifc_ctrl = kzalloc(sizeof(*ifc_ctrl), GFP_KERNEL);
761 if (!ifc_ctrl)
762 return;
763
Jaiprakash Singhdd888062015-03-20 19:28:27 -0700764 ifc_ctrl->regs.gregs = IFC_FCM_BASE_ADDR;
765
766 ver = ifc_in32(&ifc_ctrl->regs.gregs->ifc_rev);
767 if (ver >= FSL_IFC_V2_0_0)
768 ifc_ctrl->regs.rregs =
769 (void *)CONFIG_SYS_IFC_ADDR + IFC_RREGS_64KOFFSET;
770 else
771 ifc_ctrl->regs.rregs =
772 (void *)CONFIG_SYS_IFC_ADDR + IFC_RREGS_4KOFFSET;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530773
774 /* clear event registers */
Jaiprakash Singhdd888062015-03-20 19:28:27 -0700775 ifc_out32(&ifc_ctrl->regs.rregs->ifc_nand.nand_evter_stat, ~0U);
776 ifc_out32(&ifc_ctrl->regs.rregs->ifc_nand.pgrdcmpl_evt_stat, ~0U);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530777
778 /* Enable error and event for any detected errors */
Jaiprakash Singhdd888062015-03-20 19:28:27 -0700779 ifc_out32(&ifc_ctrl->regs.rregs->ifc_nand.nand_evter_en,
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530780 IFC_NAND_EVTER_EN_OPC_EN |
781 IFC_NAND_EVTER_EN_PGRDCMPL_EN |
782 IFC_NAND_EVTER_EN_FTOER_EN |
783 IFC_NAND_EVTER_EN_WPER_EN);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530784
Jaiprakash Singhdd888062015-03-20 19:28:27 -0700785 ifc_out32(&ifc_ctrl->regs.rregs->ifc_nand.ncfgr, 0x0);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530786}
787
788static void fsl_ifc_select_chip(struct mtd_info *mtd, int chip)
789{
790}
791
Kurt Kanzenbach1f161f82017-10-20 11:44:25 +0200792static int fsl_ifc_sram_init(struct fsl_ifc_mtd *priv, uint32_t ver)
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000793{
Jaiprakash Singhdd888062015-03-20 19:28:27 -0700794 struct fsl_ifc_runtime *ifc = ifc_ctrl->regs.rregs;
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000795 uint32_t cs = 0, csor = 0, csor_8k = 0, csor_ext = 0;
Prabhakar Kushwaha82efc812014-06-12 12:14:00 +0530796 uint32_t ncfgr = 0;
Prabhakar Kushwahad7550e12014-09-23 09:57:47 +0530797 u32 timeo = (CONFIG_SYS_HZ * 10) / 1000;
798 u32 time_start;
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000799
Prabhakar Kushwaha82efc812014-06-12 12:14:00 +0530800 if (ver > FSL_IFC_V1_1_0) {
801 ncfgr = ifc_in32(&ifc->ifc_nand.ncfgr);
802 ifc_out32(&ifc->ifc_nand.ncfgr, ncfgr | IFC_NAND_SRAM_INIT_EN);
803
804 /* wait for SRAM_INIT bit to be clear or timeout */
Prabhakar Kushwahad7550e12014-09-23 09:57:47 +0530805 time_start = get_timer(0);
806 while (get_timer(time_start) < timeo) {
Prabhakar Kushwaha82efc812014-06-12 12:14:00 +0530807 ifc_ctrl->status =
808 ifc_in32(&ifc->ifc_nand.nand_evter_stat);
809
810 if (!(ifc_ctrl->status & IFC_NAND_SRAM_INIT_EN))
811 return 0;
812 }
813 printf("fsl-ifc: Failed to Initialise SRAM\n");
814 return 1;
815 }
816
Kurt Kanzenbach1f161f82017-10-20 11:44:25 +0200817 cs = priv->bank;
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000818
819 /* Save CSOR and CSOR_ext */
Jaiprakash Singhdd888062015-03-20 19:28:27 -0700820 csor = ifc_in32(&ifc_ctrl->regs.gregs->csor_cs[cs].csor);
821 csor_ext = ifc_in32(&ifc_ctrl->regs.gregs->csor_cs[cs].csor_ext);
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000822
823 /* chage PageSize 8K and SpareSize 1K*/
824 csor_8k = (csor & ~(CSOR_NAND_PGS_MASK)) | 0x0018C000;
Jaiprakash Singhdd888062015-03-20 19:28:27 -0700825 ifc_out32(&ifc_ctrl->regs.gregs->csor_cs[cs].csor, csor_8k);
826 ifc_out32(&ifc_ctrl->regs.gregs->csor_cs[cs].csor_ext, 0x0000400);
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000827
828 /* READID */
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530829 ifc_out32(&ifc->ifc_nand.nand_fir0,
830 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
831 (IFC_FIR_OP_UA << IFC_NAND_FIR0_OP1_SHIFT) |
832 (IFC_FIR_OP_RB << IFC_NAND_FIR0_OP2_SHIFT));
833 ifc_out32(&ifc->ifc_nand.nand_fcr0,
834 NAND_CMD_READID << IFC_NAND_FCR0_CMD0_SHIFT);
835 ifc_out32(&ifc->ifc_nand.row3, 0x0);
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000836
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530837 ifc_out32(&ifc->ifc_nand.nand_fbcr, 0x0);
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000838
839 /* Program ROW0/COL0 */
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530840 ifc_out32(&ifc->ifc_nand.row0, 0x0);
841 ifc_out32(&ifc->ifc_nand.col0, 0x0);
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000842
843 /* set the chip select for NAND Transaction */
Kurt Kanzenbach1f161f82017-10-20 11:44:25 +0200844 ifc_out32(&ifc->ifc_nand.nand_csel, priv->bank << IFC_NAND_CSEL_SHIFT);
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000845
846 /* start read seq */
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530847 ifc_out32(&ifc->ifc_nand.nandseq_strt, IFC_NAND_SEQ_STRT_FIR_STRT);
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000848
Prabhakar Kushwahad7550e12014-09-23 09:57:47 +0530849 time_start = get_timer(0);
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000850
Prabhakar Kushwahad7550e12014-09-23 09:57:47 +0530851 while (get_timer(time_start) < timeo) {
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530852 ifc_ctrl->status = ifc_in32(&ifc->ifc_nand.nand_evter_stat);
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000853
854 if (ifc_ctrl->status & IFC_NAND_EVTER_STAT_OPC)
855 break;
856 }
857
Prabhakar Kushwaha82efc812014-06-12 12:14:00 +0530858 if (ifc_ctrl->status != IFC_NAND_EVTER_STAT_OPC) {
859 printf("fsl-ifc: Failed to Initialise SRAM\n");
860 return 1;
861 }
862
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530863 ifc_out32(&ifc->ifc_nand.nand_evter_stat, ifc_ctrl->status);
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000864
865 /* Restore CSOR and CSOR_ext */
Jaiprakash Singhdd888062015-03-20 19:28:27 -0700866 ifc_out32(&ifc_ctrl->regs.gregs->csor_cs[cs].csor, csor);
867 ifc_out32(&ifc_ctrl->regs.gregs->csor_cs[cs].csor_ext, csor_ext);
Prabhakar Kushwaha82efc812014-06-12 12:14:00 +0530868
869 return 0;
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000870}
871
Prabhakar Kushwaha895d0392013-04-04 18:44:06 +0000872static int fsl_ifc_chip_init(int devnum, u8 *addr)
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530873{
Scott Wood2c1b7e12016-05-30 13:57:55 -0500874 struct mtd_info *mtd;
Prabhakar Kushwaha895d0392013-04-04 18:44:06 +0000875 struct nand_chip *nand;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530876 struct fsl_ifc_mtd *priv;
877 struct nand_ecclayout *layout;
Jaiprakash Singhdd888062015-03-20 19:28:27 -0700878 struct fsl_ifc_fcm *gregs = NULL;
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000879 uint32_t cspr = 0, csor = 0, ver = 0;
Prabhakar Kushwaha82efc812014-06-12 12:14:00 +0530880 int ret = 0;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530881
882 if (!ifc_ctrl) {
883 fsl_ifc_ctrl_init();
884 if (!ifc_ctrl)
885 return -1;
886 }
887
888 priv = kzalloc(sizeof(*priv), GFP_KERNEL);
889 if (!priv)
890 return -ENOMEM;
891
892 priv->ctrl = ifc_ctrl;
Prabhakar Kushwaha895d0392013-04-04 18:44:06 +0000893 priv->vbase = addr;
Jaiprakash Singhdd888062015-03-20 19:28:27 -0700894 gregs = ifc_ctrl->regs.gregs;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530895
896 /* Find which chip select it is connected to.
897 */
898 for (priv->bank = 0; priv->bank < MAX_BANKS; priv->bank++) {
Prabhakar Kushwaha895d0392013-04-04 18:44:06 +0000899 phys_addr_t phys_addr = virt_to_phys(addr);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530900
Jaiprakash Singhdd888062015-03-20 19:28:27 -0700901 cspr = ifc_in32(&gregs->cspr_cs[priv->bank].cspr);
902 csor = ifc_in32(&gregs->csor_cs[priv->bank].csor);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530903
904 if ((cspr & CSPR_V) && (cspr & CSPR_MSEL) == CSPR_MSEL_NAND &&
Kurt Kanzenbach1f161f82017-10-20 11:44:25 +0200905 (cspr & CSPR_BA) == CSPR_PHYS_ADDR(phys_addr))
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530906 break;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530907 }
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;
Scott Wood17fed142016-05-30 13:57:56 -0500917 mtd = nand_to_mtd(nand);
Prabhakar Kushwaha895d0392013-04-04 18:44:06 +0000918
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;
Scott Wood17fed142016-05-30 13:57:56 -0500946 nand_set_controller_data(nand, priv);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530947
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)
Kurt Kanzenbach1f161f82017-10-20 11:44:25 +02001021 ret = fsl_ifc_sram_init(priv, ver);
Prabhakar Kushwaha82efc812014-06-12 12:14:00 +05301022 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
Scott Wood2c1b7e12016-05-30 13:57:55 -05001036 ret = nand_register(devnum, mtd);
Prabhakar Kushwaha895d0392013-04-04 18:44:06 +00001037 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}