blob: 41db9f8bb9b1e65e59862dae068d38b800495e94 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Siva Durga Prasad Paladuguc7b0bc72015-11-17 14:30:10 +05302/*
3 * Arasan NAND Flash Controller Driver
4 *
5 * Copyright (C) 2014 - 2015 Xilinx, Inc.
Siva Durga Prasad Paladuguc7b0bc72015-11-17 14:30:10 +05306 */
7
8#include <common.h>
9#include <malloc.h>
10#include <asm/io.h>
Masahiro Yamada56a931c2016-09-21 11:28:55 +090011#include <linux/errno.h>
Siva Durga Prasad Paladuguc7b0bc72015-11-17 14:30:10 +053012#include <linux/mtd/mtd.h>
Masahiro Yamada2b7a8732017-11-30 13:45:24 +090013#include <linux/mtd/rawnand.h>
Siva Durga Prasad Paladuguc7b0bc72015-11-17 14:30:10 +053014#include <linux/mtd/partitions.h>
15#include <linux/mtd/nand_ecc.h>
16#include <asm/arch/hardware.h>
17#include <asm/arch/sys_proto.h>
18#include <nand.h>
19
20struct arasan_nand_info {
21 void __iomem *nand_base;
22 u32 page;
Siva Durga Prasad Paladugu45e512c2018-01-04 16:04:21 +053023 bool on_die_ecc_enabled;
Siva Durga Prasad Paladuguc7b0bc72015-11-17 14:30:10 +053024};
25
26struct nand_regs {
27 u32 pkt_reg;
28 u32 memadr_reg1;
29 u32 memadr_reg2;
30 u32 cmd_reg;
31 u32 pgm_reg;
32 u32 intsts_enr;
33 u32 intsig_enr;
34 u32 intsts_reg;
35 u32 rdy_busy;
36 u32 cms_sysadr_reg;
37 u32 flash_sts_reg;
38 u32 tmg_reg;
39 u32 buf_dataport;
40 u32 ecc_reg;
41 u32 ecc_errcnt_reg;
42 u32 ecc_sprcmd_reg;
43 u32 errcnt_1bitreg;
44 u32 errcnt_2bitreg;
45 u32 errcnt_3bitreg;
46 u32 errcnt_4bitreg;
47 u32 dma_sysadr0_reg;
48 u32 dma_bufbdry_reg;
49 u32 cpu_rls_reg;
50 u32 errcnt_5bitreg;
51 u32 errcnt_6bitreg;
52 u32 errcnt_7bitreg;
53 u32 errcnt_8bitreg;
54 u32 data_if_reg;
55};
56
57#define arasan_nand_base ((struct nand_regs __iomem *)ARASAN_NAND_BASEADDR)
58
59struct arasan_nand_command_format {
60 u8 cmd1;
61 u8 cmd2;
62 u8 addr_cycles;
63 u32 pgm;
64};
65
66#define ONDIE_ECC_FEATURE_ADDR 0x90
Siva Durga Prasad Paladugu45e512c2018-01-04 16:04:21 +053067#define ENABLE_ONDIE_ECC 0x08
Siva Durga Prasad Paladuguc7b0bc72015-11-17 14:30:10 +053068
69#define ARASAN_PROG_RD_MASK 0x00000001
70#define ARASAN_PROG_BLK_ERS_MASK 0x00000004
71#define ARASAN_PROG_RD_ID_MASK 0x00000040
72#define ARASAN_PROG_RD_STS_MASK 0x00000008
73#define ARASAN_PROG_PG_PROG_MASK 0x00000010
74#define ARASAN_PROG_RD_PARAM_PG_MASK 0x00000080
75#define ARASAN_PROG_RST_MASK 0x00000100
76#define ARASAN_PROG_GET_FTRS_MASK 0x00000200
77#define ARASAN_PROG_SET_FTRS_MASK 0x00000400
78#define ARASAN_PROG_CHNG_ROWADR_END_MASK 0x00400000
79
80#define ARASAN_NAND_CMD_ECC_ON_MASK 0x80000000
81#define ARASAN_NAND_CMD_CMD12_MASK 0xFFFF
82#define ARASAN_NAND_CMD_PG_SIZE_MASK 0x3800000
83#define ARASAN_NAND_CMD_PG_SIZE_SHIFT 23
84#define ARASAN_NAND_CMD_CMD2_SHIFT 8
85#define ARASAN_NAND_CMD_ADDR_CYCL_MASK 0x70000000
86#define ARASAN_NAND_CMD_ADDR_CYCL_SHIFT 28
87
Vipul Kumar9d9b99b2018-03-10 17:52:23 +053088#define ARASAN_NAND_MEM_ADDR1_PAGE_MASK 0xFFFF0000
Siva Durga Prasad Paladuguc7b0bc72015-11-17 14:30:10 +053089#define ARASAN_NAND_MEM_ADDR1_COL_MASK 0xFFFF
90#define ARASAN_NAND_MEM_ADDR1_PAGE_SHIFT 16
91#define ARASAN_NAND_MEM_ADDR2_PAGE_MASK 0xFF
92#define ARASAN_NAND_MEM_ADDR2_CS_MASK 0xC0000000
93#define ARASAN_NAND_MEM_ADDR2_BCH_MASK 0xE000000
94#define ARASAN_NAND_MEM_ADDR2_BCH_SHIFT 25
95
96#define ARASAN_NAND_INT_STS_ERR_EN_MASK 0x10
97#define ARASAN_NAND_INT_STS_MUL_BIT_ERR_MASK 0x08
98#define ARASAN_NAND_INT_STS_BUF_RD_RDY_MASK 0x02
99#define ARASAN_NAND_INT_STS_BUF_WR_RDY_MASK 0x01
100#define ARASAN_NAND_INT_STS_XFR_CMPLT_MASK 0x04
101
102#define ARASAN_NAND_PKT_REG_PKT_CNT_MASK 0xFFF000
103#define ARASAN_NAND_PKT_REG_PKT_SIZE_MASK 0x7FF
104#define ARASAN_NAND_PKT_REG_PKT_CNT_SHFT 12
105
106#define ARASAN_NAND_ROW_ADDR_CYCL_MASK 0x0F
107#define ARASAN_NAND_COL_ADDR_CYCL_MASK 0xF0
108#define ARASAN_NAND_COL_ADDR_CYCL_SHIFT 4
109
110#define ARASAN_NAND_ECC_SIZE_SHIFT 16
111#define ARASAN_NAND_ECC_BCH_SHIFT 27
112
113#define ARASAN_NAND_PKTSIZE_1K 1024
114#define ARASAN_NAND_PKTSIZE_512 512
115
116#define ARASAN_NAND_POLL_TIMEOUT 1000000
117#define ARASAN_NAND_INVALID_ADDR_CYCL 0xFF
118
119#define ERR_ADDR_CYCLE -1
120#define READ_BUFF_SIZE 0x4000
121
122static struct arasan_nand_command_format *curr_cmd;
123
124enum addr_cycles {
125 NAND_ADDR_CYCL_NONE,
126 NAND_ADDR_CYCL_ONE,
127 NAND_ADDR_CYCL_ROW,
128 NAND_ADDR_CYCL_COL,
129 NAND_ADDR_CYCL_BOTH,
130};
131
132static struct arasan_nand_command_format arasan_nand_commands[] = {
133 {NAND_CMD_READ0, NAND_CMD_READSTART, NAND_ADDR_CYCL_BOTH,
134 ARASAN_PROG_RD_MASK},
135 {NAND_CMD_RNDOUT, NAND_CMD_RNDOUTSTART, NAND_ADDR_CYCL_COL,
136 ARASAN_PROG_RD_MASK},
137 {NAND_CMD_READID, NAND_CMD_NONE, NAND_ADDR_CYCL_ONE,
138 ARASAN_PROG_RD_ID_MASK},
139 {NAND_CMD_STATUS, NAND_CMD_NONE, NAND_ADDR_CYCL_NONE,
140 ARASAN_PROG_RD_STS_MASK},
141 {NAND_CMD_SEQIN, NAND_CMD_PAGEPROG, NAND_ADDR_CYCL_BOTH,
142 ARASAN_PROG_PG_PROG_MASK},
143 {NAND_CMD_RNDIN, NAND_CMD_NONE, NAND_ADDR_CYCL_COL,
144 ARASAN_PROG_CHNG_ROWADR_END_MASK},
145 {NAND_CMD_ERASE1, NAND_CMD_ERASE2, NAND_ADDR_CYCL_ROW,
146 ARASAN_PROG_BLK_ERS_MASK},
147 {NAND_CMD_RESET, NAND_CMD_NONE, NAND_ADDR_CYCL_NONE,
148 ARASAN_PROG_RST_MASK},
149 {NAND_CMD_PARAM, NAND_CMD_NONE, NAND_ADDR_CYCL_ONE,
150 ARASAN_PROG_RD_PARAM_PG_MASK},
151 {NAND_CMD_GET_FEATURES, NAND_CMD_NONE, NAND_ADDR_CYCL_ONE,
152 ARASAN_PROG_GET_FTRS_MASK},
153 {NAND_CMD_SET_FEATURES, NAND_CMD_NONE, NAND_ADDR_CYCL_ONE,
154 ARASAN_PROG_SET_FTRS_MASK},
155 {NAND_CMD_NONE, NAND_CMD_NONE, NAND_ADDR_CYCL_NONE, 0},
156};
157
158struct arasan_ecc_matrix {
159 u32 pagesize;
160 u32 ecc_codeword_size;
161 u8 eccbits;
162 u8 bch;
163 u8 bchval;
164 u16 eccaddr;
165 u16 eccsize;
166};
167
168static const struct arasan_ecc_matrix ecc_matrix[] = {
169 {512, 512, 1, 0, 0, 0x20D, 0x3},
170 {512, 512, 4, 1, 3, 0x209, 0x7},
171 {512, 512, 8, 1, 2, 0x203, 0xD},
172 /*
173 * 2K byte page
174 */
175 {2048, 512, 1, 0, 0, 0x834, 0xC},
176 {2048, 512, 4, 1, 3, 0x826, 0x1A},
177 {2048, 512, 8, 1, 2, 0x80c, 0x34},
178 {2048, 512, 12, 1, 1, 0x822, 0x4E},
179 {2048, 512, 16, 1, 0, 0x808, 0x68},
180 {2048, 1024, 24, 1, 4, 0x81c, 0x54},
181 /*
182 * 4K byte page
183 */
184 {4096, 512, 1, 0, 0, 0x1068, 0x18},
185 {4096, 512, 4, 1, 3, 0x104c, 0x34},
186 {4096, 512, 8, 1, 2, 0x1018, 0x68},
187 {4096, 512, 12, 1, 1, 0x1044, 0x9C},
188 {4096, 512, 16, 1, 0, 0x1010, 0xD0},
189 {4096, 1024, 24, 1, 4, 0x1038, 0xA8},
190 /*
191 * 8K byte page
192 */
193 {8192, 512, 1, 0, 0, 0x20d0, 0x30},
194 {8192, 512, 4, 1, 3, 0x2098, 0x68},
195 {8192, 512, 8, 1, 2, 0x2030, 0xD0},
196 {8192, 512, 12, 1, 1, 0x2088, 0x138},
197 {8192, 512, 16, 1, 0, 0x2020, 0x1A0},
198 {8192, 1024, 24, 1, 4, 0x2070, 0x150},
199 /*
200 * 16K byte page
201 */
202 {16384, 512, 1, 0, 0, 0x4460, 0x60},
203 {16384, 512, 4, 1, 3, 0x43f0, 0xD0},
204 {16384, 512, 8, 1, 2, 0x4320, 0x1A0},
205 {16384, 512, 12, 1, 1, 0x4250, 0x270},
206 {16384, 512, 16, 1, 0, 0x4180, 0x340},
207 {16384, 1024, 24, 1, 4, 0x4220, 0x2A0}
208};
209
Siva Durga Prasad Paladugu45e512c2018-01-04 16:04:21 +0530210static struct nand_ecclayout ondie_nand_oob_64 = {
211 .eccbytes = 32,
212
213 .eccpos = {
214 8, 9, 10, 11, 12, 13, 14, 15,
215 24, 25, 26, 27, 28, 29, 30, 31,
216 40, 41, 42, 43, 44, 45, 46, 47,
217 56, 57, 58, 59, 60, 61, 62, 63
218 },
219
220 .oobfree = {
221 { .offset = 4, .length = 4 },
222 { .offset = 20, .length = 4 },
223 { .offset = 36, .length = 4 },
224 { .offset = 52, .length = 4 }
225 }
226};
227
228/*
229 * bbt decriptors for chips with on-die ECC and
230 * chips with 64-byte OOB
231 */
232static u8 bbt_pattern[] = {'B', 'b', 't', '0' };
233static u8 mirror_pattern[] = {'1', 't', 'b', 'B' };
234
235static struct nand_bbt_descr bbt_main_descr = {
236 .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE |
237 NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
238 .offs = 4,
239 .len = 4,
240 .veroffs = 20,
241 .maxblocks = 4,
242 .pattern = bbt_pattern
243};
244
245static struct nand_bbt_descr bbt_mirror_descr = {
246 .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE |
247 NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
248 .offs = 4,
249 .len = 4,
250 .veroffs = 20,
251 .maxblocks = 4,
252 .pattern = mirror_pattern
253};
254
Siva Durga Prasad Paladuguc7b0bc72015-11-17 14:30:10 +0530255static u8 buf_data[READ_BUFF_SIZE];
256static u32 buf_index;
257
258static struct nand_ecclayout nand_oob;
259
260static struct nand_chip nand_chip[CONFIG_SYS_MAX_NAND_DEVICE];
261
262static void arasan_nand_select_chip(struct mtd_info *mtd, int chip)
263{
264}
265
266static void arasan_nand_enable_ecc(void)
267{
268 u32 reg_val;
269
270 reg_val = readl(&arasan_nand_base->cmd_reg);
271 reg_val |= ARASAN_NAND_CMD_ECC_ON_MASK;
272
273 writel(reg_val, &arasan_nand_base->cmd_reg);
274}
275
276static u8 arasan_nand_get_addrcycle(struct mtd_info *mtd)
277{
278 u8 addrcycles;
Scott Wood17fed142016-05-30 13:57:56 -0500279 struct nand_chip *chip = mtd_to_nand(mtd);
Siva Durga Prasad Paladuguc7b0bc72015-11-17 14:30:10 +0530280
281 switch (curr_cmd->addr_cycles) {
282 case NAND_ADDR_CYCL_NONE:
283 addrcycles = 0;
284 break;
285 case NAND_ADDR_CYCL_ONE:
286 addrcycles = 1;
287 break;
288 case NAND_ADDR_CYCL_ROW:
289 addrcycles = chip->onfi_params.addr_cycles &
290 ARASAN_NAND_ROW_ADDR_CYCL_MASK;
291 break;
292 case NAND_ADDR_CYCL_COL:
293 addrcycles = (chip->onfi_params.addr_cycles &
294 ARASAN_NAND_COL_ADDR_CYCL_MASK) >>
295 ARASAN_NAND_COL_ADDR_CYCL_SHIFT;
296 break;
297 case NAND_ADDR_CYCL_BOTH:
298 addrcycles = chip->onfi_params.addr_cycles &
299 ARASAN_NAND_ROW_ADDR_CYCL_MASK;
300 addrcycles += (chip->onfi_params.addr_cycles &
301 ARASAN_NAND_COL_ADDR_CYCL_MASK) >>
302 ARASAN_NAND_COL_ADDR_CYCL_SHIFT;
303 break;
304 default:
305 addrcycles = ARASAN_NAND_INVALID_ADDR_CYCL;
306 break;
307 }
308 return addrcycles;
309}
310
311static int arasan_nand_read_page(struct mtd_info *mtd, u8 *buf, u32 size)
312{
Scott Wood17fed142016-05-30 13:57:56 -0500313 struct nand_chip *chip = mtd_to_nand(mtd);
Siva Durga Prasad Paladugu45e512c2018-01-04 16:04:21 +0530314 struct arasan_nand_info *nand = nand_get_controller_data(chip);
Siva Durga Prasad Paladuguc7b0bc72015-11-17 14:30:10 +0530315 u32 reg_val, i, pktsize, pktnum;
316 u32 *bufptr = (u32 *)buf;
317 u32 timeout;
318 u32 rdcount = 0;
319 u8 addr_cycles;
320
321 if (chip->ecc_step_ds >= ARASAN_NAND_PKTSIZE_1K)
322 pktsize = ARASAN_NAND_PKTSIZE_1K;
323 else
324 pktsize = ARASAN_NAND_PKTSIZE_512;
325
326 if (size % pktsize)
327 pktnum = size/pktsize + 1;
328 else
329 pktnum = size/pktsize;
330
331 reg_val = readl(&arasan_nand_base->intsts_enr);
332 reg_val |= ARASAN_NAND_INT_STS_ERR_EN_MASK |
333 ARASAN_NAND_INT_STS_MUL_BIT_ERR_MASK;
334 writel(reg_val, &arasan_nand_base->intsts_enr);
335
336 reg_val = readl(&arasan_nand_base->pkt_reg);
337 reg_val &= ~(ARASAN_NAND_PKT_REG_PKT_CNT_MASK |
338 ARASAN_NAND_PKT_REG_PKT_SIZE_MASK);
339 reg_val |= (pktnum << ARASAN_NAND_PKT_REG_PKT_CNT_SHFT) |
340 pktsize;
341 writel(reg_val, &arasan_nand_base->pkt_reg);
342
Siva Durga Prasad Paladugu45e512c2018-01-04 16:04:21 +0530343 if (!nand->on_die_ecc_enabled) {
344 arasan_nand_enable_ecc();
345 addr_cycles = arasan_nand_get_addrcycle(mtd);
346 if (addr_cycles == ARASAN_NAND_INVALID_ADDR_CYCL)
347 return ERR_ADDR_CYCLE;
Siva Durga Prasad Paladuguc7b0bc72015-11-17 14:30:10 +0530348
Siva Durga Prasad Paladugu45e512c2018-01-04 16:04:21 +0530349 writel((NAND_CMD_RNDOUTSTART << ARASAN_NAND_CMD_CMD2_SHIFT) |
350 NAND_CMD_RNDOUT | (addr_cycles <<
351 ARASAN_NAND_CMD_ADDR_CYCL_SHIFT),
352 &arasan_nand_base->ecc_sprcmd_reg);
353 }
Siva Durga Prasad Paladuguc7b0bc72015-11-17 14:30:10 +0530354 writel(curr_cmd->pgm, &arasan_nand_base->pgm_reg);
355
356 while (rdcount < pktnum) {
357 timeout = ARASAN_NAND_POLL_TIMEOUT;
358 while (!(readl(&arasan_nand_base->intsts_reg) &
359 ARASAN_NAND_INT_STS_BUF_RD_RDY_MASK) && timeout) {
360 udelay(1);
361 timeout--;
362 }
363 if (!timeout) {
364 puts("arasan_read_page: timedout:Buff RDY\n");
365 return -ETIMEDOUT;
366 }
367
368 rdcount++;
369
370 if (pktnum == rdcount) {
371 reg_val = readl(&arasan_nand_base->intsts_enr);
372 reg_val |= ARASAN_NAND_INT_STS_XFR_CMPLT_MASK;
373 writel(reg_val, &arasan_nand_base->intsts_enr);
374 } else {
375 reg_val = readl(&arasan_nand_base->intsts_enr);
376 writel(reg_val | ARASAN_NAND_INT_STS_BUF_RD_RDY_MASK,
377 &arasan_nand_base->intsts_enr);
378 }
379 reg_val = readl(&arasan_nand_base->intsts_reg);
380 writel(reg_val | ARASAN_NAND_INT_STS_BUF_RD_RDY_MASK,
381 &arasan_nand_base->intsts_reg);
382
383 for (i = 0; i < pktsize/4; i++)
384 bufptr[i] = readl(&arasan_nand_base->buf_dataport);
385
386
387 bufptr += pktsize/4;
388
389 if (rdcount >= pktnum)
390 break;
391
392 writel(ARASAN_NAND_INT_STS_BUF_RD_RDY_MASK,
393 &arasan_nand_base->intsts_enr);
394 }
395
396 timeout = ARASAN_NAND_POLL_TIMEOUT;
397
398 while (!(readl(&arasan_nand_base->intsts_reg) &
399 ARASAN_NAND_INT_STS_XFR_CMPLT_MASK) && timeout) {
400 udelay(1);
401 timeout--;
402 }
403 if (!timeout) {
404 puts("arasan rd_page timedout:Xfer CMPLT\n");
405 return -ETIMEDOUT;
406 }
407
408 reg_val = readl(&arasan_nand_base->intsts_enr);
409 writel(reg_val | ARASAN_NAND_INT_STS_XFR_CMPLT_MASK,
410 &arasan_nand_base->intsts_enr);
411 reg_val = readl(&arasan_nand_base->intsts_reg);
412 writel(reg_val | ARASAN_NAND_INT_STS_XFR_CMPLT_MASK,
413 &arasan_nand_base->intsts_reg);
414
Siva Durga Prasad Paladugu45e512c2018-01-04 16:04:21 +0530415 if (!nand->on_die_ecc_enabled) {
416 if (readl(&arasan_nand_base->intsts_reg) &
417 ARASAN_NAND_INT_STS_MUL_BIT_ERR_MASK) {
418 printf("arasan rd_page:sbiterror\n");
419 return -1;
420 }
Siva Durga Prasad Paladuguc7b0bc72015-11-17 14:30:10 +0530421
Siva Durga Prasad Paladugu45e512c2018-01-04 16:04:21 +0530422 if (readl(&arasan_nand_base->intsts_reg) &
423 ARASAN_NAND_INT_STS_ERR_EN_MASK) {
424 mtd->ecc_stats.failed++;
425 printf("arasan rd_page:multibiterror\n");
426 return -1;
427 }
Siva Durga Prasad Paladuguc7b0bc72015-11-17 14:30:10 +0530428 }
429
430 return 0;
431}
432
433static int arasan_nand_read_page_hwecc(struct mtd_info *mtd,
434 struct nand_chip *chip, u8 *buf, int oob_required, int page)
435{
436 int status;
437
438 status = arasan_nand_read_page(mtd, buf, (mtd->writesize));
439
440 if (oob_required)
441 chip->ecc.read_oob(mtd, chip, page);
442
443 return status;
444}
445
446static void arasan_nand_fill_tx(const u8 *buf, int len)
447{
448 u32 __iomem *nand = &arasan_nand_base->buf_dataport;
449
450 if (((unsigned long)buf & 0x3) != 0) {
451 if (((unsigned long)buf & 0x1) != 0) {
452 if (len) {
453 writeb(*buf, nand);
454 buf += 1;
455 len--;
456 }
457 }
458
459 if (((unsigned long)buf & 0x3) != 0) {
460 if (len >= 2) {
461 writew(*(u16 *)buf, nand);
462 buf += 2;
463 len -= 2;
464 }
465 }
466 }
467
468 while (len >= 4) {
469 writel(*(u32 *)buf, nand);
470 buf += 4;
471 len -= 4;
472 }
473
474 if (len) {
475 if (len >= 2) {
476 writew(*(u16 *)buf, nand);
477 buf += 2;
478 len -= 2;
479 }
480
481 if (len)
482 writeb(*buf, nand);
483 }
484}
485
486static int arasan_nand_write_page_hwecc(struct mtd_info *mtd,
Scott Wood46e13102016-05-30 13:57:57 -0500487 struct nand_chip *chip, const u8 *buf, int oob_required,
488 int page)
Siva Durga Prasad Paladuguc7b0bc72015-11-17 14:30:10 +0530489{
490 u32 reg_val, i, pktsize, pktnum;
491 const u32 *bufptr = (const u32 *)buf;
492 u32 timeout = ARASAN_NAND_POLL_TIMEOUT;
493 u32 size = mtd->writesize;
494 u32 rdcount = 0;
495 u8 column_addr_cycles;
Scott Wood17fed142016-05-30 13:57:56 -0500496 struct arasan_nand_info *nand = nand_get_controller_data(chip);
Siva Durga Prasad Paladuguc7b0bc72015-11-17 14:30:10 +0530497
498 if (chip->ecc_step_ds >= ARASAN_NAND_PKTSIZE_1K)
499 pktsize = ARASAN_NAND_PKTSIZE_1K;
500 else
501 pktsize = ARASAN_NAND_PKTSIZE_512;
502
503 if (size % pktsize)
504 pktnum = size/pktsize + 1;
505 else
506 pktnum = size/pktsize;
507
508 reg_val = readl(&arasan_nand_base->pkt_reg);
509 reg_val &= ~(ARASAN_NAND_PKT_REG_PKT_CNT_MASK |
510 ARASAN_NAND_PKT_REG_PKT_SIZE_MASK);
511 reg_val |= (pktnum << ARASAN_NAND_PKT_REG_PKT_CNT_SHFT) | pktsize;
512 writel(reg_val, &arasan_nand_base->pkt_reg);
513
Siva Durga Prasad Paladugu45e512c2018-01-04 16:04:21 +0530514 if (!nand->on_die_ecc_enabled) {
515 arasan_nand_enable_ecc();
516 column_addr_cycles = (chip->onfi_params.addr_cycles &
517 ARASAN_NAND_COL_ADDR_CYCL_MASK) >>
518 ARASAN_NAND_COL_ADDR_CYCL_SHIFT;
519 writel((NAND_CMD_RNDIN | (column_addr_cycles << 28)),
520 &arasan_nand_base->ecc_sprcmd_reg);
521 }
Siva Durga Prasad Paladuguc7b0bc72015-11-17 14:30:10 +0530522 writel(curr_cmd->pgm, &arasan_nand_base->pgm_reg);
523
524 while (rdcount < pktnum) {
525 timeout = ARASAN_NAND_POLL_TIMEOUT;
526 while (!(readl(&arasan_nand_base->intsts_reg) &
527 ARASAN_NAND_INT_STS_BUF_WR_RDY_MASK) && timeout) {
528 udelay(1);
529 timeout--;
530 }
531
532 if (!timeout) {
533 puts("arasan_write_page: timedout:Buff RDY\n");
534 return -ETIMEDOUT;
535 }
536
537 rdcount++;
538
539 if (pktnum == rdcount) {
540 reg_val = readl(&arasan_nand_base->intsts_enr);
541 reg_val |= ARASAN_NAND_INT_STS_XFR_CMPLT_MASK;
542 writel(reg_val, &arasan_nand_base->intsts_enr);
543 } else {
544 reg_val = readl(&arasan_nand_base->intsts_enr);
545 writel(reg_val | ARASAN_NAND_INT_STS_BUF_WR_RDY_MASK,
546 &arasan_nand_base->intsts_enr);
547 }
548
549 reg_val = readl(&arasan_nand_base->intsts_reg);
550 writel(reg_val | ARASAN_NAND_INT_STS_BUF_WR_RDY_MASK,
551 &arasan_nand_base->intsts_reg);
552
553 for (i = 0; i < pktsize/4; i++)
554 writel(bufptr[i], &arasan_nand_base->buf_dataport);
555
556 bufptr += pktsize/4;
557
558 if (rdcount >= pktnum)
559 break;
560
561 writel(ARASAN_NAND_INT_STS_BUF_WR_RDY_MASK,
562 &arasan_nand_base->intsts_enr);
563 }
564
565 timeout = ARASAN_NAND_POLL_TIMEOUT;
566
567 while (!(readl(&arasan_nand_base->intsts_reg) &
568 ARASAN_NAND_INT_STS_XFR_CMPLT_MASK) && timeout) {
569 udelay(1);
570 timeout--;
571 }
572 if (!timeout) {
573 puts("arasan write_page timedout:Xfer CMPLT\n");
574 return -ETIMEDOUT;
575 }
576
577 reg_val = readl(&arasan_nand_base->intsts_enr);
578 writel(reg_val | ARASAN_NAND_INT_STS_XFR_CMPLT_MASK,
579 &arasan_nand_base->intsts_enr);
580 reg_val = readl(&arasan_nand_base->intsts_reg);
581 writel(reg_val | ARASAN_NAND_INT_STS_XFR_CMPLT_MASK,
582 &arasan_nand_base->intsts_reg);
583
584 if (oob_required)
585 chip->ecc.write_oob(mtd, chip, nand->page);
586
587 return 0;
588}
589
590static int arasan_nand_read_oob(struct mtd_info *mtd, struct nand_chip *chip,
591 int page)
592{
593 chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page);
594 chip->read_buf(mtd, chip->oob_poi, (mtd->oobsize));
595
596 return 0;
597}
598
599static int arasan_nand_write_oob(struct mtd_info *mtd, struct nand_chip *chip,
600 int page)
601{
602 int status = 0;
603 const u8 *buf = chip->oob_poi;
604
605 chip->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize, page);
606 chip->write_buf(mtd, buf, mtd->oobsize);
607
608 return status;
609}
610
611static int arasan_nand_reset(struct arasan_nand_command_format *curr_cmd)
612{
613 u32 timeout = ARASAN_NAND_POLL_TIMEOUT;
614 u32 cmd_reg = 0;
615
616 writel(ARASAN_NAND_INT_STS_XFR_CMPLT_MASK,
617 &arasan_nand_base->intsts_enr);
618 cmd_reg = readl(&arasan_nand_base->cmd_reg);
619 cmd_reg &= ~ARASAN_NAND_CMD_CMD12_MASK;
620
621 cmd_reg |= curr_cmd->cmd1 |
622 (curr_cmd->cmd2 << ARASAN_NAND_CMD_CMD2_SHIFT);
623 writel(cmd_reg, &arasan_nand_base->cmd_reg);
624 writel(curr_cmd->pgm, &arasan_nand_base->pgm_reg);
625
626 while (!(readl(&arasan_nand_base->intsts_reg) &
627 ARASAN_NAND_INT_STS_XFR_CMPLT_MASK) && timeout) {
628 udelay(1);
629 timeout--;
630 }
631 if (!timeout) {
632 printf("ERROR:%s timedout\n", __func__);
633 return -ETIMEDOUT;
634 }
635
636 writel(ARASAN_NAND_INT_STS_XFR_CMPLT_MASK,
637 &arasan_nand_base->intsts_enr);
638
639 writel(ARASAN_NAND_INT_STS_XFR_CMPLT_MASK,
640 &arasan_nand_base->intsts_reg);
641
642 return 0;
643}
644
645static u8 arasan_nand_page(struct mtd_info *mtd)
646{
647 u8 page_val = 0;
648
649 switch (mtd->writesize) {
650 case 512:
651 page_val = 0;
652 break;
653 case 2048:
654 page_val = 1;
655 break;
656 case 4096:
657 page_val = 2;
658 break;
659 case 8192:
660 page_val = 3;
661 break;
662 case 16384:
663 page_val = 4;
664 break;
665 case 1024:
666 page_val = 5;
667 break;
668 default:
669 printf("%s:Pagesize>16K\n", __func__);
670 break;
671 }
672
673 return page_val;
674}
675
676static int arasan_nand_send_wrcmd(struct arasan_nand_command_format *curr_cmd,
677 int column, int page_addr, struct mtd_info *mtd)
678{
679 u32 reg_val, page;
680 u8 page_val, addr_cycles;
681
682 writel(ARASAN_NAND_INT_STS_BUF_WR_RDY_MASK,
683 &arasan_nand_base->intsts_enr);
684 reg_val = readl(&arasan_nand_base->cmd_reg);
685 reg_val &= ~ARASAN_NAND_CMD_CMD12_MASK;
686 reg_val |= curr_cmd->cmd1 |
687 (curr_cmd->cmd2 << ARASAN_NAND_CMD_CMD2_SHIFT);
688 if (curr_cmd->cmd1 == NAND_CMD_SEQIN) {
689 reg_val &= ~ARASAN_NAND_CMD_PG_SIZE_MASK;
690 page_val = arasan_nand_page(mtd);
691 reg_val |= (page_val << ARASAN_NAND_CMD_PG_SIZE_SHIFT);
692 }
693
694 reg_val &= ~ARASAN_NAND_CMD_ADDR_CYCL_MASK;
695 addr_cycles = arasan_nand_get_addrcycle(mtd);
696
697 if (addr_cycles == ARASAN_NAND_INVALID_ADDR_CYCL)
698 return ERR_ADDR_CYCLE;
699
700 reg_val |= (addr_cycles <<
701 ARASAN_NAND_CMD_ADDR_CYCL_SHIFT);
702 writel(reg_val, &arasan_nand_base->cmd_reg);
703
704 if (page_addr == -1)
705 page_addr = 0;
706
707 page = (page_addr << ARASAN_NAND_MEM_ADDR1_PAGE_SHIFT) &
708 ARASAN_NAND_MEM_ADDR1_PAGE_MASK;
709 column &= ARASAN_NAND_MEM_ADDR1_COL_MASK;
710 writel(page|column, &arasan_nand_base->memadr_reg1);
711
712 reg_val = readl(&arasan_nand_base->memadr_reg2);
713 reg_val &= ~ARASAN_NAND_MEM_ADDR2_PAGE_MASK;
714 reg_val |= (page_addr >> ARASAN_NAND_MEM_ADDR1_PAGE_SHIFT);
715 writel(reg_val, &arasan_nand_base->memadr_reg2);
716 reg_val = readl(&arasan_nand_base->memadr_reg2);
717 reg_val &= ~ARASAN_NAND_MEM_ADDR2_CS_MASK;
718 writel(reg_val, &arasan_nand_base->memadr_reg2);
719
720 return 0;
721}
722
723static void arasan_nand_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
724{
725 u32 reg_val;
726 u32 timeout = ARASAN_NAND_POLL_TIMEOUT;
727
728 reg_val = readl(&arasan_nand_base->pkt_reg);
729 reg_val &= ~(ARASAN_NAND_PKT_REG_PKT_CNT_MASK |
730 ARASAN_NAND_PKT_REG_PKT_SIZE_MASK);
731
732 reg_val |= (1 << ARASAN_NAND_PKT_REG_PKT_CNT_SHFT) | len;
733 writel(reg_val, &arasan_nand_base->pkt_reg);
734 writel(curr_cmd->pgm, &arasan_nand_base->pgm_reg);
735
736 while (!(readl(&arasan_nand_base->intsts_reg) &
737 ARASAN_NAND_INT_STS_BUF_WR_RDY_MASK) && timeout) {
738 udelay(1);
739 timeout--;
740 }
741
742 if (!timeout)
743 puts("ERROR:arasan_nand_write_buf timedout:Buff RDY\n");
744
745 reg_val = readl(&arasan_nand_base->intsts_enr);
746 reg_val |= ARASAN_NAND_INT_STS_XFR_CMPLT_MASK;
747 writel(reg_val, &arasan_nand_base->intsts_enr);
748 writel(reg_val | ARASAN_NAND_INT_STS_BUF_WR_RDY_MASK,
749 &arasan_nand_base->intsts_enr);
750 reg_val = readl(&arasan_nand_base->intsts_reg);
751 writel(reg_val | ARASAN_NAND_INT_STS_BUF_WR_RDY_MASK,
752 &arasan_nand_base->intsts_reg);
753
754 arasan_nand_fill_tx(buf, len);
755
756 timeout = ARASAN_NAND_POLL_TIMEOUT;
757 while (!(readl(&arasan_nand_base->intsts_reg) &
758 ARASAN_NAND_INT_STS_XFR_CMPLT_MASK) && timeout) {
759 udelay(1);
760 timeout--;
761 }
762 if (!timeout)
763 puts("ERROR:arasan_nand_write_buf timedout:Xfer CMPLT\n");
764
765 writel(readl(&arasan_nand_base->intsts_enr) |
766 ARASAN_NAND_INT_STS_XFR_CMPLT_MASK,
767 &arasan_nand_base->intsts_enr);
768 writel(readl(&arasan_nand_base->intsts_reg) |
769 ARASAN_NAND_INT_STS_XFR_CMPLT_MASK,
770 &arasan_nand_base->intsts_reg);
771}
772
773static int arasan_nand_erase(struct arasan_nand_command_format *curr_cmd,
774 int column, int page_addr, struct mtd_info *mtd)
775{
776 u32 reg_val, page;
777 u32 timeout = ARASAN_NAND_POLL_TIMEOUT;
778 u8 row_addr_cycles;
779
780 writel(ARASAN_NAND_INT_STS_XFR_CMPLT_MASK,
781 &arasan_nand_base->intsts_enr);
782 reg_val = readl(&arasan_nand_base->cmd_reg);
783 reg_val &= ~ARASAN_NAND_CMD_CMD12_MASK;
784 reg_val |= curr_cmd->cmd1 |
785 (curr_cmd->cmd2 << ARASAN_NAND_CMD_CMD2_SHIFT);
786 row_addr_cycles = arasan_nand_get_addrcycle(mtd);
787
788 if (row_addr_cycles == ARASAN_NAND_INVALID_ADDR_CYCL)
789 return ERR_ADDR_CYCLE;
790
791 reg_val &= ~ARASAN_NAND_CMD_ADDR_CYCL_MASK;
792 reg_val |= (row_addr_cycles <<
793 ARASAN_NAND_CMD_ADDR_CYCL_SHIFT);
794
795 writel(reg_val, &arasan_nand_base->cmd_reg);
796
Vipul Kumar673a5c22018-03-05 15:24:59 +0530797 page = (page_addr >> ARASAN_NAND_MEM_ADDR1_PAGE_SHIFT) &
Vipul Kumar9d9b99b2018-03-10 17:52:23 +0530798 ARASAN_NAND_MEM_ADDR1_COL_MASK;
Siva Durga Prasad Paladuguc7b0bc72015-11-17 14:30:10 +0530799 column = page_addr & ARASAN_NAND_MEM_ADDR1_COL_MASK;
Vipul Kumar673a5c22018-03-05 15:24:59 +0530800 writel(column | (page << ARASAN_NAND_MEM_ADDR1_PAGE_SHIFT),
801 &arasan_nand_base->memadr_reg1);
Siva Durga Prasad Paladuguc7b0bc72015-11-17 14:30:10 +0530802
803 reg_val = readl(&arasan_nand_base->memadr_reg2);
804 reg_val &= ~ARASAN_NAND_MEM_ADDR2_PAGE_MASK;
805 reg_val |= (page_addr >> ARASAN_NAND_MEM_ADDR1_PAGE_SHIFT);
806 writel(reg_val, &arasan_nand_base->memadr_reg2);
807 reg_val = readl(&arasan_nand_base->memadr_reg2);
808 reg_val &= ~ARASAN_NAND_MEM_ADDR2_CS_MASK;
809 writel(reg_val, &arasan_nand_base->memadr_reg2);
810 writel(curr_cmd->pgm, &arasan_nand_base->pgm_reg);
811
812 while (!(readl(&arasan_nand_base->intsts_reg) &
813 ARASAN_NAND_INT_STS_XFR_CMPLT_MASK) && timeout) {
814 udelay(1);
815 timeout--;
816 }
817 if (!timeout) {
818 printf("ERROR:%s timedout:Xfer CMPLT\n", __func__);
819 return -ETIMEDOUT;
820 }
821
822 reg_val = readl(&arasan_nand_base->intsts_enr);
823 writel(reg_val | ARASAN_NAND_INT_STS_XFR_CMPLT_MASK,
824 &arasan_nand_base->intsts_enr);
825 reg_val = readl(&arasan_nand_base->intsts_reg);
826 writel(reg_val | ARASAN_NAND_INT_STS_XFR_CMPLT_MASK,
827 &arasan_nand_base->intsts_reg);
828
829 return 0;
830}
831
832static int arasan_nand_read_status(struct arasan_nand_command_format *curr_cmd,
833 int column, int page_addr, struct mtd_info *mtd)
834{
835 u32 reg_val;
836 u32 timeout = ARASAN_NAND_POLL_TIMEOUT;
837 u8 addr_cycles;
838
839 writel(ARASAN_NAND_INT_STS_XFR_CMPLT_MASK,
840 &arasan_nand_base->intsts_enr);
841 reg_val = readl(&arasan_nand_base->cmd_reg);
842 reg_val &= ~ARASAN_NAND_CMD_CMD12_MASK;
843 reg_val |= curr_cmd->cmd1 |
844 (curr_cmd->cmd2 << ARASAN_NAND_CMD_CMD2_SHIFT);
845 addr_cycles = arasan_nand_get_addrcycle(mtd);
846
847 if (addr_cycles == ARASAN_NAND_INVALID_ADDR_CYCL)
848 return ERR_ADDR_CYCLE;
849
850 reg_val &= ~ARASAN_NAND_CMD_ADDR_CYCL_MASK;
851 reg_val |= (addr_cycles <<
852 ARASAN_NAND_CMD_ADDR_CYCL_SHIFT);
853
854 writel(reg_val, &arasan_nand_base->cmd_reg);
855
856 reg_val = readl(&arasan_nand_base->pkt_reg);
857 reg_val &= ~(ARASAN_NAND_PKT_REG_PKT_CNT_MASK |
858 ARASAN_NAND_PKT_REG_PKT_SIZE_MASK);
859 reg_val |= (1 << ARASAN_NAND_PKT_REG_PKT_CNT_SHFT) | 1;
860 writel(reg_val, &arasan_nand_base->pkt_reg);
861
862 reg_val = readl(&arasan_nand_base->memadr_reg2);
863 reg_val &= ~ARASAN_NAND_MEM_ADDR2_CS_MASK;
864 writel(reg_val, &arasan_nand_base->memadr_reg2);
865
866 writel(curr_cmd->pgm, &arasan_nand_base->pgm_reg);
867 while (!(readl(&arasan_nand_base->intsts_reg) &
868 ARASAN_NAND_INT_STS_XFR_CMPLT_MASK) && timeout) {
869 udelay(1);
870 timeout--;
871 }
872
873 if (!timeout) {
874 printf("ERROR:%s: timedout:Xfer CMPLT\n", __func__);
875 return -ETIMEDOUT;
876 }
877
878 reg_val = readl(&arasan_nand_base->intsts_enr);
879 writel(reg_val | ARASAN_NAND_INT_STS_XFR_CMPLT_MASK,
880 &arasan_nand_base->intsts_enr);
881 reg_val = readl(&arasan_nand_base->intsts_reg);
882 writel(reg_val | ARASAN_NAND_INT_STS_XFR_CMPLT_MASK,
883 &arasan_nand_base->intsts_reg);
884
885 return 0;
886}
887
888static int arasan_nand_send_rdcmd(struct arasan_nand_command_format *curr_cmd,
889 int column, int page_addr, struct mtd_info *mtd)
890{
891 u32 reg_val, addr_cycles, page;
892 u8 page_val;
893
894 reg_val = readl(&arasan_nand_base->intsts_enr);
895 writel(reg_val | ARASAN_NAND_INT_STS_BUF_RD_RDY_MASK,
896 &arasan_nand_base->intsts_enr);
897
898 reg_val = readl(&arasan_nand_base->cmd_reg);
899 reg_val &= ~ARASAN_NAND_CMD_CMD12_MASK;
900 reg_val |= curr_cmd->cmd1 |
901 (curr_cmd->cmd2 << ARASAN_NAND_CMD_CMD2_SHIFT);
902
903 if (curr_cmd->cmd1 == NAND_CMD_RNDOUT ||
904 curr_cmd->cmd1 == NAND_CMD_READ0) {
905 reg_val &= ~ARASAN_NAND_CMD_PG_SIZE_MASK;
906 page_val = arasan_nand_page(mtd);
907 reg_val |= (page_val << ARASAN_NAND_CMD_PG_SIZE_SHIFT);
908 }
909
Siva Durga Prasad Paladugu99459c22016-08-25 16:00:04 +0530910 reg_val &= ~ARASAN_NAND_CMD_ECC_ON_MASK;
911
Siva Durga Prasad Paladuguc7b0bc72015-11-17 14:30:10 +0530912 reg_val &= ~ARASAN_NAND_CMD_ADDR_CYCL_MASK;
913
914 addr_cycles = arasan_nand_get_addrcycle(mtd);
915
916 if (addr_cycles == ARASAN_NAND_INVALID_ADDR_CYCL)
917 return ERR_ADDR_CYCLE;
918
919 reg_val |= (addr_cycles << 28);
920 writel(reg_val, &arasan_nand_base->cmd_reg);
921
922 if (page_addr == -1)
923 page_addr = 0;
924
925 page = (page_addr << ARASAN_NAND_MEM_ADDR1_PAGE_SHIFT) &
926 ARASAN_NAND_MEM_ADDR1_PAGE_MASK;
927 column &= ARASAN_NAND_MEM_ADDR1_COL_MASK;
928 writel(page | column, &arasan_nand_base->memadr_reg1);
929
930 reg_val = readl(&arasan_nand_base->memadr_reg2);
931 reg_val &= ~ARASAN_NAND_MEM_ADDR2_PAGE_MASK;
932 reg_val |= (page_addr >> ARASAN_NAND_MEM_ADDR1_PAGE_SHIFT);
933 writel(reg_val, &arasan_nand_base->memadr_reg2);
934
935 reg_val = readl(&arasan_nand_base->memadr_reg2);
936 reg_val &= ~ARASAN_NAND_MEM_ADDR2_CS_MASK;
937 writel(reg_val, &arasan_nand_base->memadr_reg2);
938 buf_index = 0;
939
940 return 0;
941}
942
943static void arasan_nand_read_buf(struct mtd_info *mtd, u8 *buf, int size)
944{
945 u32 reg_val, i;
946 u32 *bufptr = (u32 *)buf;
947 u32 timeout = ARASAN_NAND_POLL_TIMEOUT;
948
949 reg_val = readl(&arasan_nand_base->pkt_reg);
950 reg_val &= ~(ARASAN_NAND_PKT_REG_PKT_CNT_MASK |
951 ARASAN_NAND_PKT_REG_PKT_SIZE_MASK);
952 reg_val |= (1 << ARASAN_NAND_PKT_REG_PKT_CNT_SHFT) | size;
953 writel(reg_val, &arasan_nand_base->pkt_reg);
954
955 writel(curr_cmd->pgm, &arasan_nand_base->pgm_reg);
956
957 while (!(readl(&arasan_nand_base->intsts_reg) &
958 ARASAN_NAND_INT_STS_BUF_RD_RDY_MASK) && timeout) {
959 udelay(1);
960 timeout--;
961 }
962
963 if (!timeout)
964 puts("ERROR:arasan_nand_read_buf timedout:Buff RDY\n");
965
966 reg_val = readl(&arasan_nand_base->intsts_enr);
967 reg_val |= ARASAN_NAND_INT_STS_XFR_CMPLT_MASK;
968 writel(reg_val, &arasan_nand_base->intsts_enr);
969
970 writel(reg_val | ARASAN_NAND_INT_STS_BUF_RD_RDY_MASK,
971 &arasan_nand_base->intsts_enr);
972 reg_val = readl(&arasan_nand_base->intsts_reg);
973 writel(reg_val | ARASAN_NAND_INT_STS_BUF_RD_RDY_MASK,
974 &arasan_nand_base->intsts_reg);
975
976 buf_index = 0;
977 for (i = 0; i < size / 4; i++)
978 bufptr[i] = readl(&arasan_nand_base->buf_dataport);
979
980 if (size & 0x03)
981 bufptr[i] = readl(&arasan_nand_base->buf_dataport);
982
983 timeout = ARASAN_NAND_POLL_TIMEOUT;
984
985 while (!(readl(&arasan_nand_base->intsts_reg) &
986 ARASAN_NAND_INT_STS_XFR_CMPLT_MASK) && timeout) {
987 udelay(1);
988 timeout--;
989 }
990
991 if (!timeout)
992 puts("ERROR:arasan_nand_read_buf timedout:Xfer CMPLT\n");
993
994 reg_val = readl(&arasan_nand_base->intsts_enr);
995 writel(reg_val | ARASAN_NAND_INT_STS_XFR_CMPLT_MASK,
996 &arasan_nand_base->intsts_enr);
997 reg_val = readl(&arasan_nand_base->intsts_reg);
998 writel(reg_val | ARASAN_NAND_INT_STS_XFR_CMPLT_MASK,
999 &arasan_nand_base->intsts_reg);
1000}
1001
1002static u8 arasan_nand_read_byte(struct mtd_info *mtd)
1003{
Scott Wood17fed142016-05-30 13:57:56 -05001004 struct nand_chip *chip = mtd_to_nand(mtd);
Siva Durga Prasad Paladuguc7b0bc72015-11-17 14:30:10 +05301005 u32 size;
1006 u8 val;
1007 struct nand_onfi_params *p;
1008
1009 if (buf_index == 0) {
1010 p = &chip->onfi_params;
1011 if (curr_cmd->cmd1 == NAND_CMD_READID)
1012 size = 4;
1013 else if (curr_cmd->cmd1 == NAND_CMD_PARAM)
1014 size = sizeof(struct nand_onfi_params);
1015 else if (curr_cmd->cmd1 == NAND_CMD_RNDOUT)
1016 size = le16_to_cpu(p->ext_param_page_length) * 16;
1017 else if (curr_cmd->cmd1 == NAND_CMD_GET_FEATURES)
1018 size = 4;
1019 else if (curr_cmd->cmd1 == NAND_CMD_STATUS)
1020 return readb(&arasan_nand_base->flash_sts_reg);
1021 else
1022 size = 8;
1023 chip->read_buf(mtd, &buf_data[0], size);
1024 }
1025
1026 val = *(&buf_data[0] + buf_index);
1027 buf_index++;
1028
1029 return val;
1030}
1031
1032static void arasan_nand_cmd_function(struct mtd_info *mtd, unsigned int command,
1033 int column, int page_addr)
1034{
1035 u32 i, ret = 0;
Scott Wood17fed142016-05-30 13:57:56 -05001036 struct nand_chip *chip = mtd_to_nand(mtd);
1037 struct arasan_nand_info *nand = nand_get_controller_data(chip);
Siva Durga Prasad Paladuguc7b0bc72015-11-17 14:30:10 +05301038
1039 curr_cmd = NULL;
1040 writel(ARASAN_NAND_INT_STS_XFR_CMPLT_MASK,
1041 &arasan_nand_base->intsts_enr);
1042
1043 if ((command == NAND_CMD_READOOB) &&
1044 (mtd->writesize > 512)) {
1045 column += mtd->writesize;
1046 command = NAND_CMD_READ0;
1047 }
1048
1049 /* Get the command format */
1050 for (i = 0; (arasan_nand_commands[i].cmd1 != NAND_CMD_NONE ||
1051 arasan_nand_commands[i].cmd2 != NAND_CMD_NONE); i++) {
1052 if (command == arasan_nand_commands[i].cmd1) {
1053 curr_cmd = &arasan_nand_commands[i];
1054 break;
1055 }
1056 }
1057
1058 if (curr_cmd == NULL) {
1059 printf("Unsupported Command; 0x%x\n", command);
1060 return;
1061 }
1062
1063 if (curr_cmd->cmd1 == NAND_CMD_RESET)
1064 ret = arasan_nand_reset(curr_cmd);
1065
1066 if ((curr_cmd->cmd1 == NAND_CMD_READID) ||
1067 (curr_cmd->cmd1 == NAND_CMD_PARAM) ||
1068 (curr_cmd->cmd1 == NAND_CMD_RNDOUT) ||
1069 (curr_cmd->cmd1 == NAND_CMD_GET_FEATURES) ||
1070 (curr_cmd->cmd1 == NAND_CMD_READ0))
1071 ret = arasan_nand_send_rdcmd(curr_cmd, column, page_addr, mtd);
1072
1073 if ((curr_cmd->cmd1 == NAND_CMD_SET_FEATURES) ||
1074 (curr_cmd->cmd1 == NAND_CMD_SEQIN)) {
1075 nand->page = page_addr;
1076 ret = arasan_nand_send_wrcmd(curr_cmd, column, page_addr, mtd);
1077 }
1078
1079 if (curr_cmd->cmd1 == NAND_CMD_ERASE1)
1080 ret = arasan_nand_erase(curr_cmd, column, page_addr, mtd);
1081
1082 if (curr_cmd->cmd1 == NAND_CMD_STATUS)
1083 ret = arasan_nand_read_status(curr_cmd, column, page_addr, mtd);
1084
1085 if (ret != 0)
1086 printf("ERROR:%s:command:0x%x\n", __func__, curr_cmd->cmd1);
1087}
1088
Siva Durga Prasad Paladugu45e512c2018-01-04 16:04:21 +05301089static void arasan_check_ondie(struct mtd_info *mtd)
1090{
1091 struct nand_chip *nand_chip = mtd_to_nand(mtd);
1092 struct arasan_nand_info *nand = nand_get_controller_data(nand_chip);
1093 u8 maf_id, dev_id;
1094 u8 get_feature[4];
1095 u8 set_feature[4] = {ENABLE_ONDIE_ECC, 0x00, 0x00, 0x00};
1096 u32 i;
1097
1098 /* Send the command for reading device ID */
1099 nand_chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
1100 nand_chip->cmdfunc(mtd, NAND_CMD_READID, 0, -1);
1101
1102 /* Read manufacturer and device IDs */
1103 maf_id = nand_chip->read_byte(mtd);
1104 dev_id = nand_chip->read_byte(mtd);
1105
1106 if ((maf_id == NAND_MFR_MICRON) &&
1107 ((dev_id == 0xf1) || (dev_id == 0xa1) || (dev_id == 0xb1) ||
1108 (dev_id == 0xaa) || (dev_id == 0xba) || (dev_id == 0xda) ||
1109 (dev_id == 0xca) || (dev_id == 0xac) || (dev_id == 0xbc) ||
1110 (dev_id == 0xdc) || (dev_id == 0xcc) || (dev_id == 0xa3) ||
1111 (dev_id == 0xb3) || (dev_id == 0xd3) || (dev_id == 0xc3))) {
1112 nand_chip->cmdfunc(mtd, NAND_CMD_SET_FEATURES,
1113 ONDIE_ECC_FEATURE_ADDR, -1);
1114
1115 nand_chip->write_buf(mtd, &set_feature[0], 4);
1116 nand_chip->cmdfunc(mtd, NAND_CMD_GET_FEATURES,
1117 ONDIE_ECC_FEATURE_ADDR, -1);
1118
1119 for (i = 0; i < 4; i++)
1120 get_feature[i] = nand_chip->read_byte(mtd);
1121
1122 if (get_feature[0] & ENABLE_ONDIE_ECC)
1123 nand->on_die_ecc_enabled = true;
1124 else
1125 printf("%s: Unable to enable OnDie ECC\n", __func__);
1126
1127 /* Use the BBT pattern descriptors */
1128 nand_chip->bbt_td = &bbt_main_descr;
1129 nand_chip->bbt_md = &bbt_mirror_descr;
1130 }
1131}
1132
Siva Durga Prasad Paladuguc7b0bc72015-11-17 14:30:10 +05301133static int arasan_nand_ecc_init(struct mtd_info *mtd)
1134{
1135 int found = -1;
Siva Durga Prasad Paladugub0a4f132018-01-04 16:04:22 +05301136 u32 regval, eccpos_start, i, eccaddr;
Scott Wood17fed142016-05-30 13:57:56 -05001137 struct nand_chip *nand_chip = mtd_to_nand(mtd);
Siva Durga Prasad Paladuguc7b0bc72015-11-17 14:30:10 +05301138
Siva Durga Prasad Paladuguc7b0bc72015-11-17 14:30:10 +05301139 for (i = 0; i < ARRAY_SIZE(ecc_matrix); i++) {
1140 if ((ecc_matrix[i].pagesize == mtd->writesize) &&
1141 (ecc_matrix[i].ecc_codeword_size >=
1142 nand_chip->ecc_step_ds)) {
1143 if (ecc_matrix[i].eccbits >=
1144 nand_chip->ecc_strength_ds) {
1145 found = i;
1146 break;
1147 }
1148 found = i;
1149 }
1150 }
1151
1152 if (found < 0)
1153 return 1;
1154
Siva Durga Prasad Paladugub0a4f132018-01-04 16:04:22 +05301155 eccaddr = mtd->writesize + mtd->oobsize -
1156 ecc_matrix[found].eccsize;
1157
1158 regval = eccaddr |
Siva Durga Prasad Paladugudb796632016-05-25 15:20:38 +05301159 (ecc_matrix[found].eccsize << ARASAN_NAND_ECC_SIZE_SHIFT) |
1160 (ecc_matrix[found].bch << ARASAN_NAND_ECC_BCH_SHIFT);
Siva Durga Prasad Paladuguc7b0bc72015-11-17 14:30:10 +05301161 writel(regval, &arasan_nand_base->ecc_reg);
1162
Siva Durga Prasad Paladugudb796632016-05-25 15:20:38 +05301163 if (ecc_matrix[found].bch) {
Siva Durga Prasad Paladuguc7b0bc72015-11-17 14:30:10 +05301164 regval = readl(&arasan_nand_base->memadr_reg2);
1165 regval &= ~ARASAN_NAND_MEM_ADDR2_BCH_MASK;
Siva Durga Prasad Paladugudb796632016-05-25 15:20:38 +05301166 regval |= (ecc_matrix[found].bchval <<
Siva Durga Prasad Paladuguc7b0bc72015-11-17 14:30:10 +05301167 ARASAN_NAND_MEM_ADDR2_BCH_SHIFT);
1168 writel(regval, &arasan_nand_base->memadr_reg2);
1169 }
1170
Siva Durga Prasad Paladugudb796632016-05-25 15:20:38 +05301171 nand_oob.eccbytes = ecc_matrix[found].eccsize;
Siva Durga Prasad Paladuguc7b0bc72015-11-17 14:30:10 +05301172 eccpos_start = mtd->oobsize - nand_oob.eccbytes;
1173
1174 for (i = 0; i < nand_oob.eccbytes; i++)
1175 nand_oob.eccpos[i] = eccpos_start + i;
1176
1177 nand_oob.oobfree[0].offset = 2;
1178 nand_oob.oobfree[0].length = eccpos_start - 2;
1179
Siva Durga Prasad Paladugudb796632016-05-25 15:20:38 +05301180 nand_chip->ecc.size = ecc_matrix[found].ecc_codeword_size;
1181 nand_chip->ecc.strength = ecc_matrix[found].eccbits;
1182 nand_chip->ecc.bytes = ecc_matrix[found].eccsize;
Siva Durga Prasad Paladuguc7b0bc72015-11-17 14:30:10 +05301183 nand_chip->ecc.layout = &nand_oob;
1184
1185 return 0;
1186}
1187
1188static int arasan_nand_init(struct nand_chip *nand_chip, int devnum)
1189{
1190 struct arasan_nand_info *nand;
1191 struct mtd_info *mtd;
1192 int err = -1;
1193
1194 nand = calloc(1, sizeof(struct arasan_nand_info));
1195 if (!nand) {
1196 printf("%s: failed to allocate\n", __func__);
1197 return err;
1198 }
1199
1200 nand->nand_base = arasan_nand_base;
Scott Wood17fed142016-05-30 13:57:56 -05001201 mtd = nand_to_mtd(nand_chip);
1202 nand_set_controller_data(nand_chip, nand);
Siva Durga Prasad Paladuguc7b0bc72015-11-17 14:30:10 +05301203
1204 /* Set the driver entry points for MTD */
1205 nand_chip->cmdfunc = arasan_nand_cmd_function;
1206 nand_chip->select_chip = arasan_nand_select_chip;
1207 nand_chip->read_byte = arasan_nand_read_byte;
1208
1209 /* Buffer read/write routines */
1210 nand_chip->read_buf = arasan_nand_read_buf;
1211 nand_chip->write_buf = arasan_nand_write_buf;
1212 nand_chip->bbt_options = NAND_BBT_USE_FLASH;
1213
1214 writel(0x0, &arasan_nand_base->cmd_reg);
1215 writel(0x0, &arasan_nand_base->pgm_reg);
1216
1217 /* first scan to find the device and get the page size */
1218 if (nand_scan_ident(mtd, 1, NULL)) {
1219 printf("%s: nand_scan_ident failed\n", __func__);
1220 goto fail;
1221 }
1222
Siva Durga Prasad Paladugu80c889c2018-01-04 16:04:20 +05301223 nand_chip->ecc.mode = NAND_ECC_HW;
1224 nand_chip->ecc.hwctl = NULL;
1225 nand_chip->ecc.read_page = arasan_nand_read_page_hwecc;
1226 nand_chip->ecc.write_page = arasan_nand_write_page_hwecc;
1227 nand_chip->ecc.read_oob = arasan_nand_read_oob;
1228 nand_chip->ecc.write_oob = arasan_nand_write_oob;
1229
Siva Durga Prasad Paladugu45e512c2018-01-04 16:04:21 +05301230 arasan_check_ondie(mtd);
1231
1232 /*
1233 * If on die supported, then give priority to on-die ecc and use
1234 * it instead of controller ecc.
1235 */
1236 if (nand->on_die_ecc_enabled) {
1237 nand_chip->ecc.strength = 1;
1238 nand_chip->ecc.size = mtd->writesize;
1239 nand_chip->ecc.bytes = 0;
1240 nand_chip->ecc.layout = &ondie_nand_oob_64;
1241 } else {
1242 if (arasan_nand_ecc_init(mtd)) {
1243 printf("%s: nand_ecc_init failed\n", __func__);
1244 goto fail;
1245 }
Siva Durga Prasad Paladuguc7b0bc72015-11-17 14:30:10 +05301246 }
1247
1248 if (nand_scan_tail(mtd)) {
1249 printf("%s: nand_scan_tail failed\n", __func__);
1250 goto fail;
1251 }
1252
Scott Wood2c1b7e12016-05-30 13:57:55 -05001253 if (nand_register(devnum, mtd)) {
Siva Durga Prasad Paladuguc7b0bc72015-11-17 14:30:10 +05301254 printf("Nand Register Fail\n");
1255 goto fail;
1256 }
1257
1258 return 0;
1259fail:
1260 free(nand);
1261 return err;
1262}
1263
1264void board_nand_init(void)
1265{
1266 struct nand_chip *nand = &nand_chip[0];
1267
1268 if (arasan_nand_init(nand, 0))
1269 puts("NAND init failed\n");
1270}