blob: 29f30d8ccc42a112196434b0bf83def95923c9ce [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
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530245/* returns nonzero if entire page is blank */
246static int check_read_ecc(struct mtd_info *mtd, struct fsl_ifc_ctrl *ctrl,
Jagdish Gediya83fbe912018-03-24 02:55:51 +0530247 u32 eccstat, unsigned int bufnum)
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530248{
Jagdish Gediya83fbe912018-03-24 02:55:51 +0530249 return (eccstat >> ((3 - bufnum % 4) * 8)) & 15;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530250}
251
252/*
253 * execute IFC NAND command and wait for it to complete
254 */
255static int fsl_ifc_run_command(struct mtd_info *mtd)
256{
Scott Wood17fed142016-05-30 13:57:56 -0500257 struct nand_chip *chip = mtd_to_nand(mtd);
258 struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530259 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
Jaiprakash Singhdd888062015-03-20 19:28:27 -0700260 struct fsl_ifc_runtime *ifc = ctrl->regs.rregs;
Prabhakar Kushwahad7550e12014-09-23 09:57:47 +0530261 u32 timeo = (CONFIG_SYS_HZ * 10) / 1000;
262 u32 time_start;
Jagdish Gediya83fbe912018-03-24 02:55:51 +0530263 u32 eccstat;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530264 int i;
265
266 /* set the chip select for NAND Transaction */
Kurt Kanzenbach1f161f82017-10-20 11:44:25 +0200267 ifc_out32(&ifc->ifc_nand.nand_csel, priv->bank << IFC_NAND_CSEL_SHIFT);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530268
269 /* start read/write seq */
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530270 ifc_out32(&ifc->ifc_nand.nandseq_strt,
271 IFC_NAND_SEQ_STRT_FIR_STRT);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530272
273 /* wait for NAND Machine complete flag or timeout */
Prabhakar Kushwahad7550e12014-09-23 09:57:47 +0530274 time_start = get_timer(0);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530275
Prabhakar Kushwahad7550e12014-09-23 09:57:47 +0530276 while (get_timer(time_start) < timeo) {
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530277 ctrl->status = ifc_in32(&ifc->ifc_nand.nand_evter_stat);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530278
279 if (ctrl->status & IFC_NAND_EVTER_STAT_OPC)
280 break;
281 }
282
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530283 ifc_out32(&ifc->ifc_nand.nand_evter_stat, ctrl->status);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530284
285 if (ctrl->status & IFC_NAND_EVTER_STAT_FTOER)
286 printf("%s: Flash Time Out Error\n", __func__);
287 if (ctrl->status & IFC_NAND_EVTER_STAT_WPER)
288 printf("%s: Write Protect Error\n", __func__);
289
290 if (ctrl->eccread) {
Prabhakar Kushwahacdd045d2012-01-20 18:38:14 +0530291 int errors;
292 int bufnum = ctrl->page & priv->bufnum_mask;
Jagdish Gediya83fbe912018-03-24 02:55:51 +0530293 int sector_start = bufnum * chip->ecc.steps;
294 int sector_end = sector_start + chip->ecc.steps - 1;
295 u32 *eccstat_regs;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530296
Jagdish Gediya83fbe912018-03-24 02:55:51 +0530297 eccstat_regs = ifc->ifc_nand.nand_eccstat;
298 eccstat = ifc_in32(&eccstat_regs[sector_start / 4]);
Scott Wood70365492015-03-19 09:20:49 -0700299
Jagdish Gediya83fbe912018-03-24 02:55:51 +0530300 for (i = sector_start; i <= sector_end; i++) {
301 if ((i != sector_start) && !(i % 4))
302 eccstat = ifc_in32(&eccstat_regs[i / 4]);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530303
Prabhakar Kushwahacdd045d2012-01-20 18:38:14 +0530304 errors = check_read_ecc(mtd, ctrl, eccstat, i);
305
306 if (errors == 15) {
307 /*
308 * Uncorrectable error.
Darwin Dingel3dae7e62018-08-02 10:02:45 +0200309 * We'll check for blank pages later.
Prabhakar Kushwahacdd045d2012-01-20 18:38:14 +0530310 *
311 * We disable ECCER reporting due to erratum
312 * IFC-A002770 -- so report it now if we
313 * see an uncorrectable error in ECCSTAT.
314 */
Darwin Dingel3dae7e62018-08-02 10:02:45 +0200315 ctrl->status |= IFC_NAND_EVTER_STAT_ECCER;
316 continue;
Prabhakar Kushwahacdd045d2012-01-20 18:38:14 +0530317 }
318
319 mtd->ecc_stats.corrected += errors;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530320 }
321
322 ctrl->eccread = 0;
323 }
324
325 /* returns 0 on success otherwise non-zero) */
326 return ctrl->status == IFC_NAND_EVTER_STAT_OPC ? 0 : -EIO;
327}
328
329static void fsl_ifc_do_read(struct nand_chip *chip,
330 int oob,
331 struct mtd_info *mtd)
332{
Scott Wood17fed142016-05-30 13:57:56 -0500333 struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530334 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
Jaiprakash Singhdd888062015-03-20 19:28:27 -0700335 struct fsl_ifc_runtime *ifc = ctrl->regs.rregs;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530336
337 /* Program FIR/IFC_NAND_FCR0 for Small/Large page */
338 if (mtd->writesize > 512) {
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530339 ifc_out32(&ifc->ifc_nand.nand_fir0,
340 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
341 (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP1_SHIFT) |
342 (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP2_SHIFT) |
343 (IFC_FIR_OP_CMD1 << IFC_NAND_FIR0_OP3_SHIFT) |
344 (IFC_FIR_OP_RBCD << IFC_NAND_FIR0_OP4_SHIFT));
345 ifc_out32(&ifc->ifc_nand.nand_fir1, 0x0);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530346
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530347 ifc_out32(&ifc->ifc_nand.nand_fcr0,
348 (NAND_CMD_READ0 << IFC_NAND_FCR0_CMD0_SHIFT) |
349 (NAND_CMD_READSTART << IFC_NAND_FCR0_CMD1_SHIFT));
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530350 } else {
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530351 ifc_out32(&ifc->ifc_nand.nand_fir0,
352 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
353 (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP1_SHIFT) |
354 (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP2_SHIFT) |
355 (IFC_FIR_OP_RBCD << IFC_NAND_FIR0_OP3_SHIFT));
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530356
357 if (oob)
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530358 ifc_out32(&ifc->ifc_nand.nand_fcr0,
359 NAND_CMD_READOOB << IFC_NAND_FCR0_CMD0_SHIFT);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530360 else
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530361 ifc_out32(&ifc->ifc_nand.nand_fcr0,
362 NAND_CMD_READ0 << IFC_NAND_FCR0_CMD0_SHIFT);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530363 }
364}
365
366/* cmdfunc send commands to the IFC NAND Machine */
367static void fsl_ifc_cmdfunc(struct mtd_info *mtd, unsigned int command,
368 int column, int page_addr)
369{
Scott Wood17fed142016-05-30 13:57:56 -0500370 struct nand_chip *chip = mtd_to_nand(mtd);
371 struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530372 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
Jaiprakash Singhdd888062015-03-20 19:28:27 -0700373 struct fsl_ifc_runtime *ifc = ctrl->regs.rregs;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530374
375 /* clear the read buffer */
376 ctrl->read_bytes = 0;
377 if (command != NAND_CMD_PAGEPROG)
378 ctrl->index = 0;
379
380 switch (command) {
381 /* READ0 read the entire buffer to use hardware ECC. */
382 case NAND_CMD_READ0: {
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530383 ifc_out32(&ifc->ifc_nand.nand_fbcr, 0);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530384 set_addr(mtd, 0, page_addr, 0);
385
386 ctrl->read_bytes = mtd->writesize + mtd->oobsize;
387 ctrl->index += column;
388
389 if (chip->ecc.mode == NAND_ECC_HW)
390 ctrl->eccread = 1;
391
392 fsl_ifc_do_read(chip, 0, mtd);
393 fsl_ifc_run_command(mtd);
394 return;
395 }
396
397 /* READOOB reads only the OOB because no ECC is performed. */
398 case NAND_CMD_READOOB:
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530399 ifc_out32(&ifc->ifc_nand.nand_fbcr, mtd->oobsize - column);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530400 set_addr(mtd, column, page_addr, 1);
401
402 ctrl->read_bytes = mtd->writesize + mtd->oobsize;
403
404 fsl_ifc_do_read(chip, 1, mtd);
405 fsl_ifc_run_command(mtd);
406
407 return;
408
409 /* READID must read all possible bytes while CEB is active */
410 case NAND_CMD_READID:
Prabhakar Kushwahaf31cf532012-04-08 18:57:18 +0000411 case NAND_CMD_PARAM: {
412 int timing = IFC_FIR_OP_RB;
413 if (command == NAND_CMD_PARAM)
414 timing = IFC_FIR_OP_RBCD;
415
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530416 ifc_out32(&ifc->ifc_nand.nand_fir0,
417 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
418 (IFC_FIR_OP_UA << IFC_NAND_FIR0_OP1_SHIFT) |
419 (timing << IFC_NAND_FIR0_OP2_SHIFT));
420 ifc_out32(&ifc->ifc_nand.nand_fcr0,
421 command << IFC_NAND_FCR0_CMD0_SHIFT);
422 ifc_out32(&ifc->ifc_nand.row3, column);
Prabhakar Kushwahaf31cf532012-04-08 18:57:18 +0000423
424 /*
425 * although currently it's 8 bytes for READID, we always read
426 * the maximum 256 bytes(for PARAM)
427 */
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530428 ifc_out32(&ifc->ifc_nand.nand_fbcr, 256);
Prabhakar Kushwahaf31cf532012-04-08 18:57:18 +0000429 ctrl->read_bytes = 256;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530430
431 set_addr(mtd, 0, 0, 0);
432 fsl_ifc_run_command(mtd);
433 return;
Prabhakar Kushwahaf31cf532012-04-08 18:57:18 +0000434 }
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530435
436 /* ERASE1 stores the block and page address */
437 case NAND_CMD_ERASE1:
438 set_addr(mtd, 0, page_addr, 0);
439 return;
440
441 /* ERASE2 uses the block and page address from ERASE1 */
442 case NAND_CMD_ERASE2:
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_RA0 << IFC_NAND_FIR0_OP1_SHIFT) |
446 (IFC_FIR_OP_CMD1 << IFC_NAND_FIR0_OP2_SHIFT));
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530447
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530448 ifc_out32(&ifc->ifc_nand.nand_fcr0,
449 (NAND_CMD_ERASE1 << IFC_NAND_FCR0_CMD0_SHIFT) |
450 (NAND_CMD_ERASE2 << IFC_NAND_FCR0_CMD1_SHIFT));
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530451
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530452 ifc_out32(&ifc->ifc_nand.nand_fbcr, 0);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530453 ctrl->read_bytes = 0;
454 fsl_ifc_run_command(mtd);
455 return;
456
457 /* SEQIN sets up the addr buffer and all registers except the length */
458 case NAND_CMD_SEQIN: {
459 u32 nand_fcr0;
460 ctrl->column = column;
461 ctrl->oob = 0;
462
463 if (mtd->writesize > 512) {
464 nand_fcr0 =
465 (NAND_CMD_SEQIN << IFC_NAND_FCR0_CMD0_SHIFT) |
Prabhakar Kushwaha18e6bde2013-10-03 11:35:35 +0530466 (NAND_CMD_STATUS << IFC_NAND_FCR0_CMD1_SHIFT) |
467 (NAND_CMD_PAGEPROG << IFC_NAND_FCR0_CMD2_SHIFT);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530468
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530469 ifc_out32(&ifc->ifc_nand.nand_fir0,
470 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
471 (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP1_SHIFT) |
472 (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP2_SHIFT) |
473 (IFC_FIR_OP_WBCD <<
474 IFC_NAND_FIR0_OP3_SHIFT) |
475 (IFC_FIR_OP_CMD2 << IFC_NAND_FIR0_OP4_SHIFT));
476 ifc_out32(&ifc->ifc_nand.nand_fir1,
477 (IFC_FIR_OP_CW1 << IFC_NAND_FIR1_OP5_SHIFT) |
478 (IFC_FIR_OP_RDSTAT <<
Prabhakar Kushwaha18e6bde2013-10-03 11:35:35 +0530479 IFC_NAND_FIR1_OP6_SHIFT) |
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530480 (IFC_FIR_OP_NOP << IFC_NAND_FIR1_OP7_SHIFT));
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530481 } else {
482 nand_fcr0 = ((NAND_CMD_PAGEPROG <<
483 IFC_NAND_FCR0_CMD1_SHIFT) |
484 (NAND_CMD_SEQIN <<
Prabhakar Kushwaha18e6bde2013-10-03 11:35:35 +0530485 IFC_NAND_FCR0_CMD2_SHIFT) |
486 (NAND_CMD_STATUS <<
487 IFC_NAND_FCR0_CMD3_SHIFT));
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530488
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530489 ifc_out32(&ifc->ifc_nand.nand_fir0,
490 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
491 (IFC_FIR_OP_CMD2 << IFC_NAND_FIR0_OP1_SHIFT) |
492 (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP2_SHIFT) |
493 (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP3_SHIFT) |
494 (IFC_FIR_OP_WBCD << IFC_NAND_FIR0_OP4_SHIFT));
495 ifc_out32(&ifc->ifc_nand.nand_fir1,
496 (IFC_FIR_OP_CMD1 << IFC_NAND_FIR1_OP5_SHIFT) |
497 (IFC_FIR_OP_CW3 << IFC_NAND_FIR1_OP6_SHIFT) |
498 (IFC_FIR_OP_RDSTAT <<
Prabhakar Kushwaha18e6bde2013-10-03 11:35:35 +0530499 IFC_NAND_FIR1_OP7_SHIFT) |
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530500 (IFC_FIR_OP_NOP << IFC_NAND_FIR1_OP8_SHIFT));
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530501
Prabhakar Kushwaha0ed5e772012-01-20 18:39:05 +0530502 if (column >= mtd->writesize)
503 nand_fcr0 |=
504 NAND_CMD_READOOB << IFC_NAND_FCR0_CMD0_SHIFT;
505 else
506 nand_fcr0 |=
507 NAND_CMD_READ0 << IFC_NAND_FCR0_CMD0_SHIFT;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530508 }
509
Prabhakar Kushwaha0ed5e772012-01-20 18:39:05 +0530510 if (column >= mtd->writesize) {
511 /* OOB area --> READOOB */
512 column -= mtd->writesize;
513 ctrl->oob = 1;
514 }
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530515 ifc_out32(&ifc->ifc_nand.nand_fcr0, nand_fcr0);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530516 set_addr(mtd, column, page_addr, ctrl->oob);
517 return;
518 }
519
520 /* PAGEPROG reuses all of the setup from SEQIN and adds the length */
521 case NAND_CMD_PAGEPROG:
522 if (ctrl->oob)
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530523 ifc_out32(&ifc->ifc_nand.nand_fbcr,
524 ctrl->index - ctrl->column);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530525 else
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530526 ifc_out32(&ifc->ifc_nand.nand_fbcr, 0);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530527
528 fsl_ifc_run_command(mtd);
529 return;
530
531 case NAND_CMD_STATUS:
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530532 ifc_out32(&ifc->ifc_nand.nand_fir0,
533 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
534 (IFC_FIR_OP_RB << IFC_NAND_FIR0_OP1_SHIFT));
535 ifc_out32(&ifc->ifc_nand.nand_fcr0,
536 NAND_CMD_STATUS << IFC_NAND_FCR0_CMD0_SHIFT);
537 ifc_out32(&ifc->ifc_nand.nand_fbcr, 1);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530538 set_addr(mtd, 0, 0, 0);
539 ctrl->read_bytes = 1;
540
541 fsl_ifc_run_command(mtd);
542
Scott Wood3ea94ed2015-06-26 19:03:26 -0500543 /*
544 * The chip always seems to report that it is
545 * write-protected, even when it is not.
546 */
547 if (chip->options & NAND_BUSWIDTH_16)
548 ifc_out16(ctrl->addr,
549 ifc_in16(ctrl->addr) | NAND_STATUS_WP);
550 else
551 out_8(ctrl->addr, in_8(ctrl->addr) | NAND_STATUS_WP);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530552 return;
553
554 case NAND_CMD_RESET:
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530555 ifc_out32(&ifc->ifc_nand.nand_fir0,
556 IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT);
557 ifc_out32(&ifc->ifc_nand.nand_fcr0,
558 NAND_CMD_RESET << IFC_NAND_FCR0_CMD0_SHIFT);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530559 fsl_ifc_run_command(mtd);
560 return;
561
562 default:
563 printf("%s: error, unsupported command 0x%x.\n",
564 __func__, command);
565 }
566}
567
568/*
569 * Write buf to the IFC NAND Controller Data Buffer
570 */
571static void fsl_ifc_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
572{
Scott Wood17fed142016-05-30 13:57:56 -0500573 struct nand_chip *chip = mtd_to_nand(mtd);
574 struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530575 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
576 unsigned int bufsize = mtd->writesize + mtd->oobsize;
577
578 if (len <= 0) {
579 printf("%s of %d bytes", __func__, len);
580 ctrl->status = 0;
581 return;
582 }
583
584 if ((unsigned int)len > bufsize - ctrl->index) {
585 printf("%s beyond end of buffer "
586 "(%d requested, %u available)\n",
587 __func__, len, bufsize - ctrl->index);
588 len = bufsize - ctrl->index;
589 }
590
Scott Wood3ea94ed2015-06-26 19:03:26 -0500591 memcpy_toio(ctrl->addr + ctrl->index, buf, len);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530592 ctrl->index += len;
593}
594
595/*
596 * read a byte from either the IFC hardware buffer if it has any data left
597 * otherwise issue a command to read a single byte.
598 */
599static u8 fsl_ifc_read_byte(struct mtd_info *mtd)
600{
Scott Wood17fed142016-05-30 13:57:56 -0500601 struct nand_chip *chip = mtd_to_nand(mtd);
602 struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530603 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
Scott Wood3ea94ed2015-06-26 19:03:26 -0500604 unsigned int offset;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530605
Scott Wood3ea94ed2015-06-26 19:03:26 -0500606 /*
607 * If there are still bytes in the IFC buffer, then use the
608 * next byte.
609 */
610 if (ctrl->index < ctrl->read_bytes) {
611 offset = ctrl->index++;
612 return in_8(ctrl->addr + offset);
613 }
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530614
615 printf("%s beyond end of buffer\n", __func__);
616 return ERR_BYTE;
617}
618
619/*
620 * Read two bytes from the IFC hardware buffer
621 * read function for 16-bit buswith
622 */
623static uint8_t fsl_ifc_read_byte16(struct mtd_info *mtd)
624{
Scott Wood17fed142016-05-30 13:57:56 -0500625 struct nand_chip *chip = mtd_to_nand(mtd);
626 struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530627 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
628 uint16_t data;
629
630 /*
631 * If there are still bytes in the IFC buffer, then use the
632 * next byte.
633 */
634 if (ctrl->index < ctrl->read_bytes) {
Scott Wood3ea94ed2015-06-26 19:03:26 -0500635 data = ifc_in16(ctrl->addr + ctrl->index);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530636 ctrl->index += 2;
637 return (uint8_t)data;
638 }
639
640 printf("%s beyond end of buffer\n", __func__);
641 return ERR_BYTE;
642}
643
644/*
645 * Read from the IFC Controller Data Buffer
646 */
647static void fsl_ifc_read_buf(struct mtd_info *mtd, u8 *buf, int len)
648{
Scott Wood17fed142016-05-30 13:57:56 -0500649 struct nand_chip *chip = mtd_to_nand(mtd);
650 struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530651 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
652 int avail;
653
654 if (len < 0)
655 return;
656
657 avail = min((unsigned int)len, ctrl->read_bytes - ctrl->index);
Scott Wood3ea94ed2015-06-26 19:03:26 -0500658 memcpy_fromio(buf, ctrl->addr + ctrl->index, avail);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530659 ctrl->index += avail;
660
661 if (len > avail)
662 printf("%s beyond end of buffer "
663 "(%d requested, %d available)\n",
664 __func__, len, avail);
665}
666
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530667/* This function is called after Program and Erase Operations to
668 * check for success or failure.
669 */
670static int fsl_ifc_wait(struct mtd_info *mtd, struct nand_chip *chip)
671{
Scott Wood17fed142016-05-30 13:57:56 -0500672 struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530673 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
Jaiprakash Singhdd888062015-03-20 19:28:27 -0700674 struct fsl_ifc_runtime *ifc = ctrl->regs.rregs;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530675 u32 nand_fsr;
Jagdish Gediya997f04a2018-05-02 01:20:57 +0530676 int status;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530677
678 if (ctrl->status != IFC_NAND_EVTER_STAT_OPC)
679 return NAND_STATUS_FAIL;
680
681 /* Use READ_STATUS command, but wait for the device to be ready */
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530682 ifc_out32(&ifc->ifc_nand.nand_fir0,
683 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
684 (IFC_FIR_OP_RDSTAT << IFC_NAND_FIR0_OP1_SHIFT));
685 ifc_out32(&ifc->ifc_nand.nand_fcr0, NAND_CMD_STATUS <<
686 IFC_NAND_FCR0_CMD0_SHIFT);
687 ifc_out32(&ifc->ifc_nand.nand_fbcr, 1);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530688 set_addr(mtd, 0, 0, 0);
689 ctrl->read_bytes = 1;
690
691 fsl_ifc_run_command(mtd);
692
693 if (ctrl->status != IFC_NAND_EVTER_STAT_OPC)
694 return NAND_STATUS_FAIL;
695
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530696 nand_fsr = ifc_in32(&ifc->ifc_nand.nand_fsr);
Jagdish Gediya997f04a2018-05-02 01:20:57 +0530697 status = nand_fsr >> 24;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530698
699 /* Chip sometimes reporting write protect even when it's not */
Jagdish Gediya997f04a2018-05-02 01:20:57 +0530700 return status | NAND_STATUS_WP;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530701}
702
Darwin Dingel3dae7e62018-08-02 10:02:45 +0200703/*
704 * The controller does not check for bitflips in erased pages,
705 * therefore software must check instead.
706 */
707static int
708check_erased_page(struct nand_chip *chip, u8 *buf, struct mtd_info *mtd)
709{
710 u8 *ecc = chip->oob_poi;
711 const int ecc_size = chip->ecc.bytes;
712 const int pkt_size = chip->ecc.size;
713 int i, res, bitflips;
714
715 /* IFC starts ecc bytes at offset 8 in the spare area. */
716 ecc += 8;
717 bitflips = 0;
718 for (i = 0; i < chip->ecc.steps; i++) {
719 res = nand_check_erased_ecc_chunk(buf, pkt_size, ecc, ecc_size,
720 NULL, 0, chip->ecc.strength);
721
722 if (res < 0) {
723 printf("fsl-ifc: NAND Flash ECC Uncorrectable Error\n");
724 mtd->ecc_stats.failed++;
725 } else if (res > 0) {
726 mtd->ecc_stats.corrected += res;
727 }
728 bitflips = max(res, bitflips);
729 buf += pkt_size;
730 ecc += ecc_size;
731 }
732
733 return bitflips;
734}
735
Sergey Lapin3a38a552013-01-14 03:46:50 +0000736static int fsl_ifc_read_page(struct mtd_info *mtd, struct nand_chip *chip,
737 uint8_t *buf, int oob_required, int page)
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530738{
Scott Wood17fed142016-05-30 13:57:56 -0500739 struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530740 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
741
742 fsl_ifc_read_buf(mtd, buf, mtd->writesize);
743 fsl_ifc_read_buf(mtd, chip->oob_poi, mtd->oobsize);
744
Darwin Dingel3dae7e62018-08-02 10:02:45 +0200745 if (ctrl->status & IFC_NAND_EVTER_STAT_ECCER)
746 return check_erased_page(chip, buf, mtd);
747
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530748 if (ctrl->status != IFC_NAND_EVTER_STAT_OPC)
749 mtd->ecc_stats.failed++;
750
751 return 0;
752}
753
754/* ECC will be calculated automatically, and errors will be detected in
755 * waitfunc.
756 */
Sergey Lapin3a38a552013-01-14 03:46:50 +0000757static int fsl_ifc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
Scott Wood46e13102016-05-30 13:57:57 -0500758 const uint8_t *buf, int oob_required, int page)
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530759{
760 fsl_ifc_write_buf(mtd, buf, mtd->writesize);
761 fsl_ifc_write_buf(mtd, chip->oob_poi, mtd->oobsize);
Sergey Lapin3a38a552013-01-14 03:46:50 +0000762
763 return 0;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530764}
765
766static void fsl_ifc_ctrl_init(void)
767{
Jaiprakash Singhdd888062015-03-20 19:28:27 -0700768 uint32_t ver = 0;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530769 ifc_ctrl = kzalloc(sizeof(*ifc_ctrl), GFP_KERNEL);
770 if (!ifc_ctrl)
771 return;
772
Jaiprakash Singhdd888062015-03-20 19:28:27 -0700773 ifc_ctrl->regs.gregs = IFC_FCM_BASE_ADDR;
774
775 ver = ifc_in32(&ifc_ctrl->regs.gregs->ifc_rev);
776 if (ver >= FSL_IFC_V2_0_0)
777 ifc_ctrl->regs.rregs =
778 (void *)CONFIG_SYS_IFC_ADDR + IFC_RREGS_64KOFFSET;
779 else
780 ifc_ctrl->regs.rregs =
781 (void *)CONFIG_SYS_IFC_ADDR + IFC_RREGS_4KOFFSET;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530782
783 /* clear event registers */
Jaiprakash Singhdd888062015-03-20 19:28:27 -0700784 ifc_out32(&ifc_ctrl->regs.rregs->ifc_nand.nand_evter_stat, ~0U);
785 ifc_out32(&ifc_ctrl->regs.rregs->ifc_nand.pgrdcmpl_evt_stat, ~0U);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530786
787 /* Enable error and event for any detected errors */
Jaiprakash Singhdd888062015-03-20 19:28:27 -0700788 ifc_out32(&ifc_ctrl->regs.rregs->ifc_nand.nand_evter_en,
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530789 IFC_NAND_EVTER_EN_OPC_EN |
790 IFC_NAND_EVTER_EN_PGRDCMPL_EN |
791 IFC_NAND_EVTER_EN_FTOER_EN |
792 IFC_NAND_EVTER_EN_WPER_EN);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530793
Jaiprakash Singhdd888062015-03-20 19:28:27 -0700794 ifc_out32(&ifc_ctrl->regs.rregs->ifc_nand.ncfgr, 0x0);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530795}
796
797static void fsl_ifc_select_chip(struct mtd_info *mtd, int chip)
798{
799}
800
Kurt Kanzenbach1f161f82017-10-20 11:44:25 +0200801static int fsl_ifc_sram_init(struct fsl_ifc_mtd *priv, uint32_t ver)
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000802{
Jaiprakash Singhdd888062015-03-20 19:28:27 -0700803 struct fsl_ifc_runtime *ifc = ifc_ctrl->regs.rregs;
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000804 uint32_t cs = 0, csor = 0, csor_8k = 0, csor_ext = 0;
Prabhakar Kushwaha82efc812014-06-12 12:14:00 +0530805 uint32_t ncfgr = 0;
Prabhakar Kushwahad7550e12014-09-23 09:57:47 +0530806 u32 timeo = (CONFIG_SYS_HZ * 10) / 1000;
807 u32 time_start;
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000808
Prabhakar Kushwaha82efc812014-06-12 12:14:00 +0530809 if (ver > FSL_IFC_V1_1_0) {
810 ncfgr = ifc_in32(&ifc->ifc_nand.ncfgr);
811 ifc_out32(&ifc->ifc_nand.ncfgr, ncfgr | IFC_NAND_SRAM_INIT_EN);
812
813 /* wait for SRAM_INIT bit to be clear or timeout */
Prabhakar Kushwahad7550e12014-09-23 09:57:47 +0530814 time_start = get_timer(0);
815 while (get_timer(time_start) < timeo) {
Prabhakar Kushwaha82efc812014-06-12 12:14:00 +0530816 ifc_ctrl->status =
817 ifc_in32(&ifc->ifc_nand.nand_evter_stat);
818
819 if (!(ifc_ctrl->status & IFC_NAND_SRAM_INIT_EN))
820 return 0;
821 }
822 printf("fsl-ifc: Failed to Initialise SRAM\n");
823 return 1;
824 }
825
Kurt Kanzenbach1f161f82017-10-20 11:44:25 +0200826 cs = priv->bank;
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000827
828 /* Save CSOR and CSOR_ext */
Jaiprakash Singhdd888062015-03-20 19:28:27 -0700829 csor = ifc_in32(&ifc_ctrl->regs.gregs->csor_cs[cs].csor);
830 csor_ext = ifc_in32(&ifc_ctrl->regs.gregs->csor_cs[cs].csor_ext);
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000831
832 /* chage PageSize 8K and SpareSize 1K*/
833 csor_8k = (csor & ~(CSOR_NAND_PGS_MASK)) | 0x0018C000;
Jaiprakash Singhdd888062015-03-20 19:28:27 -0700834 ifc_out32(&ifc_ctrl->regs.gregs->csor_cs[cs].csor, csor_8k);
835 ifc_out32(&ifc_ctrl->regs.gregs->csor_cs[cs].csor_ext, 0x0000400);
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000836
837 /* READID */
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530838 ifc_out32(&ifc->ifc_nand.nand_fir0,
839 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
840 (IFC_FIR_OP_UA << IFC_NAND_FIR0_OP1_SHIFT) |
841 (IFC_FIR_OP_RB << IFC_NAND_FIR0_OP2_SHIFT));
842 ifc_out32(&ifc->ifc_nand.nand_fcr0,
843 NAND_CMD_READID << IFC_NAND_FCR0_CMD0_SHIFT);
844 ifc_out32(&ifc->ifc_nand.row3, 0x0);
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000845
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530846 ifc_out32(&ifc->ifc_nand.nand_fbcr, 0x0);
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000847
848 /* Program ROW0/COL0 */
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530849 ifc_out32(&ifc->ifc_nand.row0, 0x0);
850 ifc_out32(&ifc->ifc_nand.col0, 0x0);
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000851
852 /* set the chip select for NAND Transaction */
Kurt Kanzenbach1f161f82017-10-20 11:44:25 +0200853 ifc_out32(&ifc->ifc_nand.nand_csel, priv->bank << IFC_NAND_CSEL_SHIFT);
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000854
855 /* start read seq */
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530856 ifc_out32(&ifc->ifc_nand.nandseq_strt, IFC_NAND_SEQ_STRT_FIR_STRT);
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000857
Prabhakar Kushwahad7550e12014-09-23 09:57:47 +0530858 time_start = get_timer(0);
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000859
Prabhakar Kushwahad7550e12014-09-23 09:57:47 +0530860 while (get_timer(time_start) < timeo) {
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530861 ifc_ctrl->status = ifc_in32(&ifc->ifc_nand.nand_evter_stat);
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000862
863 if (ifc_ctrl->status & IFC_NAND_EVTER_STAT_OPC)
864 break;
865 }
866
Prabhakar Kushwaha82efc812014-06-12 12:14:00 +0530867 if (ifc_ctrl->status != IFC_NAND_EVTER_STAT_OPC) {
868 printf("fsl-ifc: Failed to Initialise SRAM\n");
869 return 1;
870 }
871
Prabhakar Kushwaha62908c22014-01-18 12:28:30 +0530872 ifc_out32(&ifc->ifc_nand.nand_evter_stat, ifc_ctrl->status);
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000873
874 /* Restore CSOR and CSOR_ext */
Jaiprakash Singhdd888062015-03-20 19:28:27 -0700875 ifc_out32(&ifc_ctrl->regs.gregs->csor_cs[cs].csor, csor);
876 ifc_out32(&ifc_ctrl->regs.gregs->csor_cs[cs].csor_ext, csor_ext);
Prabhakar Kushwaha82efc812014-06-12 12:14:00 +0530877
878 return 0;
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000879}
880
Prabhakar Kushwaha895d0392013-04-04 18:44:06 +0000881static int fsl_ifc_chip_init(int devnum, u8 *addr)
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530882{
Scott Wood2c1b7e12016-05-30 13:57:55 -0500883 struct mtd_info *mtd;
Prabhakar Kushwaha895d0392013-04-04 18:44:06 +0000884 struct nand_chip *nand;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530885 struct fsl_ifc_mtd *priv;
886 struct nand_ecclayout *layout;
Jaiprakash Singhdd888062015-03-20 19:28:27 -0700887 struct fsl_ifc_fcm *gregs = NULL;
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +0000888 uint32_t cspr = 0, csor = 0, ver = 0;
Prabhakar Kushwaha82efc812014-06-12 12:14:00 +0530889 int ret = 0;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530890
891 if (!ifc_ctrl) {
892 fsl_ifc_ctrl_init();
893 if (!ifc_ctrl)
894 return -1;
895 }
896
897 priv = kzalloc(sizeof(*priv), GFP_KERNEL);
898 if (!priv)
899 return -ENOMEM;
900
901 priv->ctrl = ifc_ctrl;
Prabhakar Kushwaha895d0392013-04-04 18:44:06 +0000902 priv->vbase = addr;
Jaiprakash Singhdd888062015-03-20 19:28:27 -0700903 gregs = ifc_ctrl->regs.gregs;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530904
905 /* Find which chip select it is connected to.
906 */
907 for (priv->bank = 0; priv->bank < MAX_BANKS; priv->bank++) {
Prabhakar Kushwaha895d0392013-04-04 18:44:06 +0000908 phys_addr_t phys_addr = virt_to_phys(addr);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530909
Jaiprakash Singhdd888062015-03-20 19:28:27 -0700910 cspr = ifc_in32(&gregs->cspr_cs[priv->bank].cspr);
911 csor = ifc_in32(&gregs->csor_cs[priv->bank].csor);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530912
913 if ((cspr & CSPR_V) && (cspr & CSPR_MSEL) == CSPR_MSEL_NAND &&
Kurt Kanzenbach1f161f82017-10-20 11:44:25 +0200914 (cspr & CSPR_BA) == CSPR_PHYS_ADDR(phys_addr))
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530915 break;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530916 }
917
918 if (priv->bank >= MAX_BANKS) {
919 printf("%s: address did not match any "
920 "chip selects\n", __func__);
Prabhakar Kushwahaae25e882012-04-10 22:48:27 +0000921 kfree(priv);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530922 return -ENODEV;
923 }
924
Prabhakar Kushwaha895d0392013-04-04 18:44:06 +0000925 nand = &priv->chip;
Scott Wood17fed142016-05-30 13:57:56 -0500926 mtd = nand_to_mtd(nand);
Prabhakar Kushwaha895d0392013-04-04 18:44:06 +0000927
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530928 ifc_ctrl->chips[priv->bank] = priv;
929
930 /* fill in nand_chip structure */
931 /* set up function call table */
932
933 nand->write_buf = fsl_ifc_write_buf;
934 nand->read_buf = fsl_ifc_read_buf;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530935 nand->select_chip = fsl_ifc_select_chip;
936 nand->cmdfunc = fsl_ifc_cmdfunc;
937 nand->waitfunc = fsl_ifc_wait;
938
939 /* set up nand options */
940 nand->bbt_td = &bbt_main_descr;
941 nand->bbt_md = &bbt_mirror_descr;
942
943 /* set up nand options */
Sergey Lapin3a38a552013-01-14 03:46:50 +0000944 nand->options = NAND_NO_SUBPAGE_WRITE;
945 nand->bbt_options = NAND_BBT_USE_FLASH;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530946
947 if (cspr & CSPR_PORT_SIZE_16) {
948 nand->read_byte = fsl_ifc_read_byte16;
949 nand->options |= NAND_BUSWIDTH_16;
950 } else {
951 nand->read_byte = fsl_ifc_read_byte;
952 }
953
954 nand->controller = &ifc_ctrl->controller;
Scott Wood17fed142016-05-30 13:57:56 -0500955 nand_set_controller_data(nand, priv);
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530956
957 nand->ecc.read_page = fsl_ifc_read_page;
958 nand->ecc.write_page = fsl_ifc_write_page;
959
960 /* Hardware generates ECC per 512 Bytes */
961 nand->ecc.size = 512;
962 nand->ecc.bytes = 8;
963
964 switch (csor & CSOR_NAND_PGS_MASK) {
965 case CSOR_NAND_PGS_512:
966 if (nand->options & NAND_BUSWIDTH_16) {
967 layout = &oob_512_16bit_ecc4;
968 } else {
969 layout = &oob_512_8bit_ecc4;
970
971 /* Avoid conflict with bad block marker */
972 bbt_main_descr.offs = 0;
973 bbt_mirror_descr.offs = 0;
974 }
975
Sergey Lapin3a38a552013-01-14 03:46:50 +0000976 nand->ecc.strength = 4;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530977 priv->bufnum_mask = 15;
978 break;
979
980 case CSOR_NAND_PGS_2K:
981 layout = &oob_2048_ecc4;
Sergey Lapin3a38a552013-01-14 03:46:50 +0000982 nand->ecc.strength = 4;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530983 priv->bufnum_mask = 3;
984 break;
985
986 case CSOR_NAND_PGS_4K:
987 if ((csor & CSOR_NAND_ECC_MODE_MASK) ==
988 CSOR_NAND_ECC_MODE_4) {
989 layout = &oob_4096_ecc4;
Sergey Lapin3a38a552013-01-14 03:46:50 +0000990 nand->ecc.strength = 4;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530991 } else {
992 layout = &oob_4096_ecc8;
Sergey Lapin3a38a552013-01-14 03:46:50 +0000993 nand->ecc.strength = 8;
Dipen Dudhat9eae0832011-03-22 09:27:39 +0530994 nand->ecc.bytes = 16;
995 }
996
997 priv->bufnum_mask = 1;
998 break;
999
Prabhakar Kushwahaa3aaf1d2013-10-04 10:05:36 +05301000 case CSOR_NAND_PGS_8K:
1001 if ((csor & CSOR_NAND_ECC_MODE_MASK) ==
1002 CSOR_NAND_ECC_MODE_4) {
1003 layout = &oob_8192_ecc4;
1004 nand->ecc.strength = 4;
1005 } else {
1006 layout = &oob_8192_ecc8;
1007 nand->ecc.strength = 8;
1008 nand->ecc.bytes = 16;
1009 }
1010
1011 priv->bufnum_mask = 0;
1012 break;
1013
1014
Dipen Dudhat9eae0832011-03-22 09:27:39 +05301015 default:
1016 printf("ifc nand: bad csor %#x: bad page size\n", csor);
1017 return -ENODEV;
1018 }
1019
1020 /* Must also set CSOR_NAND_ECC_ENC_EN if DEC_EN set */
1021 if (csor & CSOR_NAND_ECC_DEC_EN) {
1022 nand->ecc.mode = NAND_ECC_HW;
1023 nand->ecc.layout = layout;
1024 } else {
1025 nand->ecc.mode = NAND_ECC_SOFT;
1026 }
1027
Jaiprakash Singhdd888062015-03-20 19:28:27 -07001028 ver = ifc_in32(&gregs->ifc_rev);
Prabhakar Kushwaha82efc812014-06-12 12:14:00 +05301029 if (ver >= FSL_IFC_V1_1_0)
Kurt Kanzenbach1f161f82017-10-20 11:44:25 +02001030 ret = fsl_ifc_sram_init(priv, ver);
Prabhakar Kushwaha82efc812014-06-12 12:14:00 +05301031 if (ret)
1032 return ret;
Prabhakar Kushwahadccbf352012-09-12 22:26:05 +00001033
Prabhakar Kushwaha5c23a822014-06-14 08:48:19 +05301034 if (ver >= FSL_IFC_V2_0_0)
1035 priv->bufnum_mask = (priv->bufnum_mask * 2) + 1;
1036
Prabhakar Kushwaha895d0392013-04-04 18:44:06 +00001037 ret = nand_scan_ident(mtd, 1, NULL);
1038 if (ret)
1039 return ret;
1040
1041 ret = nand_scan_tail(mtd);
1042 if (ret)
1043 return ret;
1044
Scott Wood2c1b7e12016-05-30 13:57:55 -05001045 ret = nand_register(devnum, mtd);
Prabhakar Kushwaha895d0392013-04-04 18:44:06 +00001046 if (ret)
1047 return ret;
Dipen Dudhat9eae0832011-03-22 09:27:39 +05301048 return 0;
1049}
Prabhakar Kushwaha895d0392013-04-04 18:44:06 +00001050
1051#ifndef CONFIG_SYS_NAND_BASE_LIST
1052#define CONFIG_SYS_NAND_BASE_LIST { CONFIG_SYS_NAND_BASE }
1053#endif
1054
1055static unsigned long base_address[CONFIG_SYS_MAX_NAND_DEVICE] =
1056 CONFIG_SYS_NAND_BASE_LIST;
1057
1058void board_nand_init(void)
1059{
1060 int i;
1061
1062 for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++)
1063 fsl_ifc_chip_init(i, (u8 *)base_address[i]);
1064}