blob: cf20238782c696fe0bb6ef19872662643d8e2be9 [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>
Simon Glassadaaa482019-11-14 12:57:43 -070010#include <command.h>
Dipen Dudhat9eae0832011-03-22 09:27:39 +053011#include <malloc.h>
Prabhakar Kushwaha895d0392013-04-04 18:44:06 +000012#include <nand.h>
Simon Glassd66c5f72020-02-03 07:36:15 -070013#include <dm/devres.h>
Dipen Dudhat9eae0832011-03-22 09:27:39 +053014
15#include <linux/mtd/mtd.h>
Masahiro Yamada2b7a8732017-11-30 13:45:24 +090016#include <linux/mtd/rawnand.h>
Dipen Dudhat9eae0832011-03-22 09:27:39 +053017#include <linux/mtd/nand_ecc.h>
18
19#include <asm/io.h>
Masahiro Yamada56a931c2016-09-21 11:28:55 +090020#include <linux/errno.h>
York Sun37562f62013-10-22 12:39:02 -070021#include <fsl_ifc.h>
Dipen Dudhat9eae0832011-03-22 09:27:39 +053022
Prabhakar Kushwahaa8759642014-06-12 09:13:08 +053023#ifndef CONFIG_SYS_FSL_IFC_BANK_COUNT
24#define CONFIG_SYS_FSL_IFC_BANK_COUNT 4
25#endif
26
Prabhakar Kushwahaa8759642014-06-12 09:13:08 +053027#define MAX_BANKS CONFIG_SYS_FSL_IFC_BANK_COUNT
Dipen Dudhat9eae0832011-03-22 09:27:39 +053028#define ERR_BYTE 0xFF /* Value returned for read bytes
29 when read failed */
Dipen Dudhat9eae0832011-03-22 09:27:39 +053030
31struct fsl_ifc_ctrl;
32
33/* mtd information per set */
34struct fsl_ifc_mtd {
Dipen Dudhat9eae0832011-03-22 09:27:39 +053035 struct nand_chip chip;
36 struct fsl_ifc_ctrl *ctrl;
37
38 struct device *dev;
39 int bank; /* Chip select bank number */
40 unsigned int bufnum_mask; /* bufnum = page & bufnum_mask */
41 u8 __iomem *vbase; /* Chip select base virtual address */
42};
43
44/* overview of the fsl ifc controller */
45struct fsl_ifc_ctrl {
46 struct nand_hw_control controller;
47 struct fsl_ifc_mtd *chips[MAX_BANKS];
48
49 /* device info */
Jaiprakash Singhdd888062015-03-20 19:28:27 -070050 struct fsl_ifc regs;
Scott Wood3ea94ed2015-06-26 19:03:26 -050051 void __iomem *addr; /* Address of assigned IFC buffer */
Dipen Dudhat9eae0832011-03-22 09:27:39 +053052 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{
Scott Wood17fed142016-05-30 13:57:56 -0500225 struct nand_chip *chip = mtd_to_nand(mtd);
226 struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530227 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
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530247/* returns nonzero if entire page is blank */
248static int check_read_ecc(struct mtd_info *mtd, struct fsl_ifc_ctrl *ctrl,
Jagdish Gediya83fbe912018-03-24 02:55:51 +0530249 u32 eccstat, unsigned int bufnum)
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530250{
Jagdish Gediya83fbe912018-03-24 02:55:51 +0530251 return (eccstat >> ((3 - bufnum % 4) * 8)) & 15;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530252}
253
254/*
255 * execute IFC NAND command and wait for it to complete
256 */
257static int fsl_ifc_run_command(struct mtd_info *mtd)
258{
Scott Wood17fed142016-05-30 13:57:56 -0500259 struct nand_chip *chip = mtd_to_nand(mtd);
260 struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530261 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
Jaiprakash Singhdd888062015-03-20 19:28:27 -0700262 struct fsl_ifc_runtime *ifc = ctrl->regs.rregs;
Prabhakar Kushwahad7550e12014-09-23 09:57:47 +0530263 u32 timeo = (CONFIG_SYS_HZ * 10) / 1000;
264 u32 time_start;
Jagdish Gediya83fbe912018-03-24 02:55:51 +0530265 u32 eccstat;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530266 int i;
267
268 /* set the chip select for NAND Transaction */
Kurt Kanzenbach1f161f82017-10-20 11:44:25 +0200269 ifc_out32(&ifc->ifc_nand.nand_csel, priv->bank << IFC_NAND_CSEL_SHIFT);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530270
271 /* start read/write seq */
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530272 ifc_out32(&ifc->ifc_nand.nandseq_strt,
273 IFC_NAND_SEQ_STRT_FIR_STRT);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530274
275 /* wait for NAND Machine complete flag or timeout */
Prabhakar Kushwahad7550e12014-09-23 09:57:47 +0530276 time_start = get_timer(0);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530277
Prabhakar Kushwahad7550e12014-09-23 09:57:47 +0530278 while (get_timer(time_start) < timeo) {
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530279 ctrl->status = ifc_in32(&ifc->ifc_nand.nand_evter_stat);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530280
281 if (ctrl->status & IFC_NAND_EVTER_STAT_OPC)
282 break;
283 }
284
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530285 ifc_out32(&ifc->ifc_nand.nand_evter_stat, ctrl->status);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530286
287 if (ctrl->status & IFC_NAND_EVTER_STAT_FTOER)
288 printf("%s: Flash Time Out Error\n", __func__);
289 if (ctrl->status & IFC_NAND_EVTER_STAT_WPER)
290 printf("%s: Write Protect Error\n", __func__);
291
292 if (ctrl->eccread) {
Prabhakar Kushwahacdd045d2012-01-20 18:38:14 +0530293 int errors;
294 int bufnum = ctrl->page & priv->bufnum_mask;
Jagdish Gediya83fbe912018-03-24 02:55:51 +0530295 int sector_start = bufnum * chip->ecc.steps;
296 int sector_end = sector_start + chip->ecc.steps - 1;
297 u32 *eccstat_regs;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530298
Jagdish Gediya83fbe912018-03-24 02:55:51 +0530299 eccstat_regs = ifc->ifc_nand.nand_eccstat;
300 eccstat = ifc_in32(&eccstat_regs[sector_start / 4]);
Scott Wood70365492015-03-19 09:20:49 -0700301
Jagdish Gediya83fbe912018-03-24 02:55:51 +0530302 for (i = sector_start; i <= sector_end; i++) {
303 if ((i != sector_start) && !(i % 4))
304 eccstat = ifc_in32(&eccstat_regs[i / 4]);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530305
Prabhakar Kushwahacdd045d2012-01-20 18:38:14 +0530306 errors = check_read_ecc(mtd, ctrl, eccstat, i);
307
308 if (errors == 15) {
309 /*
310 * Uncorrectable error.
Darwin Dingel3dae7e62018-08-02 10:02:45 +0200311 * We'll check for blank pages later.
Prabhakar Kushwahacdd045d2012-01-20 18:38:14 +0530312 *
313 * We disable ECCER reporting due to erratum
314 * IFC-A002770 -- so report it now if we
315 * see an uncorrectable error in ECCSTAT.
316 */
Darwin Dingel3dae7e62018-08-02 10:02:45 +0200317 ctrl->status |= IFC_NAND_EVTER_STAT_ECCER;
318 continue;
Prabhakar Kushwahacdd045d2012-01-20 18:38:14 +0530319 }
320
321 mtd->ecc_stats.corrected += errors;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530322 }
323
324 ctrl->eccread = 0;
325 }
326
327 /* returns 0 on success otherwise non-zero) */
328 return ctrl->status == IFC_NAND_EVTER_STAT_OPC ? 0 : -EIO;
329}
330
331static void fsl_ifc_do_read(struct nand_chip *chip,
332 int oob,
333 struct mtd_info *mtd)
334{
Scott Wood17fed142016-05-30 13:57:56 -0500335 struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530336 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
Jaiprakash Singhdd888062015-03-20 19:28:27 -0700337 struct fsl_ifc_runtime *ifc = ctrl->regs.rregs;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530338
339 /* Program FIR/IFC_NAND_FCR0 for Small/Large page */
340 if (mtd->writesize > 512) {
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530341 ifc_out32(&ifc->ifc_nand.nand_fir0,
342 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
343 (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP1_SHIFT) |
344 (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP2_SHIFT) |
345 (IFC_FIR_OP_CMD1 << IFC_NAND_FIR0_OP3_SHIFT) |
346 (IFC_FIR_OP_RBCD << IFC_NAND_FIR0_OP4_SHIFT));
347 ifc_out32(&ifc->ifc_nand.nand_fir1, 0x0);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530348
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530349 ifc_out32(&ifc->ifc_nand.nand_fcr0,
350 (NAND_CMD_READ0 << IFC_NAND_FCR0_CMD0_SHIFT) |
351 (NAND_CMD_READSTART << IFC_NAND_FCR0_CMD1_SHIFT));
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530352 } else {
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530353 ifc_out32(&ifc->ifc_nand.nand_fir0,
354 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
355 (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP1_SHIFT) |
356 (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP2_SHIFT) |
357 (IFC_FIR_OP_RBCD << IFC_NAND_FIR0_OP3_SHIFT));
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530358
359 if (oob)
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530360 ifc_out32(&ifc->ifc_nand.nand_fcr0,
361 NAND_CMD_READOOB << IFC_NAND_FCR0_CMD0_SHIFT);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530362 else
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530363 ifc_out32(&ifc->ifc_nand.nand_fcr0,
364 NAND_CMD_READ0 << IFC_NAND_FCR0_CMD0_SHIFT);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530365 }
366}
367
368/* cmdfunc send commands to the IFC NAND Machine */
369static void fsl_ifc_cmdfunc(struct mtd_info *mtd, unsigned int command,
370 int column, int page_addr)
371{
Scott Wood17fed142016-05-30 13:57:56 -0500372 struct nand_chip *chip = mtd_to_nand(mtd);
373 struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530374 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
Jaiprakash Singhdd888062015-03-20 19:28:27 -0700375 struct fsl_ifc_runtime *ifc = ctrl->regs.rregs;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530376
377 /* clear the read buffer */
378 ctrl->read_bytes = 0;
379 if (command != NAND_CMD_PAGEPROG)
380 ctrl->index = 0;
381
382 switch (command) {
383 /* READ0 read the entire buffer to use hardware ECC. */
384 case NAND_CMD_READ0: {
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530385 ifc_out32(&ifc->ifc_nand.nand_fbcr, 0);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530386 set_addr(mtd, 0, page_addr, 0);
387
388 ctrl->read_bytes = mtd->writesize + mtd->oobsize;
389 ctrl->index += column;
390
391 if (chip->ecc.mode == NAND_ECC_HW)
392 ctrl->eccread = 1;
393
394 fsl_ifc_do_read(chip, 0, mtd);
395 fsl_ifc_run_command(mtd);
396 return;
397 }
398
399 /* READOOB reads only the OOB because no ECC is performed. */
400 case NAND_CMD_READOOB:
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530401 ifc_out32(&ifc->ifc_nand.nand_fbcr, mtd->oobsize - column);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530402 set_addr(mtd, column, page_addr, 1);
403
404 ctrl->read_bytes = mtd->writesize + mtd->oobsize;
405
406 fsl_ifc_do_read(chip, 1, mtd);
407 fsl_ifc_run_command(mtd);
408
409 return;
410
411 /* READID must read all possible bytes while CEB is active */
412 case NAND_CMD_READID:
Prabhakar Kushwahaf31cf532012-04-08 18:57:18 +0000413 case NAND_CMD_PARAM: {
414 int timing = IFC_FIR_OP_RB;
415 if (command == NAND_CMD_PARAM)
416 timing = IFC_FIR_OP_RBCD;
417
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530418 ifc_out32(&ifc->ifc_nand.nand_fir0,
419 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
420 (IFC_FIR_OP_UA << IFC_NAND_FIR0_OP1_SHIFT) |
421 (timing << IFC_NAND_FIR0_OP2_SHIFT));
422 ifc_out32(&ifc->ifc_nand.nand_fcr0,
423 command << IFC_NAND_FCR0_CMD0_SHIFT);
424 ifc_out32(&ifc->ifc_nand.row3, column);
Prabhakar Kushwahaf31cf532012-04-08 18:57:18 +0000425
426 /*
427 * although currently it's 8 bytes for READID, we always read
428 * the maximum 256 bytes(for PARAM)
429 */
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530430 ifc_out32(&ifc->ifc_nand.nand_fbcr, 256);
Prabhakar Kushwahaf31cf532012-04-08 18:57:18 +0000431 ctrl->read_bytes = 256;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530432
433 set_addr(mtd, 0, 0, 0);
434 fsl_ifc_run_command(mtd);
435 return;
Prabhakar Kushwahaf31cf532012-04-08 18:57:18 +0000436 }
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530437
438 /* ERASE1 stores the block and page address */
439 case NAND_CMD_ERASE1:
440 set_addr(mtd, 0, page_addr, 0);
441 return;
442
443 /* ERASE2 uses the block and page address from ERASE1 */
444 case NAND_CMD_ERASE2:
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530445 ifc_out32(&ifc->ifc_nand.nand_fir0,
446 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
447 (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP1_SHIFT) |
448 (IFC_FIR_OP_CMD1 << IFC_NAND_FIR0_OP2_SHIFT));
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530449
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530450 ifc_out32(&ifc->ifc_nand.nand_fcr0,
451 (NAND_CMD_ERASE1 << IFC_NAND_FCR0_CMD0_SHIFT) |
452 (NAND_CMD_ERASE2 << IFC_NAND_FCR0_CMD1_SHIFT));
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530453
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530454 ifc_out32(&ifc->ifc_nand.nand_fbcr, 0);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530455 ctrl->read_bytes = 0;
456 fsl_ifc_run_command(mtd);
457 return;
458
459 /* SEQIN sets up the addr buffer and all registers except the length */
460 case NAND_CMD_SEQIN: {
461 u32 nand_fcr0;
462 ctrl->column = column;
463 ctrl->oob = 0;
464
465 if (mtd->writesize > 512) {
466 nand_fcr0 =
467 (NAND_CMD_SEQIN << IFC_NAND_FCR0_CMD0_SHIFT) |
Prabhakar Kushwaha18e6bde2013-10-03 11:35:35 +0530468 (NAND_CMD_STATUS << IFC_NAND_FCR0_CMD1_SHIFT) |
469 (NAND_CMD_PAGEPROG << IFC_NAND_FCR0_CMD2_SHIFT);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530470
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530471 ifc_out32(&ifc->ifc_nand.nand_fir0,
472 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
473 (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP1_SHIFT) |
474 (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP2_SHIFT) |
475 (IFC_FIR_OP_WBCD <<
476 IFC_NAND_FIR0_OP3_SHIFT) |
477 (IFC_FIR_OP_CMD2 << IFC_NAND_FIR0_OP4_SHIFT));
478 ifc_out32(&ifc->ifc_nand.nand_fir1,
479 (IFC_FIR_OP_CW1 << IFC_NAND_FIR1_OP5_SHIFT) |
480 (IFC_FIR_OP_RDSTAT <<
Prabhakar Kushwaha18e6bde2013-10-03 11:35:35 +0530481 IFC_NAND_FIR1_OP6_SHIFT) |
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530482 (IFC_FIR_OP_NOP << IFC_NAND_FIR1_OP7_SHIFT));
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530483 } else {
484 nand_fcr0 = ((NAND_CMD_PAGEPROG <<
485 IFC_NAND_FCR0_CMD1_SHIFT) |
486 (NAND_CMD_SEQIN <<
Prabhakar Kushwaha18e6bde2013-10-03 11:35:35 +0530487 IFC_NAND_FCR0_CMD2_SHIFT) |
488 (NAND_CMD_STATUS <<
489 IFC_NAND_FCR0_CMD3_SHIFT));
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530490
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530491 ifc_out32(&ifc->ifc_nand.nand_fir0,
492 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
493 (IFC_FIR_OP_CMD2 << IFC_NAND_FIR0_OP1_SHIFT) |
494 (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP2_SHIFT) |
495 (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP3_SHIFT) |
496 (IFC_FIR_OP_WBCD << IFC_NAND_FIR0_OP4_SHIFT));
497 ifc_out32(&ifc->ifc_nand.nand_fir1,
498 (IFC_FIR_OP_CMD1 << IFC_NAND_FIR1_OP5_SHIFT) |
499 (IFC_FIR_OP_CW3 << IFC_NAND_FIR1_OP6_SHIFT) |
500 (IFC_FIR_OP_RDSTAT <<
Prabhakar Kushwaha18e6bde2013-10-03 11:35:35 +0530501 IFC_NAND_FIR1_OP7_SHIFT) |
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530502 (IFC_FIR_OP_NOP << IFC_NAND_FIR1_OP8_SHIFT));
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530503
Prabhakar Kushwaha0ed5e772012-01-20 18:39:05 +0530504 if (column >= mtd->writesize)
505 nand_fcr0 |=
506 NAND_CMD_READOOB << IFC_NAND_FCR0_CMD0_SHIFT;
507 else
508 nand_fcr0 |=
509 NAND_CMD_READ0 << IFC_NAND_FCR0_CMD0_SHIFT;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530510 }
511
Prabhakar Kushwaha0ed5e772012-01-20 18:39:05 +0530512 if (column >= mtd->writesize) {
513 /* OOB area --> READOOB */
514 column -= mtd->writesize;
515 ctrl->oob = 1;
516 }
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530517 ifc_out32(&ifc->ifc_nand.nand_fcr0, nand_fcr0);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530518 set_addr(mtd, column, page_addr, ctrl->oob);
519 return;
520 }
521
522 /* PAGEPROG reuses all of the setup from SEQIN and adds the length */
523 case NAND_CMD_PAGEPROG:
524 if (ctrl->oob)
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530525 ifc_out32(&ifc->ifc_nand.nand_fbcr,
526 ctrl->index - ctrl->column);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530527 else
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530528 ifc_out32(&ifc->ifc_nand.nand_fbcr, 0);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530529
530 fsl_ifc_run_command(mtd);
531 return;
532
533 case NAND_CMD_STATUS:
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530534 ifc_out32(&ifc->ifc_nand.nand_fir0,
535 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
536 (IFC_FIR_OP_RB << IFC_NAND_FIR0_OP1_SHIFT));
537 ifc_out32(&ifc->ifc_nand.nand_fcr0,
538 NAND_CMD_STATUS << IFC_NAND_FCR0_CMD0_SHIFT);
539 ifc_out32(&ifc->ifc_nand.nand_fbcr, 1);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530540 set_addr(mtd, 0, 0, 0);
541 ctrl->read_bytes = 1;
542
543 fsl_ifc_run_command(mtd);
544
Scott Wood3ea94ed2015-06-26 19:03:26 -0500545 /*
546 * The chip always seems to report that it is
547 * write-protected, even when it is not.
548 */
549 if (chip->options & NAND_BUSWIDTH_16)
550 ifc_out16(ctrl->addr,
551 ifc_in16(ctrl->addr) | NAND_STATUS_WP);
552 else
553 out_8(ctrl->addr, in_8(ctrl->addr) | NAND_STATUS_WP);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530554 return;
555
556 case NAND_CMD_RESET:
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530557 ifc_out32(&ifc->ifc_nand.nand_fir0,
558 IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT);
559 ifc_out32(&ifc->ifc_nand.nand_fcr0,
560 NAND_CMD_RESET << IFC_NAND_FCR0_CMD0_SHIFT);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530561 fsl_ifc_run_command(mtd);
562 return;
563
564 default:
565 printf("%s: error, unsupported command 0x%x.\n",
566 __func__, command);
567 }
568}
569
570/*
571 * Write buf to the IFC NAND Controller Data Buffer
572 */
573static void fsl_ifc_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
574{
Scott Wood17fed142016-05-30 13:57:56 -0500575 struct nand_chip *chip = mtd_to_nand(mtd);
576 struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530577 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
578 unsigned int bufsize = mtd->writesize + mtd->oobsize;
579
580 if (len <= 0) {
581 printf("%s of %d bytes", __func__, len);
582 ctrl->status = 0;
583 return;
584 }
585
586 if ((unsigned int)len > bufsize - ctrl->index) {
587 printf("%s beyond end of buffer "
588 "(%d requested, %u available)\n",
589 __func__, len, bufsize - ctrl->index);
590 len = bufsize - ctrl->index;
591 }
592
Scott Wood3ea94ed2015-06-26 19:03:26 -0500593 memcpy_toio(ctrl->addr + ctrl->index, buf, len);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530594 ctrl->index += len;
595}
596
597/*
598 * read a byte from either the IFC hardware buffer if it has any data left
599 * otherwise issue a command to read a single byte.
600 */
601static u8 fsl_ifc_read_byte(struct mtd_info *mtd)
602{
Scott Wood17fed142016-05-30 13:57:56 -0500603 struct nand_chip *chip = mtd_to_nand(mtd);
604 struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530605 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
Scott Wood3ea94ed2015-06-26 19:03:26 -0500606 unsigned int offset;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530607
Scott Wood3ea94ed2015-06-26 19:03:26 -0500608 /*
609 * If there are still bytes in the IFC buffer, then use the
610 * next byte.
611 */
612 if (ctrl->index < ctrl->read_bytes) {
613 offset = ctrl->index++;
614 return in_8(ctrl->addr + offset);
615 }
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530616
617 printf("%s beyond end of buffer\n", __func__);
618 return ERR_BYTE;
619}
620
621/*
622 * Read two bytes from the IFC hardware buffer
623 * read function for 16-bit buswith
624 */
625static uint8_t fsl_ifc_read_byte16(struct mtd_info *mtd)
626{
Scott Wood17fed142016-05-30 13:57:56 -0500627 struct nand_chip *chip = mtd_to_nand(mtd);
628 struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530629 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
630 uint16_t data;
631
632 /*
633 * If there are still bytes in the IFC buffer, then use the
634 * next byte.
635 */
636 if (ctrl->index < ctrl->read_bytes) {
Scott Wood3ea94ed2015-06-26 19:03:26 -0500637 data = ifc_in16(ctrl->addr + ctrl->index);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530638 ctrl->index += 2;
639 return (uint8_t)data;
640 }
641
642 printf("%s beyond end of buffer\n", __func__);
643 return ERR_BYTE;
644}
645
646/*
647 * Read from the IFC Controller Data Buffer
648 */
649static void fsl_ifc_read_buf(struct mtd_info *mtd, u8 *buf, int len)
650{
Scott Wood17fed142016-05-30 13:57:56 -0500651 struct nand_chip *chip = mtd_to_nand(mtd);
652 struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530653 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
654 int avail;
655
656 if (len < 0)
657 return;
658
659 avail = min((unsigned int)len, ctrl->read_bytes - ctrl->index);
Scott Wood3ea94ed2015-06-26 19:03:26 -0500660 memcpy_fromio(buf, ctrl->addr + ctrl->index, avail);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530661 ctrl->index += avail;
662
663 if (len > avail)
664 printf("%s beyond end of buffer "
665 "(%d requested, %d available)\n",
666 __func__, len, avail);
667}
668
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530669/* This function is called after Program and Erase Operations to
670 * check for success or failure.
671 */
672static int fsl_ifc_wait(struct mtd_info *mtd, struct nand_chip *chip)
673{
Scott Wood17fed142016-05-30 13:57:56 -0500674 struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530675 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
Jaiprakash Singhdd888062015-03-20 19:28:27 -0700676 struct fsl_ifc_runtime *ifc = ctrl->regs.rregs;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530677 u32 nand_fsr;
Jagdish Gediya997f04a2018-05-02 01:20:57 +0530678 int status;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530679
680 if (ctrl->status != IFC_NAND_EVTER_STAT_OPC)
681 return NAND_STATUS_FAIL;
682
683 /* Use READ_STATUS command, but wait for the device to be ready */
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530684 ifc_out32(&ifc->ifc_nand.nand_fir0,
685 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
686 (IFC_FIR_OP_RDSTAT << IFC_NAND_FIR0_OP1_SHIFT));
687 ifc_out32(&ifc->ifc_nand.nand_fcr0, NAND_CMD_STATUS <<
688 IFC_NAND_FCR0_CMD0_SHIFT);
689 ifc_out32(&ifc->ifc_nand.nand_fbcr, 1);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530690 set_addr(mtd, 0, 0, 0);
691 ctrl->read_bytes = 1;
692
693 fsl_ifc_run_command(mtd);
694
695 if (ctrl->status != IFC_NAND_EVTER_STAT_OPC)
696 return NAND_STATUS_FAIL;
697
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530698 nand_fsr = ifc_in32(&ifc->ifc_nand.nand_fsr);
Jagdish Gediya997f04a2018-05-02 01:20:57 +0530699 status = nand_fsr >> 24;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530700
701 /* Chip sometimes reporting write protect even when it's not */
Jagdish Gediya997f04a2018-05-02 01:20:57 +0530702 return status | NAND_STATUS_WP;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530703}
704
Darwin Dingel3dae7e62018-08-02 10:02:45 +0200705/*
706 * The controller does not check for bitflips in erased pages,
707 * therefore software must check instead.
708 */
709static int
710check_erased_page(struct nand_chip *chip, u8 *buf, struct mtd_info *mtd)
711{
712 u8 *ecc = chip->oob_poi;
713 const int ecc_size = chip->ecc.bytes;
714 const int pkt_size = chip->ecc.size;
715 int i, res, bitflips;
716
717 /* IFC starts ecc bytes at offset 8 in the spare area. */
718 ecc += 8;
719 bitflips = 0;
720 for (i = 0; i < chip->ecc.steps; i++) {
721 res = nand_check_erased_ecc_chunk(buf, pkt_size, ecc, ecc_size,
722 NULL, 0, chip->ecc.strength);
723
724 if (res < 0) {
725 printf("fsl-ifc: NAND Flash ECC Uncorrectable Error\n");
726 mtd->ecc_stats.failed++;
727 } else if (res > 0) {
728 mtd->ecc_stats.corrected += res;
729 }
730 bitflips = max(res, bitflips);
731 buf += pkt_size;
732 ecc += ecc_size;
733 }
734
735 return bitflips;
736}
737
Sergey Lapin3a38a552013-01-14 03:46:50 +0000738static int fsl_ifc_read_page(struct mtd_info *mtd, struct nand_chip *chip,
739 uint8_t *buf, int oob_required, int page)
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530740{
Scott Wood17fed142016-05-30 13:57:56 -0500741 struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530742 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
743
744 fsl_ifc_read_buf(mtd, buf, mtd->writesize);
745 fsl_ifc_read_buf(mtd, chip->oob_poi, mtd->oobsize);
746
Darwin Dingel3dae7e62018-08-02 10:02:45 +0200747 if (ctrl->status & IFC_NAND_EVTER_STAT_ECCER)
748 return check_erased_page(chip, buf, mtd);
749
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530750 if (ctrl->status != IFC_NAND_EVTER_STAT_OPC)
751 mtd->ecc_stats.failed++;
752
753 return 0;
754}
755
756/* ECC will be calculated automatically, and errors will be detected in
757 * waitfunc.
758 */
Sergey Lapin3a38a552013-01-14 03:46:50 +0000759static int fsl_ifc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
Scott Wood46e13102016-05-30 13:57:57 -0500760 const uint8_t *buf, int oob_required, int page)
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530761{
762 fsl_ifc_write_buf(mtd, buf, mtd->writesize);
763 fsl_ifc_write_buf(mtd, chip->oob_poi, mtd->oobsize);
Sergey Lapin3a38a552013-01-14 03:46:50 +0000764
765 return 0;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530766}
767
768static void fsl_ifc_ctrl_init(void)
769{
Jaiprakash Singhdd888062015-03-20 19:28:27 -0700770 uint32_t ver = 0;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530771 ifc_ctrl = kzalloc(sizeof(*ifc_ctrl), GFP_KERNEL);
772 if (!ifc_ctrl)
773 return;
774
Jaiprakash Singhdd888062015-03-20 19:28:27 -0700775 ifc_ctrl->regs.gregs = IFC_FCM_BASE_ADDR;
776
777 ver = ifc_in32(&ifc_ctrl->regs.gregs->ifc_rev);
778 if (ver >= FSL_IFC_V2_0_0)
779 ifc_ctrl->regs.rregs =
780 (void *)CONFIG_SYS_IFC_ADDR + IFC_RREGS_64KOFFSET;
781 else
782 ifc_ctrl->regs.rregs =
783 (void *)CONFIG_SYS_IFC_ADDR + IFC_RREGS_4KOFFSET;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530784
785 /* clear event registers */
Jaiprakash Singhdd888062015-03-20 19:28:27 -0700786 ifc_out32(&ifc_ctrl->regs.rregs->ifc_nand.nand_evter_stat, ~0U);
787 ifc_out32(&ifc_ctrl->regs.rregs->ifc_nand.pgrdcmpl_evt_stat, ~0U);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530788
789 /* Enable error and event for any detected errors */
Jaiprakash Singhdd888062015-03-20 19:28:27 -0700790 ifc_out32(&ifc_ctrl->regs.rregs->ifc_nand.nand_evter_en,
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530791 IFC_NAND_EVTER_EN_OPC_EN |
792 IFC_NAND_EVTER_EN_PGRDCMPL_EN |
793 IFC_NAND_EVTER_EN_FTOER_EN |
794 IFC_NAND_EVTER_EN_WPER_EN);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530795
Jaiprakash Singhdd888062015-03-20 19:28:27 -0700796 ifc_out32(&ifc_ctrl->regs.rregs->ifc_nand.ncfgr, 0x0);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530797}
798
799static void fsl_ifc_select_chip(struct mtd_info *mtd, int chip)
800{
801}
802
Kurt Kanzenbach1f161f82017-10-20 11:44:25 +0200803static int fsl_ifc_sram_init(struct fsl_ifc_mtd *priv, uint32_t ver)
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000804{
Jaiprakash Singhdd888062015-03-20 19:28:27 -0700805 struct fsl_ifc_runtime *ifc = ifc_ctrl->regs.rregs;
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000806 uint32_t cs = 0, csor = 0, csor_8k = 0, csor_ext = 0;
Prabhakar Kushwaha82efc812014-06-12 12:14:00 +0530807 uint32_t ncfgr = 0;
Prabhakar Kushwahad7550e12014-09-23 09:57:47 +0530808 u32 timeo = (CONFIG_SYS_HZ * 10) / 1000;
809 u32 time_start;
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000810
Prabhakar Kushwaha82efc812014-06-12 12:14:00 +0530811 if (ver > FSL_IFC_V1_1_0) {
812 ncfgr = ifc_in32(&ifc->ifc_nand.ncfgr);
813 ifc_out32(&ifc->ifc_nand.ncfgr, ncfgr | IFC_NAND_SRAM_INIT_EN);
814
815 /* wait for SRAM_INIT bit to be clear or timeout */
Prabhakar Kushwahad7550e12014-09-23 09:57:47 +0530816 time_start = get_timer(0);
817 while (get_timer(time_start) < timeo) {
Prabhakar Kushwaha82efc812014-06-12 12:14:00 +0530818 ifc_ctrl->status =
819 ifc_in32(&ifc->ifc_nand.nand_evter_stat);
820
821 if (!(ifc_ctrl->status & IFC_NAND_SRAM_INIT_EN))
822 return 0;
823 }
824 printf("fsl-ifc: Failed to Initialise SRAM\n");
825 return 1;
826 }
827
Kurt Kanzenbach1f161f82017-10-20 11:44:25 +0200828 cs = priv->bank;
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000829
830 /* Save CSOR and CSOR_ext */
Jaiprakash Singhdd888062015-03-20 19:28:27 -0700831 csor = ifc_in32(&ifc_ctrl->regs.gregs->csor_cs[cs].csor);
832 csor_ext = ifc_in32(&ifc_ctrl->regs.gregs->csor_cs[cs].csor_ext);
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000833
834 /* chage PageSize 8K and SpareSize 1K*/
835 csor_8k = (csor & ~(CSOR_NAND_PGS_MASK)) | 0x0018C000;
Jaiprakash Singhdd888062015-03-20 19:28:27 -0700836 ifc_out32(&ifc_ctrl->regs.gregs->csor_cs[cs].csor, csor_8k);
837 ifc_out32(&ifc_ctrl->regs.gregs->csor_cs[cs].csor_ext, 0x0000400);
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000838
839 /* READID */
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530840 ifc_out32(&ifc->ifc_nand.nand_fir0,
841 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
842 (IFC_FIR_OP_UA << IFC_NAND_FIR0_OP1_SHIFT) |
843 (IFC_FIR_OP_RB << IFC_NAND_FIR0_OP2_SHIFT));
844 ifc_out32(&ifc->ifc_nand.nand_fcr0,
845 NAND_CMD_READID << IFC_NAND_FCR0_CMD0_SHIFT);
846 ifc_out32(&ifc->ifc_nand.row3, 0x0);
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000847
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530848 ifc_out32(&ifc->ifc_nand.nand_fbcr, 0x0);
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000849
850 /* Program ROW0/COL0 */
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530851 ifc_out32(&ifc->ifc_nand.row0, 0x0);
852 ifc_out32(&ifc->ifc_nand.col0, 0x0);
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000853
854 /* set the chip select for NAND Transaction */
Kurt Kanzenbach1f161f82017-10-20 11:44:25 +0200855 ifc_out32(&ifc->ifc_nand.nand_csel, priv->bank << IFC_NAND_CSEL_SHIFT);
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000856
857 /* start read seq */
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530858 ifc_out32(&ifc->ifc_nand.nandseq_strt, IFC_NAND_SEQ_STRT_FIR_STRT);
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000859
Prabhakar Kushwahad7550e12014-09-23 09:57:47 +0530860 time_start = get_timer(0);
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000861
Prabhakar Kushwahad7550e12014-09-23 09:57:47 +0530862 while (get_timer(time_start) < timeo) {
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530863 ifc_ctrl->status = ifc_in32(&ifc->ifc_nand.nand_evter_stat);
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000864
865 if (ifc_ctrl->status & IFC_NAND_EVTER_STAT_OPC)
866 break;
867 }
868
Prabhakar Kushwaha82efc812014-06-12 12:14:00 +0530869 if (ifc_ctrl->status != IFC_NAND_EVTER_STAT_OPC) {
870 printf("fsl-ifc: Failed to Initialise SRAM\n");
871 return 1;
872 }
873
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530874 ifc_out32(&ifc->ifc_nand.nand_evter_stat, ifc_ctrl->status);
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000875
876 /* Restore CSOR and CSOR_ext */
Jaiprakash Singhdd888062015-03-20 19:28:27 -0700877 ifc_out32(&ifc_ctrl->regs.gregs->csor_cs[cs].csor, csor);
878 ifc_out32(&ifc_ctrl->regs.gregs->csor_cs[cs].csor_ext, csor_ext);
Prabhakar Kushwaha82efc812014-06-12 12:14:00 +0530879
880 return 0;
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000881}
882
Prabhakar Kushwaha895d0392013-04-04 18:44:06 +0000883static int fsl_ifc_chip_init(int devnum, u8 *addr)
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530884{
Scott Wood2c1b7e12016-05-30 13:57:55 -0500885 struct mtd_info *mtd;
Prabhakar Kushwaha895d0392013-04-04 18:44:06 +0000886 struct nand_chip *nand;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530887 struct fsl_ifc_mtd *priv;
888 struct nand_ecclayout *layout;
Jaiprakash Singhdd888062015-03-20 19:28:27 -0700889 struct fsl_ifc_fcm *gregs = NULL;
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000890 uint32_t cspr = 0, csor = 0, ver = 0;
Prabhakar Kushwaha82efc812014-06-12 12:14:00 +0530891 int ret = 0;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530892
893 if (!ifc_ctrl) {
894 fsl_ifc_ctrl_init();
895 if (!ifc_ctrl)
896 return -1;
897 }
898
899 priv = kzalloc(sizeof(*priv), GFP_KERNEL);
900 if (!priv)
901 return -ENOMEM;
902
903 priv->ctrl = ifc_ctrl;
Prabhakar Kushwaha895d0392013-04-04 18:44:06 +0000904 priv->vbase = addr;
Jaiprakash Singhdd888062015-03-20 19:28:27 -0700905 gregs = ifc_ctrl->regs.gregs;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530906
907 /* Find which chip select it is connected to.
908 */
909 for (priv->bank = 0; priv->bank < MAX_BANKS; priv->bank++) {
Prabhakar Kushwaha895d0392013-04-04 18:44:06 +0000910 phys_addr_t phys_addr = virt_to_phys(addr);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530911
Jaiprakash Singhdd888062015-03-20 19:28:27 -0700912 cspr = ifc_in32(&gregs->cspr_cs[priv->bank].cspr);
913 csor = ifc_in32(&gregs->csor_cs[priv->bank].csor);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530914
915 if ((cspr & CSPR_V) && (cspr & CSPR_MSEL) == CSPR_MSEL_NAND &&
Kurt Kanzenbach1f161f82017-10-20 11:44:25 +0200916 (cspr & CSPR_BA) == CSPR_PHYS_ADDR(phys_addr))
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530917 break;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530918 }
919
920 if (priv->bank >= MAX_BANKS) {
921 printf("%s: address did not match any "
922 "chip selects\n", __func__);
Prabhakar Kushwahaae25e882012-04-10 22:48:27 +0000923 kfree(priv);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530924 return -ENODEV;
925 }
926
Prabhakar Kushwaha895d0392013-04-04 18:44:06 +0000927 nand = &priv->chip;
Scott Wood17fed142016-05-30 13:57:56 -0500928 mtd = nand_to_mtd(nand);
Prabhakar Kushwaha895d0392013-04-04 18:44:06 +0000929
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530930 ifc_ctrl->chips[priv->bank] = priv;
931
932 /* fill in nand_chip structure */
933 /* set up function call table */
934
935 nand->write_buf = fsl_ifc_write_buf;
936 nand->read_buf = fsl_ifc_read_buf;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530937 nand->select_chip = fsl_ifc_select_chip;
938 nand->cmdfunc = fsl_ifc_cmdfunc;
939 nand->waitfunc = fsl_ifc_wait;
940
941 /* set up nand options */
942 nand->bbt_td = &bbt_main_descr;
943 nand->bbt_md = &bbt_mirror_descr;
944
945 /* set up nand options */
Sergey Lapin3a38a552013-01-14 03:46:50 +0000946 nand->options = NAND_NO_SUBPAGE_WRITE;
947 nand->bbt_options = NAND_BBT_USE_FLASH;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530948
949 if (cspr & CSPR_PORT_SIZE_16) {
950 nand->read_byte = fsl_ifc_read_byte16;
951 nand->options |= NAND_BUSWIDTH_16;
952 } else {
953 nand->read_byte = fsl_ifc_read_byte;
954 }
955
956 nand->controller = &ifc_ctrl->controller;
Scott Wood17fed142016-05-30 13:57:56 -0500957 nand_set_controller_data(nand, priv);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530958
959 nand->ecc.read_page = fsl_ifc_read_page;
960 nand->ecc.write_page = fsl_ifc_write_page;
961
962 /* Hardware generates ECC per 512 Bytes */
963 nand->ecc.size = 512;
964 nand->ecc.bytes = 8;
965
966 switch (csor & CSOR_NAND_PGS_MASK) {
967 case CSOR_NAND_PGS_512:
968 if (nand->options & NAND_BUSWIDTH_16) {
969 layout = &oob_512_16bit_ecc4;
970 } else {
971 layout = &oob_512_8bit_ecc4;
972
973 /* Avoid conflict with bad block marker */
974 bbt_main_descr.offs = 0;
975 bbt_mirror_descr.offs = 0;
976 }
977
Sergey Lapin3a38a552013-01-14 03:46:50 +0000978 nand->ecc.strength = 4;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530979 priv->bufnum_mask = 15;
980 break;
981
982 case CSOR_NAND_PGS_2K:
983 layout = &oob_2048_ecc4;
Sergey Lapin3a38a552013-01-14 03:46:50 +0000984 nand->ecc.strength = 4;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530985 priv->bufnum_mask = 3;
986 break;
987
988 case CSOR_NAND_PGS_4K:
989 if ((csor & CSOR_NAND_ECC_MODE_MASK) ==
990 CSOR_NAND_ECC_MODE_4) {
991 layout = &oob_4096_ecc4;
Sergey Lapin3a38a552013-01-14 03:46:50 +0000992 nand->ecc.strength = 4;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530993 } else {
994 layout = &oob_4096_ecc8;
Sergey Lapin3a38a552013-01-14 03:46:50 +0000995 nand->ecc.strength = 8;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530996 nand->ecc.bytes = 16;
997 }
998
999 priv->bufnum_mask = 1;
1000 break;
1001
Prabhakar Kushwahaa3aaf1d2013-10-04 10:05:36 +05301002 case CSOR_NAND_PGS_8K:
1003 if ((csor & CSOR_NAND_ECC_MODE_MASK) ==
1004 CSOR_NAND_ECC_MODE_4) {
1005 layout = &oob_8192_ecc4;
1006 nand->ecc.strength = 4;
1007 } else {
1008 layout = &oob_8192_ecc8;
1009 nand->ecc.strength = 8;
1010 nand->ecc.bytes = 16;
1011 }
1012
1013 priv->bufnum_mask = 0;
1014 break;
1015
1016
Dipen Dudhat9eae0832011-03-22 09:27:39 +05301017 default:
1018 printf("ifc nand: bad csor %#x: bad page size\n", csor);
1019 return -ENODEV;
1020 }
1021
1022 /* Must also set CSOR_NAND_ECC_ENC_EN if DEC_EN set */
1023 if (csor & CSOR_NAND_ECC_DEC_EN) {
1024 nand->ecc.mode = NAND_ECC_HW;
1025 nand->ecc.layout = layout;
1026 } else {
1027 nand->ecc.mode = NAND_ECC_SOFT;
1028 }
1029
Jaiprakash Singhdd888062015-03-20 19:28:27 -07001030 ver = ifc_in32(&gregs->ifc_rev);
Prabhakar Kushwaha82efc812014-06-12 12:14:00 +05301031 if (ver >= FSL_IFC_V1_1_0)
Kurt Kanzenbach1f161f82017-10-20 11:44:25 +02001032 ret = fsl_ifc_sram_init(priv, ver);
Prabhakar Kushwaha82efc812014-06-12 12:14:00 +05301033 if (ret)
1034 return ret;
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +00001035
Prabhakar Kushwaha5c23a822014-06-14 08:48:19 +05301036 if (ver >= FSL_IFC_V2_0_0)
1037 priv->bufnum_mask = (priv->bufnum_mask * 2) + 1;
1038
Prabhakar Kushwaha895d0392013-04-04 18:44:06 +00001039 ret = nand_scan_ident(mtd, 1, NULL);
1040 if (ret)
1041 return ret;
1042
1043 ret = nand_scan_tail(mtd);
1044 if (ret)
1045 return ret;
1046
Scott Wood2c1b7e12016-05-30 13:57:55 -05001047 ret = nand_register(devnum, mtd);
Prabhakar Kushwaha895d0392013-04-04 18:44:06 +00001048 if (ret)
1049 return ret;
Dipen Dudhat9eae0832011-03-22 09:27:39 +05301050 return 0;
1051}
Prabhakar Kushwaha895d0392013-04-04 18:44:06 +00001052
1053#ifndef CONFIG_SYS_NAND_BASE_LIST
1054#define CONFIG_SYS_NAND_BASE_LIST { CONFIG_SYS_NAND_BASE }
1055#endif
1056
1057static unsigned long base_address[CONFIG_SYS_MAX_NAND_DEVICE] =
1058 CONFIG_SYS_NAND_BASE_LIST;
1059
1060void board_nand_init(void)
1061{
1062 int i;
1063
1064 for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++)
1065 fsl_ifc_chip_init(i, (u8 *)base_address[i]);
1066}