blob: e5ff937872e41b0a88247e3f9c986ceca7377f2b [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: {
Maxim Kochetkovfce4f4d2021-03-12 09:27:41 +0300414 /*
415 * For READID, read 8 bytes that are currently used.
416 * For PARAM, read all 3 copies of 256-bytes pages.
417 */
418 int len = 8;
Prabhakar Kushwahaf31cf532012-04-08 18:57:18 +0000419 int timing = IFC_FIR_OP_RB;
Maxim Kochetkovfce4f4d2021-03-12 09:27:41 +0300420 if (command == NAND_CMD_PARAM) {
Prabhakar Kushwahaf31cf532012-04-08 18:57:18 +0000421 timing = IFC_FIR_OP_RBCD;
Maxim Kochetkovfce4f4d2021-03-12 09:27:41 +0300422 len = 256 * 3;
423 }
Prabhakar Kushwahaf31cf532012-04-08 18:57:18 +0000424
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530425 ifc_out32(&ifc->ifc_nand.nand_fir0,
426 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
427 (IFC_FIR_OP_UA << IFC_NAND_FIR0_OP1_SHIFT) |
428 (timing << IFC_NAND_FIR0_OP2_SHIFT));
429 ifc_out32(&ifc->ifc_nand.nand_fcr0,
430 command << IFC_NAND_FCR0_CMD0_SHIFT);
431 ifc_out32(&ifc->ifc_nand.row3, column);
Prabhakar Kushwahaf31cf532012-04-08 18:57:18 +0000432
Maxim Kochetkovfce4f4d2021-03-12 09:27:41 +0300433 ifc_out32(&ifc->ifc_nand.nand_fbcr, len);
434 ctrl->read_bytes = len;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530435
436 set_addr(mtd, 0, 0, 0);
437 fsl_ifc_run_command(mtd);
438 return;
Prabhakar Kushwahaf31cf532012-04-08 18:57:18 +0000439 }
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530440
441 /* ERASE1 stores the block and page address */
442 case NAND_CMD_ERASE1:
443 set_addr(mtd, 0, page_addr, 0);
444 return;
445
446 /* ERASE2 uses the block and page address from ERASE1 */
447 case NAND_CMD_ERASE2:
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530448 ifc_out32(&ifc->ifc_nand.nand_fir0,
449 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
450 (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP1_SHIFT) |
451 (IFC_FIR_OP_CMD1 << IFC_NAND_FIR0_OP2_SHIFT));
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530452
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530453 ifc_out32(&ifc->ifc_nand.nand_fcr0,
454 (NAND_CMD_ERASE1 << IFC_NAND_FCR0_CMD0_SHIFT) |
455 (NAND_CMD_ERASE2 << IFC_NAND_FCR0_CMD1_SHIFT));
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530456
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530457 ifc_out32(&ifc->ifc_nand.nand_fbcr, 0);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530458 ctrl->read_bytes = 0;
459 fsl_ifc_run_command(mtd);
460 return;
461
462 /* SEQIN sets up the addr buffer and all registers except the length */
463 case NAND_CMD_SEQIN: {
464 u32 nand_fcr0;
465 ctrl->column = column;
466 ctrl->oob = 0;
467
468 if (mtd->writesize > 512) {
469 nand_fcr0 =
470 (NAND_CMD_SEQIN << IFC_NAND_FCR0_CMD0_SHIFT) |
Prabhakar Kushwaha18e6bde2013-10-03 11:35:35 +0530471 (NAND_CMD_STATUS << IFC_NAND_FCR0_CMD1_SHIFT) |
472 (NAND_CMD_PAGEPROG << IFC_NAND_FCR0_CMD2_SHIFT);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530473
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530474 ifc_out32(&ifc->ifc_nand.nand_fir0,
475 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
476 (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP1_SHIFT) |
477 (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP2_SHIFT) |
478 (IFC_FIR_OP_WBCD <<
479 IFC_NAND_FIR0_OP3_SHIFT) |
480 (IFC_FIR_OP_CMD2 << IFC_NAND_FIR0_OP4_SHIFT));
481 ifc_out32(&ifc->ifc_nand.nand_fir1,
482 (IFC_FIR_OP_CW1 << IFC_NAND_FIR1_OP5_SHIFT) |
483 (IFC_FIR_OP_RDSTAT <<
Prabhakar Kushwaha18e6bde2013-10-03 11:35:35 +0530484 IFC_NAND_FIR1_OP6_SHIFT) |
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530485 (IFC_FIR_OP_NOP << IFC_NAND_FIR1_OP7_SHIFT));
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530486 } else {
487 nand_fcr0 = ((NAND_CMD_PAGEPROG <<
488 IFC_NAND_FCR0_CMD1_SHIFT) |
489 (NAND_CMD_SEQIN <<
Prabhakar Kushwaha18e6bde2013-10-03 11:35:35 +0530490 IFC_NAND_FCR0_CMD2_SHIFT) |
491 (NAND_CMD_STATUS <<
492 IFC_NAND_FCR0_CMD3_SHIFT));
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530493
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530494 ifc_out32(&ifc->ifc_nand.nand_fir0,
495 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
496 (IFC_FIR_OP_CMD2 << IFC_NAND_FIR0_OP1_SHIFT) |
497 (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP2_SHIFT) |
498 (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP3_SHIFT) |
499 (IFC_FIR_OP_WBCD << IFC_NAND_FIR0_OP4_SHIFT));
500 ifc_out32(&ifc->ifc_nand.nand_fir1,
501 (IFC_FIR_OP_CMD1 << IFC_NAND_FIR1_OP5_SHIFT) |
502 (IFC_FIR_OP_CW3 << IFC_NAND_FIR1_OP6_SHIFT) |
503 (IFC_FIR_OP_RDSTAT <<
Prabhakar Kushwaha18e6bde2013-10-03 11:35:35 +0530504 IFC_NAND_FIR1_OP7_SHIFT) |
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530505 (IFC_FIR_OP_NOP << IFC_NAND_FIR1_OP8_SHIFT));
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530506
Prabhakar Kushwaha0ed5e772012-01-20 18:39:05 +0530507 if (column >= mtd->writesize)
508 nand_fcr0 |=
509 NAND_CMD_READOOB << IFC_NAND_FCR0_CMD0_SHIFT;
510 else
511 nand_fcr0 |=
512 NAND_CMD_READ0 << IFC_NAND_FCR0_CMD0_SHIFT;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530513 }
514
Prabhakar Kushwaha0ed5e772012-01-20 18:39:05 +0530515 if (column >= mtd->writesize) {
516 /* OOB area --> READOOB */
517 column -= mtd->writesize;
518 ctrl->oob = 1;
519 }
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530520 ifc_out32(&ifc->ifc_nand.nand_fcr0, nand_fcr0);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530521 set_addr(mtd, column, page_addr, ctrl->oob);
522 return;
523 }
524
525 /* PAGEPROG reuses all of the setup from SEQIN and adds the length */
526 case NAND_CMD_PAGEPROG:
527 if (ctrl->oob)
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530528 ifc_out32(&ifc->ifc_nand.nand_fbcr,
529 ctrl->index - ctrl->column);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530530 else
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530531 ifc_out32(&ifc->ifc_nand.nand_fbcr, 0);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530532
533 fsl_ifc_run_command(mtd);
534 return;
535
536 case NAND_CMD_STATUS:
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530537 ifc_out32(&ifc->ifc_nand.nand_fir0,
538 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
539 (IFC_FIR_OP_RB << IFC_NAND_FIR0_OP1_SHIFT));
540 ifc_out32(&ifc->ifc_nand.nand_fcr0,
541 NAND_CMD_STATUS << IFC_NAND_FCR0_CMD0_SHIFT);
542 ifc_out32(&ifc->ifc_nand.nand_fbcr, 1);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530543 set_addr(mtd, 0, 0, 0);
544 ctrl->read_bytes = 1;
545
546 fsl_ifc_run_command(mtd);
547
Scott Wood3ea94ed2015-06-26 19:03:26 -0500548 /*
549 * The chip always seems to report that it is
550 * write-protected, even when it is not.
551 */
552 if (chip->options & NAND_BUSWIDTH_16)
553 ifc_out16(ctrl->addr,
554 ifc_in16(ctrl->addr) | NAND_STATUS_WP);
555 else
556 out_8(ctrl->addr, in_8(ctrl->addr) | NAND_STATUS_WP);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530557 return;
558
559 case NAND_CMD_RESET:
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530560 ifc_out32(&ifc->ifc_nand.nand_fir0,
561 IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT);
562 ifc_out32(&ifc->ifc_nand.nand_fcr0,
563 NAND_CMD_RESET << IFC_NAND_FCR0_CMD0_SHIFT);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530564 fsl_ifc_run_command(mtd);
565 return;
566
567 default:
568 printf("%s: error, unsupported command 0x%x.\n",
569 __func__, command);
570 }
571}
572
573/*
574 * Write buf to the IFC NAND Controller Data Buffer
575 */
576static void fsl_ifc_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
577{
Scott Wood17fed142016-05-30 13:57:56 -0500578 struct nand_chip *chip = mtd_to_nand(mtd);
579 struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530580 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
581 unsigned int bufsize = mtd->writesize + mtd->oobsize;
582
583 if (len <= 0) {
584 printf("%s of %d bytes", __func__, len);
585 ctrl->status = 0;
586 return;
587 }
588
589 if ((unsigned int)len > bufsize - ctrl->index) {
590 printf("%s beyond end of buffer "
591 "(%d requested, %u available)\n",
592 __func__, len, bufsize - ctrl->index);
593 len = bufsize - ctrl->index;
594 }
595
Scott Wood3ea94ed2015-06-26 19:03:26 -0500596 memcpy_toio(ctrl->addr + ctrl->index, buf, len);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530597 ctrl->index += len;
598}
599
600/*
601 * read a byte from either the IFC hardware buffer if it has any data left
602 * otherwise issue a command to read a single byte.
603 */
604static u8 fsl_ifc_read_byte(struct mtd_info *mtd)
605{
Scott Wood17fed142016-05-30 13:57:56 -0500606 struct nand_chip *chip = mtd_to_nand(mtd);
607 struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530608 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
Scott Wood3ea94ed2015-06-26 19:03:26 -0500609 unsigned int offset;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530610
Scott Wood3ea94ed2015-06-26 19:03:26 -0500611 /*
612 * If there are still bytes in the IFC buffer, then use the
613 * next byte.
614 */
615 if (ctrl->index < ctrl->read_bytes) {
616 offset = ctrl->index++;
617 return in_8(ctrl->addr + offset);
618 }
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530619
620 printf("%s beyond end of buffer\n", __func__);
621 return ERR_BYTE;
622}
623
624/*
625 * Read two bytes from the IFC hardware buffer
626 * read function for 16-bit buswith
627 */
628static uint8_t fsl_ifc_read_byte16(struct mtd_info *mtd)
629{
Scott Wood17fed142016-05-30 13:57:56 -0500630 struct nand_chip *chip = mtd_to_nand(mtd);
631 struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530632 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
633 uint16_t data;
634
635 /*
636 * If there are still bytes in the IFC buffer, then use the
637 * next byte.
638 */
639 if (ctrl->index < ctrl->read_bytes) {
Scott Wood3ea94ed2015-06-26 19:03:26 -0500640 data = ifc_in16(ctrl->addr + ctrl->index);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530641 ctrl->index += 2;
642 return (uint8_t)data;
643 }
644
645 printf("%s beyond end of buffer\n", __func__);
646 return ERR_BYTE;
647}
648
649/*
650 * Read from the IFC Controller Data Buffer
651 */
652static void fsl_ifc_read_buf(struct mtd_info *mtd, u8 *buf, int len)
653{
Scott Wood17fed142016-05-30 13:57:56 -0500654 struct nand_chip *chip = mtd_to_nand(mtd);
655 struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530656 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
657 int avail;
658
659 if (len < 0)
660 return;
661
662 avail = min((unsigned int)len, ctrl->read_bytes - ctrl->index);
Scott Wood3ea94ed2015-06-26 19:03:26 -0500663 memcpy_fromio(buf, ctrl->addr + ctrl->index, avail);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530664 ctrl->index += avail;
665
666 if (len > avail)
667 printf("%s beyond end of buffer "
668 "(%d requested, %d available)\n",
669 __func__, len, avail);
670}
671
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530672/* This function is called after Program and Erase Operations to
673 * check for success or failure.
674 */
675static int fsl_ifc_wait(struct mtd_info *mtd, struct nand_chip *chip)
676{
Scott Wood17fed142016-05-30 13:57:56 -0500677 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;
Jaiprakash Singhdd888062015-03-20 19:28:27 -0700679 struct fsl_ifc_runtime *ifc = ctrl->regs.rregs;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530680 u32 nand_fsr;
Jagdish Gediya997f04a2018-05-02 01:20:57 +0530681 int status;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530682
683 if (ctrl->status != IFC_NAND_EVTER_STAT_OPC)
684 return NAND_STATUS_FAIL;
685
686 /* Use READ_STATUS command, but wait for the device to be ready */
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530687 ifc_out32(&ifc->ifc_nand.nand_fir0,
688 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
689 (IFC_FIR_OP_RDSTAT << IFC_NAND_FIR0_OP1_SHIFT));
690 ifc_out32(&ifc->ifc_nand.nand_fcr0, NAND_CMD_STATUS <<
691 IFC_NAND_FCR0_CMD0_SHIFT);
692 ifc_out32(&ifc->ifc_nand.nand_fbcr, 1);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530693 set_addr(mtd, 0, 0, 0);
694 ctrl->read_bytes = 1;
695
696 fsl_ifc_run_command(mtd);
697
698 if (ctrl->status != IFC_NAND_EVTER_STAT_OPC)
699 return NAND_STATUS_FAIL;
700
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530701 nand_fsr = ifc_in32(&ifc->ifc_nand.nand_fsr);
Jagdish Gediya997f04a2018-05-02 01:20:57 +0530702 status = nand_fsr >> 24;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530703
704 /* Chip sometimes reporting write protect even when it's not */
Jagdish Gediya997f04a2018-05-02 01:20:57 +0530705 return status | NAND_STATUS_WP;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530706}
707
Darwin Dingel3dae7e62018-08-02 10:02:45 +0200708/*
709 * The controller does not check for bitflips in erased pages,
710 * therefore software must check instead.
711 */
712static int
713check_erased_page(struct nand_chip *chip, u8 *buf, struct mtd_info *mtd)
714{
715 u8 *ecc = chip->oob_poi;
716 const int ecc_size = chip->ecc.bytes;
717 const int pkt_size = chip->ecc.size;
718 int i, res, bitflips;
719
720 /* IFC starts ecc bytes at offset 8 in the spare area. */
721 ecc += 8;
722 bitflips = 0;
723 for (i = 0; i < chip->ecc.steps; i++) {
724 res = nand_check_erased_ecc_chunk(buf, pkt_size, ecc, ecc_size,
725 NULL, 0, chip->ecc.strength);
726
727 if (res < 0) {
728 printf("fsl-ifc: NAND Flash ECC Uncorrectable Error\n");
729 mtd->ecc_stats.failed++;
730 } else if (res > 0) {
731 mtd->ecc_stats.corrected += res;
732 }
733 bitflips = max(res, bitflips);
734 buf += pkt_size;
735 ecc += ecc_size;
736 }
737
738 return bitflips;
739}
740
Sergey Lapin3a38a552013-01-14 03:46:50 +0000741static int fsl_ifc_read_page(struct mtd_info *mtd, struct nand_chip *chip,
742 uint8_t *buf, int oob_required, int page)
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530743{
Scott Wood17fed142016-05-30 13:57:56 -0500744 struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530745 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
746
747 fsl_ifc_read_buf(mtd, buf, mtd->writesize);
748 fsl_ifc_read_buf(mtd, chip->oob_poi, mtd->oobsize);
749
Darwin Dingel3dae7e62018-08-02 10:02:45 +0200750 if (ctrl->status & IFC_NAND_EVTER_STAT_ECCER)
751 return check_erased_page(chip, buf, mtd);
752
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530753 if (ctrl->status != IFC_NAND_EVTER_STAT_OPC)
754 mtd->ecc_stats.failed++;
755
756 return 0;
757}
758
759/* ECC will be calculated automatically, and errors will be detected in
760 * waitfunc.
761 */
Sergey Lapin3a38a552013-01-14 03:46:50 +0000762static int fsl_ifc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
Scott Wood46e13102016-05-30 13:57:57 -0500763 const uint8_t *buf, int oob_required, int page)
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530764{
765 fsl_ifc_write_buf(mtd, buf, mtd->writesize);
766 fsl_ifc_write_buf(mtd, chip->oob_poi, mtd->oobsize);
Sergey Lapin3a38a552013-01-14 03:46:50 +0000767
768 return 0;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530769}
770
771static void fsl_ifc_ctrl_init(void)
772{
Jaiprakash Singhdd888062015-03-20 19:28:27 -0700773 uint32_t ver = 0;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530774 ifc_ctrl = kzalloc(sizeof(*ifc_ctrl), GFP_KERNEL);
775 if (!ifc_ctrl)
776 return;
777
Jaiprakash Singhdd888062015-03-20 19:28:27 -0700778 ifc_ctrl->regs.gregs = IFC_FCM_BASE_ADDR;
779
780 ver = ifc_in32(&ifc_ctrl->regs.gregs->ifc_rev);
781 if (ver >= FSL_IFC_V2_0_0)
782 ifc_ctrl->regs.rregs =
783 (void *)CONFIG_SYS_IFC_ADDR + IFC_RREGS_64KOFFSET;
784 else
785 ifc_ctrl->regs.rregs =
786 (void *)CONFIG_SYS_IFC_ADDR + IFC_RREGS_4KOFFSET;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530787
788 /* clear event registers */
Jaiprakash Singhdd888062015-03-20 19:28:27 -0700789 ifc_out32(&ifc_ctrl->regs.rregs->ifc_nand.nand_evter_stat, ~0U);
790 ifc_out32(&ifc_ctrl->regs.rregs->ifc_nand.pgrdcmpl_evt_stat, ~0U);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530791
792 /* Enable error and event for any detected errors */
Jaiprakash Singhdd888062015-03-20 19:28:27 -0700793 ifc_out32(&ifc_ctrl->regs.rregs->ifc_nand.nand_evter_en,
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530794 IFC_NAND_EVTER_EN_OPC_EN |
795 IFC_NAND_EVTER_EN_PGRDCMPL_EN |
796 IFC_NAND_EVTER_EN_FTOER_EN |
797 IFC_NAND_EVTER_EN_WPER_EN);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530798
Jaiprakash Singhdd888062015-03-20 19:28:27 -0700799 ifc_out32(&ifc_ctrl->regs.rregs->ifc_nand.ncfgr, 0x0);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530800}
801
802static void fsl_ifc_select_chip(struct mtd_info *mtd, int chip)
803{
804}
805
Kurt Kanzenbach1f161f82017-10-20 11:44:25 +0200806static int fsl_ifc_sram_init(struct fsl_ifc_mtd *priv, uint32_t ver)
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000807{
Jaiprakash Singhdd888062015-03-20 19:28:27 -0700808 struct fsl_ifc_runtime *ifc = ifc_ctrl->regs.rregs;
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000809 uint32_t cs = 0, csor = 0, csor_8k = 0, csor_ext = 0;
Prabhakar Kushwaha82efc812014-06-12 12:14:00 +0530810 uint32_t ncfgr = 0;
Prabhakar Kushwahad7550e12014-09-23 09:57:47 +0530811 u32 timeo = (CONFIG_SYS_HZ * 10) / 1000;
812 u32 time_start;
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000813
Prabhakar Kushwaha82efc812014-06-12 12:14:00 +0530814 if (ver > FSL_IFC_V1_1_0) {
815 ncfgr = ifc_in32(&ifc->ifc_nand.ncfgr);
816 ifc_out32(&ifc->ifc_nand.ncfgr, ncfgr | IFC_NAND_SRAM_INIT_EN);
817
818 /* wait for SRAM_INIT bit to be clear or timeout */
Prabhakar Kushwahad7550e12014-09-23 09:57:47 +0530819 time_start = get_timer(0);
820 while (get_timer(time_start) < timeo) {
Prabhakar Kushwaha82efc812014-06-12 12:14:00 +0530821 ifc_ctrl->status =
822 ifc_in32(&ifc->ifc_nand.nand_evter_stat);
823
824 if (!(ifc_ctrl->status & IFC_NAND_SRAM_INIT_EN))
825 return 0;
826 }
827 printf("fsl-ifc: Failed to Initialise SRAM\n");
828 return 1;
829 }
830
Kurt Kanzenbach1f161f82017-10-20 11:44:25 +0200831 cs = priv->bank;
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000832
833 /* Save CSOR and CSOR_ext */
Jaiprakash Singhdd888062015-03-20 19:28:27 -0700834 csor = ifc_in32(&ifc_ctrl->regs.gregs->csor_cs[cs].csor);
835 csor_ext = ifc_in32(&ifc_ctrl->regs.gregs->csor_cs[cs].csor_ext);
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000836
837 /* chage PageSize 8K and SpareSize 1K*/
838 csor_8k = (csor & ~(CSOR_NAND_PGS_MASK)) | 0x0018C000;
Jaiprakash Singhdd888062015-03-20 19:28:27 -0700839 ifc_out32(&ifc_ctrl->regs.gregs->csor_cs[cs].csor, csor_8k);
840 ifc_out32(&ifc_ctrl->regs.gregs->csor_cs[cs].csor_ext, 0x0000400);
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000841
842 /* READID */
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530843 ifc_out32(&ifc->ifc_nand.nand_fir0,
844 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
845 (IFC_FIR_OP_UA << IFC_NAND_FIR0_OP1_SHIFT) |
846 (IFC_FIR_OP_RB << IFC_NAND_FIR0_OP2_SHIFT));
847 ifc_out32(&ifc->ifc_nand.nand_fcr0,
848 NAND_CMD_READID << IFC_NAND_FCR0_CMD0_SHIFT);
849 ifc_out32(&ifc->ifc_nand.row3, 0x0);
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000850
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530851 ifc_out32(&ifc->ifc_nand.nand_fbcr, 0x0);
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000852
853 /* Program ROW0/COL0 */
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530854 ifc_out32(&ifc->ifc_nand.row0, 0x0);
855 ifc_out32(&ifc->ifc_nand.col0, 0x0);
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000856
857 /* set the chip select for NAND Transaction */
Kurt Kanzenbach1f161f82017-10-20 11:44:25 +0200858 ifc_out32(&ifc->ifc_nand.nand_csel, priv->bank << IFC_NAND_CSEL_SHIFT);
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000859
860 /* start read seq */
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530861 ifc_out32(&ifc->ifc_nand.nandseq_strt, IFC_NAND_SEQ_STRT_FIR_STRT);
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000862
Prabhakar Kushwahad7550e12014-09-23 09:57:47 +0530863 time_start = get_timer(0);
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000864
Prabhakar Kushwahad7550e12014-09-23 09:57:47 +0530865 while (get_timer(time_start) < timeo) {
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530866 ifc_ctrl->status = ifc_in32(&ifc->ifc_nand.nand_evter_stat);
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000867
868 if (ifc_ctrl->status & IFC_NAND_EVTER_STAT_OPC)
869 break;
870 }
871
Prabhakar Kushwaha82efc812014-06-12 12:14:00 +0530872 if (ifc_ctrl->status != IFC_NAND_EVTER_STAT_OPC) {
873 printf("fsl-ifc: Failed to Initialise SRAM\n");
874 return 1;
875 }
876
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530877 ifc_out32(&ifc->ifc_nand.nand_evter_stat, ifc_ctrl->status);
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000878
879 /* Restore CSOR and CSOR_ext */
Jaiprakash Singhdd888062015-03-20 19:28:27 -0700880 ifc_out32(&ifc_ctrl->regs.gregs->csor_cs[cs].csor, csor);
881 ifc_out32(&ifc_ctrl->regs.gregs->csor_cs[cs].csor_ext, csor_ext);
Prabhakar Kushwaha82efc812014-06-12 12:14:00 +0530882
883 return 0;
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000884}
885
Prabhakar Kushwaha895d0392013-04-04 18:44:06 +0000886static int fsl_ifc_chip_init(int devnum, u8 *addr)
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530887{
Scott Wood2c1b7e12016-05-30 13:57:55 -0500888 struct mtd_info *mtd;
Prabhakar Kushwaha895d0392013-04-04 18:44:06 +0000889 struct nand_chip *nand;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530890 struct fsl_ifc_mtd *priv;
891 struct nand_ecclayout *layout;
Jaiprakash Singhdd888062015-03-20 19:28:27 -0700892 struct fsl_ifc_fcm *gregs = NULL;
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000893 uint32_t cspr = 0, csor = 0, ver = 0;
Prabhakar Kushwaha82efc812014-06-12 12:14:00 +0530894 int ret = 0;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530895
896 if (!ifc_ctrl) {
897 fsl_ifc_ctrl_init();
898 if (!ifc_ctrl)
899 return -1;
900 }
901
902 priv = kzalloc(sizeof(*priv), GFP_KERNEL);
903 if (!priv)
904 return -ENOMEM;
905
906 priv->ctrl = ifc_ctrl;
Prabhakar Kushwaha895d0392013-04-04 18:44:06 +0000907 priv->vbase = addr;
Jaiprakash Singhdd888062015-03-20 19:28:27 -0700908 gregs = ifc_ctrl->regs.gregs;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530909
910 /* Find which chip select it is connected to.
911 */
912 for (priv->bank = 0; priv->bank < MAX_BANKS; priv->bank++) {
Prabhakar Kushwaha895d0392013-04-04 18:44:06 +0000913 phys_addr_t phys_addr = virt_to_phys(addr);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530914
Jaiprakash Singhdd888062015-03-20 19:28:27 -0700915 cspr = ifc_in32(&gregs->cspr_cs[priv->bank].cspr);
916 csor = ifc_in32(&gregs->csor_cs[priv->bank].csor);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530917
918 if ((cspr & CSPR_V) && (cspr & CSPR_MSEL) == CSPR_MSEL_NAND &&
Kurt Kanzenbach1f161f82017-10-20 11:44:25 +0200919 (cspr & CSPR_BA) == CSPR_PHYS_ADDR(phys_addr))
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530920 break;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530921 }
922
923 if (priv->bank >= MAX_BANKS) {
924 printf("%s: address did not match any "
925 "chip selects\n", __func__);
Prabhakar Kushwahaae25e882012-04-10 22:48:27 +0000926 kfree(priv);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530927 return -ENODEV;
928 }
929
Prabhakar Kushwaha895d0392013-04-04 18:44:06 +0000930 nand = &priv->chip;
Scott Wood17fed142016-05-30 13:57:56 -0500931 mtd = nand_to_mtd(nand);
Prabhakar Kushwaha895d0392013-04-04 18:44:06 +0000932
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530933 ifc_ctrl->chips[priv->bank] = priv;
934
935 /* fill in nand_chip structure */
936 /* set up function call table */
937
938 nand->write_buf = fsl_ifc_write_buf;
939 nand->read_buf = fsl_ifc_read_buf;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530940 nand->select_chip = fsl_ifc_select_chip;
941 nand->cmdfunc = fsl_ifc_cmdfunc;
942 nand->waitfunc = fsl_ifc_wait;
943
944 /* set up nand options */
945 nand->bbt_td = &bbt_main_descr;
946 nand->bbt_md = &bbt_mirror_descr;
947
948 /* set up nand options */
Sergey Lapin3a38a552013-01-14 03:46:50 +0000949 nand->options = NAND_NO_SUBPAGE_WRITE;
950 nand->bbt_options = NAND_BBT_USE_FLASH;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530951
952 if (cspr & CSPR_PORT_SIZE_16) {
953 nand->read_byte = fsl_ifc_read_byte16;
954 nand->options |= NAND_BUSWIDTH_16;
955 } else {
956 nand->read_byte = fsl_ifc_read_byte;
957 }
958
959 nand->controller = &ifc_ctrl->controller;
Scott Wood17fed142016-05-30 13:57:56 -0500960 nand_set_controller_data(nand, priv);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530961
962 nand->ecc.read_page = fsl_ifc_read_page;
963 nand->ecc.write_page = fsl_ifc_write_page;
964
965 /* Hardware generates ECC per 512 Bytes */
966 nand->ecc.size = 512;
967 nand->ecc.bytes = 8;
968
969 switch (csor & CSOR_NAND_PGS_MASK) {
970 case CSOR_NAND_PGS_512:
971 if (nand->options & NAND_BUSWIDTH_16) {
972 layout = &oob_512_16bit_ecc4;
973 } else {
974 layout = &oob_512_8bit_ecc4;
975
976 /* Avoid conflict with bad block marker */
977 bbt_main_descr.offs = 0;
978 bbt_mirror_descr.offs = 0;
979 }
980
Sergey Lapin3a38a552013-01-14 03:46:50 +0000981 nand->ecc.strength = 4;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530982 priv->bufnum_mask = 15;
983 break;
984
985 case CSOR_NAND_PGS_2K:
986 layout = &oob_2048_ecc4;
Sergey Lapin3a38a552013-01-14 03:46:50 +0000987 nand->ecc.strength = 4;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530988 priv->bufnum_mask = 3;
989 break;
990
991 case CSOR_NAND_PGS_4K:
992 if ((csor & CSOR_NAND_ECC_MODE_MASK) ==
993 CSOR_NAND_ECC_MODE_4) {
994 layout = &oob_4096_ecc4;
Sergey Lapin3a38a552013-01-14 03:46:50 +0000995 nand->ecc.strength = 4;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530996 } else {
997 layout = &oob_4096_ecc8;
Sergey Lapin3a38a552013-01-14 03:46:50 +0000998 nand->ecc.strength = 8;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530999 nand->ecc.bytes = 16;
1000 }
1001
1002 priv->bufnum_mask = 1;
1003 break;
1004
Prabhakar Kushwahaa3aaf1d2013-10-04 10:05:36 +05301005 case CSOR_NAND_PGS_8K:
1006 if ((csor & CSOR_NAND_ECC_MODE_MASK) ==
1007 CSOR_NAND_ECC_MODE_4) {
1008 layout = &oob_8192_ecc4;
1009 nand->ecc.strength = 4;
1010 } else {
1011 layout = &oob_8192_ecc8;
1012 nand->ecc.strength = 8;
1013 nand->ecc.bytes = 16;
1014 }
1015
1016 priv->bufnum_mask = 0;
1017 break;
1018
1019
Dipen Dudhat9eae0832011-03-22 09:27:39 +05301020 default:
1021 printf("ifc nand: bad csor %#x: bad page size\n", csor);
1022 return -ENODEV;
1023 }
1024
1025 /* Must also set CSOR_NAND_ECC_ENC_EN if DEC_EN set */
1026 if (csor & CSOR_NAND_ECC_DEC_EN) {
1027 nand->ecc.mode = NAND_ECC_HW;
1028 nand->ecc.layout = layout;
1029 } else {
1030 nand->ecc.mode = NAND_ECC_SOFT;
1031 }
1032
Jaiprakash Singhdd888062015-03-20 19:28:27 -07001033 ver = ifc_in32(&gregs->ifc_rev);
Prabhakar Kushwaha82efc812014-06-12 12:14:00 +05301034 if (ver >= FSL_IFC_V1_1_0)
Kurt Kanzenbach1f161f82017-10-20 11:44:25 +02001035 ret = fsl_ifc_sram_init(priv, ver);
Prabhakar Kushwaha82efc812014-06-12 12:14:00 +05301036 if (ret)
1037 return ret;
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +00001038
Prabhakar Kushwaha5c23a822014-06-14 08:48:19 +05301039 if (ver >= FSL_IFC_V2_0_0)
1040 priv->bufnum_mask = (priv->bufnum_mask * 2) + 1;
1041
Prabhakar Kushwaha895d0392013-04-04 18:44:06 +00001042 ret = nand_scan_ident(mtd, 1, NULL);
1043 if (ret)
1044 return ret;
1045
1046 ret = nand_scan_tail(mtd);
1047 if (ret)
1048 return ret;
1049
Scott Wood2c1b7e12016-05-30 13:57:55 -05001050 ret = nand_register(devnum, mtd);
Prabhakar Kushwaha895d0392013-04-04 18:44:06 +00001051 if (ret)
1052 return ret;
Dipen Dudhat9eae0832011-03-22 09:27:39 +05301053 return 0;
1054}
Prabhakar Kushwaha895d0392013-04-04 18:44:06 +00001055
1056#ifndef CONFIG_SYS_NAND_BASE_LIST
1057#define CONFIG_SYS_NAND_BASE_LIST { CONFIG_SYS_NAND_BASE }
1058#endif
1059
1060static unsigned long base_address[CONFIG_SYS_MAX_NAND_DEVICE] =
1061 CONFIG_SYS_NAND_BASE_LIST;
1062
1063void board_nand_init(void)
1064{
1065 int i;
1066
1067 for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++)
1068 fsl_ifc_chip_init(i, (u8 *)base_address[i]);
1069}