]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blame - drivers/mtd/nand/sh_flctl.c
mtd: sh_flctl: Implement NAND_CMD_RNDOUT command
[mirror_ubuntu-artful-kernel.git] / drivers / mtd / nand / sh_flctl.c
CommitLineData
6028aa01
YS
1/*
2 * SuperH FLCTL nand controller
3 *
b79c7adf
MD
4 * Copyright (c) 2008 Renesas Solutions Corp.
5 * Copyright (c) 2008 Atom Create Engineering Co., Ltd.
6028aa01 6 *
b79c7adf 7 * Based on fsl_elbc_nand.c, Copyright (c) 2006-2007 Freescale Semiconductor
6028aa01
YS
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; version 2 of the License.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 *
22 */
23
24#include <linux/module.h>
25#include <linux/kernel.h>
26#include <linux/delay.h>
27#include <linux/io.h>
28#include <linux/platform_device.h>
5a0e3ad6 29#include <linux/slab.h>
6028aa01
YS
30
31#include <linux/mtd/mtd.h>
32#include <linux/mtd/nand.h>
33#include <linux/mtd/partitions.h>
34#include <linux/mtd/sh_flctl.h>
35
36static struct nand_ecclayout flctl_4secc_oob_16 = {
37 .eccbytes = 10,
38 .eccpos = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9},
39 .oobfree = {
40 {.offset = 12,
41 . length = 4} },
42};
43
44static struct nand_ecclayout flctl_4secc_oob_64 = {
45 .eccbytes = 10,
46 .eccpos = {48, 49, 50, 51, 52, 53, 54, 55, 56, 57},
47 .oobfree = {
48 {.offset = 60,
49 . length = 4} },
50};
51
52static uint8_t scan_ff_pattern[] = { 0xff, 0xff };
53
54static struct nand_bbt_descr flctl_4secc_smallpage = {
55 .options = NAND_BBT_SCAN2NDPAGE,
56 .offs = 11,
57 .len = 1,
58 .pattern = scan_ff_pattern,
59};
60
61static struct nand_bbt_descr flctl_4secc_largepage = {
c0e6616a 62 .options = NAND_BBT_SCAN2NDPAGE,
6028aa01
YS
63 .offs = 58,
64 .len = 2,
65 .pattern = scan_ff_pattern,
66};
67
68static void empty_fifo(struct sh_flctl *flctl)
69{
70 writel(0x000c0000, FLINTDMACR(flctl)); /* FIFO Clear */
71 writel(0x00000000, FLINTDMACR(flctl)); /* Clear Error flags */
72}
73
74static void start_translation(struct sh_flctl *flctl)
75{
76 writeb(TRSTRT, FLTRCR(flctl));
77}
78
b79c7adf
MD
79static void timeout_error(struct sh_flctl *flctl, const char *str)
80{
25985edc 81 dev_err(&flctl->pdev->dev, "Timeout occurred in %s\n", str);
b79c7adf
MD
82}
83
6028aa01
YS
84static void wait_completion(struct sh_flctl *flctl)
85{
86 uint32_t timeout = LOOP_TIMEOUT_MAX;
87
88 while (timeout--) {
89 if (readb(FLTRCR(flctl)) & TREND) {
90 writeb(0x0, FLTRCR(flctl));
91 return;
92 }
93 udelay(1);
94 }
95
b79c7adf 96 timeout_error(flctl, __func__);
6028aa01
YS
97 writeb(0x0, FLTRCR(flctl));
98}
99
100static void set_addr(struct mtd_info *mtd, int column, int page_addr)
101{
102 struct sh_flctl *flctl = mtd_to_flctl(mtd);
103 uint32_t addr = 0;
104
105 if (column == -1) {
106 addr = page_addr; /* ERASE1 */
107 } else if (page_addr != -1) {
108 /* SEQIN, READ0, etc.. */
010ab820
MD
109 if (flctl->chip.options & NAND_BUSWIDTH_16)
110 column >>= 1;
6028aa01
YS
111 if (flctl->page_size) {
112 addr = column & 0x0FFF;
113 addr |= (page_addr & 0xff) << 16;
114 addr |= ((page_addr >> 8) & 0xff) << 24;
115 /* big than 128MB */
116 if (flctl->rw_ADRCNT == ADRCNT2_E) {
117 uint32_t addr2;
118 addr2 = (page_addr >> 16) & 0xff;
119 writel(addr2, FLADR2(flctl));
120 }
121 } else {
122 addr = column;
123 addr |= (page_addr & 0xff) << 8;
124 addr |= ((page_addr >> 8) & 0xff) << 16;
125 addr |= ((page_addr >> 16) & 0xff) << 24;
126 }
127 }
128 writel(addr, FLADR(flctl));
129}
130
131static void wait_rfifo_ready(struct sh_flctl *flctl)
132{
133 uint32_t timeout = LOOP_TIMEOUT_MAX;
134
135 while (timeout--) {
136 uint32_t val;
137 /* check FIFO */
138 val = readl(FLDTCNTR(flctl)) >> 16;
139 if (val & 0xFF)
140 return;
141 udelay(1);
142 }
b79c7adf 143 timeout_error(flctl, __func__);
6028aa01
YS
144}
145
146static void wait_wfifo_ready(struct sh_flctl *flctl)
147{
148 uint32_t len, timeout = LOOP_TIMEOUT_MAX;
149
150 while (timeout--) {
151 /* check FIFO */
152 len = (readl(FLDTCNTR(flctl)) >> 16) & 0xFF;
153 if (len >= 4)
154 return;
155 udelay(1);
156 }
b79c7adf 157 timeout_error(flctl, __func__);
6028aa01
YS
158}
159
c0e6616a 160static int wait_recfifo_ready(struct sh_flctl *flctl, int sector_number)
6028aa01
YS
161{
162 uint32_t timeout = LOOP_TIMEOUT_MAX;
163 int checked[4];
164 void __iomem *ecc_reg[4];
165 int i;
166 uint32_t data, size;
167
168 memset(checked, 0, sizeof(checked));
169
170 while (timeout--) {
171 size = readl(FLDTCNTR(flctl)) >> 24;
172 if (size & 0xFF)
173 return 0; /* success */
174
175 if (readl(FL4ECCCR(flctl)) & _4ECCFA)
176 return 1; /* can't correct */
177
178 udelay(1);
179 if (!(readl(FL4ECCCR(flctl)) & _4ECCEND))
180 continue;
181
182 /* start error correction */
183 ecc_reg[0] = FL4ECCRESULT0(flctl);
184 ecc_reg[1] = FL4ECCRESULT1(flctl);
185 ecc_reg[2] = FL4ECCRESULT2(flctl);
186 ecc_reg[3] = FL4ECCRESULT3(flctl);
187
188 for (i = 0; i < 3; i++) {
189 data = readl(ecc_reg[i]);
190 if (data != INIT_FL4ECCRESULT_VAL && !checked[i]) {
191 uint8_t org;
192 int index;
193
c0e6616a
YS
194 if (flctl->page_size)
195 index = (512 * sector_number) +
196 (data >> 16);
197 else
198 index = data >> 16;
199
6028aa01
YS
200 org = flctl->done_buff[index];
201 flctl->done_buff[index] = org ^ (data & 0xFF);
202 checked[i] = 1;
203 }
204 }
205
206 writel(0, FL4ECCCR(flctl));
207 }
208
b79c7adf 209 timeout_error(flctl, __func__);
6028aa01
YS
210 return 1; /* timeout */
211}
212
213static void wait_wecfifo_ready(struct sh_flctl *flctl)
214{
215 uint32_t timeout = LOOP_TIMEOUT_MAX;
216 uint32_t len;
217
218 while (timeout--) {
219 /* check FLECFIFO */
220 len = (readl(FLDTCNTR(flctl)) >> 24) & 0xFF;
221 if (len >= 4)
222 return;
223 udelay(1);
224 }
b79c7adf 225 timeout_error(flctl, __func__);
6028aa01
YS
226}
227
228static void read_datareg(struct sh_flctl *flctl, int offset)
229{
230 unsigned long data;
231 unsigned long *buf = (unsigned long *)&flctl->done_buff[offset];
232
233 wait_completion(flctl);
234
235 data = readl(FLDATAR(flctl));
236 *buf = le32_to_cpu(data);
237}
238
239static void read_fiforeg(struct sh_flctl *flctl, int rlen, int offset)
240{
241 int i, len_4align;
242 unsigned long *buf = (unsigned long *)&flctl->done_buff[offset];
243 void *fifo_addr = (void *)FLDTFIFO(flctl);
244
245 len_4align = (rlen + 3) / 4;
246
247 for (i = 0; i < len_4align; i++) {
248 wait_rfifo_ready(flctl);
249 buf[i] = readl(fifo_addr);
250 buf[i] = be32_to_cpu(buf[i]);
251 }
252}
253
c0e6616a 254static int read_ecfiforeg(struct sh_flctl *flctl, uint8_t *buff, int sector)
6028aa01
YS
255{
256 int i;
257 unsigned long *ecc_buf = (unsigned long *)buff;
258 void *fifo_addr = (void *)FLECFIFO(flctl);
259
260 for (i = 0; i < 4; i++) {
c0e6616a 261 if (wait_recfifo_ready(flctl , sector))
6028aa01
YS
262 return 1;
263 ecc_buf[i] = readl(fifo_addr);
264 ecc_buf[i] = be32_to_cpu(ecc_buf[i]);
265 }
266
267 return 0;
268}
269
270static void write_fiforeg(struct sh_flctl *flctl, int rlen, int offset)
271{
272 int i, len_4align;
273 unsigned long *data = (unsigned long *)&flctl->done_buff[offset];
274 void *fifo_addr = (void *)FLDTFIFO(flctl);
275
276 len_4align = (rlen + 3) / 4;
277 for (i = 0; i < len_4align; i++) {
278 wait_wfifo_ready(flctl);
279 writel(cpu_to_be32(data[i]), fifo_addr);
280 }
281}
282
283static void set_cmd_regs(struct mtd_info *mtd, uint32_t cmd, uint32_t flcmcdr_val)
284{
285 struct sh_flctl *flctl = mtd_to_flctl(mtd);
010ab820 286 uint32_t flcmncr_val = readl(FLCMNCR(flctl)) & ~SEL_16BIT;
6028aa01
YS
287 uint32_t flcmdcr_val, addr_len_bytes = 0;
288
289 /* Set SNAND bit if page size is 2048byte */
290 if (flctl->page_size)
291 flcmncr_val |= SNAND_E;
292 else
293 flcmncr_val &= ~SNAND_E;
294
295 /* default FLCMDCR val */
296 flcmdcr_val = DOCMD1_E | DOADR_E;
297
298 /* Set for FLCMDCR */
299 switch (cmd) {
300 case NAND_CMD_ERASE1:
301 addr_len_bytes = flctl->erase_ADRCNT;
302 flcmdcr_val |= DOCMD2_E;
303 break;
304 case NAND_CMD_READ0:
305 case NAND_CMD_READOOB:
dd5ab248 306 case NAND_CMD_RNDOUT:
6028aa01
YS
307 addr_len_bytes = flctl->rw_ADRCNT;
308 flcmdcr_val |= CDSRC_E;
010ab820
MD
309 if (flctl->chip.options & NAND_BUSWIDTH_16)
310 flcmncr_val |= SEL_16BIT;
6028aa01
YS
311 break;
312 case NAND_CMD_SEQIN:
313 /* This case is that cmd is READ0 or READ1 or READ00 */
314 flcmdcr_val &= ~DOADR_E; /* ONLY execute 1st cmd */
315 break;
316 case NAND_CMD_PAGEPROG:
317 addr_len_bytes = flctl->rw_ADRCNT;
35a34799 318 flcmdcr_val |= DOCMD2_E | CDSRC_E | SELRW;
010ab820
MD
319 if (flctl->chip.options & NAND_BUSWIDTH_16)
320 flcmncr_val |= SEL_16BIT;
35a34799
YS
321 break;
322 case NAND_CMD_READID:
323 flcmncr_val &= ~SNAND_E;
7b6b2303 324 flcmdcr_val |= CDSRC_E;
35a34799
YS
325 addr_len_bytes = ADRCNT_1;
326 break;
327 case NAND_CMD_STATUS:
328 case NAND_CMD_RESET:
329 flcmncr_val &= ~SNAND_E;
330 flcmdcr_val &= ~(DOADR_E | DOSR_E);
331 break;
332 default:
333 break;
334 }
335
336 /* Set address bytes parameter */
337 flcmdcr_val |= addr_len_bytes;
338
339 /* Now actually write */
340 writel(flcmncr_val, FLCMNCR(flctl));
341 writel(flcmdcr_val, FLCMDCR(flctl));
342 writel(flcmcdr_val, FLCMCDR(flctl));
343}
344
345static int flctl_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
46a8cf2d 346 uint8_t *buf, int page)
35a34799
YS
347{
348 int i, eccsize = chip->ecc.size;
349 int eccbytes = chip->ecc.bytes;
350 int eccsteps = chip->ecc.steps;
351 uint8_t *p = buf;
352 struct sh_flctl *flctl = mtd_to_flctl(mtd);
353
354 for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize)
355 chip->read_buf(mtd, p, eccsize);
356
357 for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
358 if (flctl->hwecc_cant_correct[i])
359 mtd->ecc_stats.failed++;
360 else
361 mtd->ecc_stats.corrected += 0;
362 }
363
364 return 0;
365}
366
367static void flctl_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
368 const uint8_t *buf)
369{
370 int i, eccsize = chip->ecc.size;
371 int eccbytes = chip->ecc.bytes;
372 int eccsteps = chip->ecc.steps;
373 const uint8_t *p = buf;
374
375 for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize)
376 chip->write_buf(mtd, p, eccsize);
377}
378
379static void execmd_read_page_sector(struct mtd_info *mtd, int page_addr)
380{
381 struct sh_flctl *flctl = mtd_to_flctl(mtd);
382 int sector, page_sectors;
383
384 if (flctl->page_size)
385 page_sectors = 4;
386 else
387 page_sectors = 1;
388
389 writel(readl(FLCMNCR(flctl)) | ACM_SACCES_MODE | _4ECCCORRECT,
390 FLCMNCR(flctl));
391
392 set_cmd_regs(mtd, NAND_CMD_READ0,
393 (NAND_CMD_READSTART << 8) | NAND_CMD_READ0);
394
395 for (sector = 0; sector < page_sectors; sector++) {
396 int ret;
397
398 empty_fifo(flctl);
399 writel(readl(FLCMDCR(flctl)) | 1, FLCMDCR(flctl));
400 writel(page_addr << 2 | sector, FLADR(flctl));
401
402 start_translation(flctl);
403 read_fiforeg(flctl, 512, 512 * sector);
404
405 ret = read_ecfiforeg(flctl,
c0e6616a
YS
406 &flctl->done_buff[mtd->writesize + 16 * sector],
407 sector);
35a34799
YS
408
409 if (ret)
410 flctl->hwecc_cant_correct[sector] = 1;
411
412 writel(0x0, FL4ECCCR(flctl));
413 wait_completion(flctl);
414 }
415 writel(readl(FLCMNCR(flctl)) & ~(ACM_SACCES_MODE | _4ECCCORRECT),
416 FLCMNCR(flctl));
417}
418
419static void execmd_read_oob(struct mtd_info *mtd, int page_addr)
420{
421 struct sh_flctl *flctl = mtd_to_flctl(mtd);
422
423 set_cmd_regs(mtd, NAND_CMD_READ0,
424 (NAND_CMD_READSTART << 8) | NAND_CMD_READ0);
425
426 empty_fifo(flctl);
427 if (flctl->page_size) {
428 int i;
429 /* In case that the page size is 2k */
430 for (i = 0; i < 16 * 3; i++)
431 flctl->done_buff[i] = 0xFF;
432
433 set_addr(mtd, 3 * 528 + 512, page_addr);
434 writel(16, FLDTCNTR(flctl));
435
436 start_translation(flctl);
437 read_fiforeg(flctl, 16, 16 * 3);
438 wait_completion(flctl);
439 } else {
440 /* In case that the page size is 512b */
441 set_addr(mtd, 512, page_addr);
442 writel(16, FLDTCNTR(flctl));
443
444 start_translation(flctl);
445 read_fiforeg(flctl, 16, 0);
446 wait_completion(flctl);
447 }
448}
449
450static void execmd_write_page_sector(struct mtd_info *mtd)
451{
452 struct sh_flctl *flctl = mtd_to_flctl(mtd);
453 int i, page_addr = flctl->seqin_page_addr;
454 int sector, page_sectors;
455
456 if (flctl->page_size)
457 page_sectors = 4;
458 else
459 page_sectors = 1;
460
461 writel(readl(FLCMNCR(flctl)) | ACM_SACCES_MODE, FLCMNCR(flctl));
462
463 set_cmd_regs(mtd, NAND_CMD_PAGEPROG,
464 (NAND_CMD_PAGEPROG << 8) | NAND_CMD_SEQIN);
465
466 for (sector = 0; sector < page_sectors; sector++) {
467 empty_fifo(flctl);
468 writel(readl(FLCMDCR(flctl)) | 1, FLCMDCR(flctl));
469 writel(page_addr << 2 | sector, FLADR(flctl));
470
471 start_translation(flctl);
472 write_fiforeg(flctl, 512, 512 * sector);
473
474 for (i = 0; i < 4; i++) {
475 wait_wecfifo_ready(flctl); /* wait for write ready */
476 writel(0xFFFFFFFF, FLECFIFO(flctl));
477 }
478 wait_completion(flctl);
479 }
480
481 writel(readl(FLCMNCR(flctl)) & ~ACM_SACCES_MODE, FLCMNCR(flctl));
482}
483
484static void execmd_write_oob(struct mtd_info *mtd)
485{
486 struct sh_flctl *flctl = mtd_to_flctl(mtd);
487 int page_addr = flctl->seqin_page_addr;
488 int sector, page_sectors;
489
490 if (flctl->page_size) {
491 sector = 3;
492 page_sectors = 4;
493 } else {
494 sector = 0;
495 page_sectors = 1;
496 }
497
498 set_cmd_regs(mtd, NAND_CMD_PAGEPROG,
499 (NAND_CMD_PAGEPROG << 8) | NAND_CMD_SEQIN);
500
501 for (; sector < page_sectors; sector++) {
502 empty_fifo(flctl);
503 set_addr(mtd, sector * 528 + 512, page_addr);
504 writel(16, FLDTCNTR(flctl)); /* set read size */
505
506 start_translation(flctl);
507 write_fiforeg(flctl, 16, 16 * sector);
508 wait_completion(flctl);
509 }
510}
511
512static void flctl_cmdfunc(struct mtd_info *mtd, unsigned int command,
513 int column, int page_addr)
514{
515 struct sh_flctl *flctl = mtd_to_flctl(mtd);
516 uint32_t read_cmd = 0;
517
518 flctl->read_bytes = 0;
519 if (command != NAND_CMD_PAGEPROG)
520 flctl->index = 0;
521
522 switch (command) {
523 case NAND_CMD_READ1:
524 case NAND_CMD_READ0:
525 if (flctl->hwecc) {
526 /* read page with hwecc */
527 execmd_read_page_sector(mtd, page_addr);
528 break;
529 }
35a34799
YS
530 if (flctl->page_size)
531 set_cmd_regs(mtd, command, (NAND_CMD_READSTART << 8)
532 | command);
533 else
534 set_cmd_regs(mtd, command, command);
535
536 set_addr(mtd, 0, page_addr);
537
538 flctl->read_bytes = mtd->writesize + mtd->oobsize;
010ab820
MD
539 if (flctl->chip.options & NAND_BUSWIDTH_16)
540 column >>= 1;
35a34799
YS
541 flctl->index += column;
542 goto read_normal_exit;
543
544 case NAND_CMD_READOOB:
545 if (flctl->hwecc) {
546 /* read page with hwecc */
547 execmd_read_oob(mtd, page_addr);
548 break;
549 }
550
35a34799
YS
551 if (flctl->page_size) {
552 set_cmd_regs(mtd, command, (NAND_CMD_READSTART << 8)
553 | NAND_CMD_READ0);
554 set_addr(mtd, mtd->writesize, page_addr);
555 } else {
556 set_cmd_regs(mtd, command, command);
557 set_addr(mtd, 0, page_addr);
558 }
559 flctl->read_bytes = mtd->oobsize;
560 goto read_normal_exit;
561
dd5ab248
BH
562 case NAND_CMD_RNDOUT:
563 if (flctl->hwecc)
564 break;
565
566 if (flctl->page_size)
567 set_cmd_regs(mtd, command, (NAND_CMD_RNDOUTSTART << 8)
568 | command);
569 else
570 set_cmd_regs(mtd, command, command);
571
572 set_addr(mtd, column, 0);
573
574 flctl->read_bytes = mtd->writesize + mtd->oobsize - column;
575 goto read_normal_exit;
576
35a34799 577 case NAND_CMD_READID:
35a34799 578 set_cmd_regs(mtd, command, command);
35a34799 579
7b6b2303
BH
580 /* READID is always performed using an 8-bit bus */
581 if (flctl->chip.options & NAND_BUSWIDTH_16)
582 column <<= 1;
583 set_addr(mtd, column, 0);
584
585 flctl->read_bytes = 8;
35a34799 586 writel(flctl->read_bytes, FLDTCNTR(flctl)); /* set read size */
abb59ef3 587 empty_fifo(flctl);
35a34799 588 start_translation(flctl);
7b6b2303
BH
589 read_fiforeg(flctl, flctl->read_bytes, 0);
590 wait_completion(flctl);
35a34799
YS
591 break;
592
593 case NAND_CMD_ERASE1:
594 flctl->erase1_page_addr = page_addr;
595 break;
596
597 case NAND_CMD_ERASE2:
598 set_cmd_regs(mtd, NAND_CMD_ERASE1,
599 (command << 8) | NAND_CMD_ERASE1);
600 set_addr(mtd, -1, flctl->erase1_page_addr);
601 start_translation(flctl);
602 wait_completion(flctl);
603 break;
604
605 case NAND_CMD_SEQIN:
606 if (!flctl->page_size) {
607 /* output read command */
608 if (column >= mtd->writesize) {
609 column -= mtd->writesize;
610 read_cmd = NAND_CMD_READOOB;
611 } else if (column < 256) {
612 read_cmd = NAND_CMD_READ0;
613 } else {
614 column -= 256;
615 read_cmd = NAND_CMD_READ1;
616 }
617 }
618 flctl->seqin_column = column;
619 flctl->seqin_page_addr = page_addr;
620 flctl->seqin_read_cmd = read_cmd;
621 break;
622
623 case NAND_CMD_PAGEPROG:
624 empty_fifo(flctl);
625 if (!flctl->page_size) {
626 set_cmd_regs(mtd, NAND_CMD_SEQIN,
627 flctl->seqin_read_cmd);
628 set_addr(mtd, -1, -1);
629 writel(0, FLDTCNTR(flctl)); /* set 0 size */
630 start_translation(flctl);
631 wait_completion(flctl);
632 }
633 if (flctl->hwecc) {
634 /* write page with hwecc */
635 if (flctl->seqin_column == mtd->writesize)
636 execmd_write_oob(mtd);
637 else if (!flctl->seqin_column)
638 execmd_write_page_sector(mtd);
639 else
640 printk(KERN_ERR "Invalid address !?\n");
641 break;
642 }
643 set_cmd_regs(mtd, command, (command << 8) | NAND_CMD_SEQIN);
644 set_addr(mtd, flctl->seqin_column, flctl->seqin_page_addr);
645 writel(flctl->index, FLDTCNTR(flctl)); /* set write size */
646 start_translation(flctl);
647 write_fiforeg(flctl, flctl->index, 0);
648 wait_completion(flctl);
649 break;
650
651 case NAND_CMD_STATUS:
652 set_cmd_regs(mtd, command, command);
653 set_addr(mtd, -1, -1);
654
655 flctl->read_bytes = 1;
656 writel(flctl->read_bytes, FLDTCNTR(flctl)); /* set read size */
657 start_translation(flctl);
658 read_datareg(flctl, 0); /* read and end */
659 break;
660
661 case NAND_CMD_RESET:
662 set_cmd_regs(mtd, command, command);
663 set_addr(mtd, -1, -1);
664
665 writel(0, FLDTCNTR(flctl)); /* set 0 size */
666 start_translation(flctl);
667 wait_completion(flctl);
668 break;
669
670 default:
671 break;
672 }
673 return;
674
675read_normal_exit:
676 writel(flctl->read_bytes, FLDTCNTR(flctl)); /* set read size */
abb59ef3 677 empty_fifo(flctl);
35a34799
YS
678 start_translation(flctl);
679 read_fiforeg(flctl, flctl->read_bytes, 0);
680 wait_completion(flctl);
681 return;
682}
683
684static void flctl_select_chip(struct mtd_info *mtd, int chipnr)
685{
686 struct sh_flctl *flctl = mtd_to_flctl(mtd);
687 uint32_t flcmncr_val = readl(FLCMNCR(flctl));
688
689 switch (chipnr) {
690 case -1:
691 flcmncr_val &= ~CE0_ENABLE;
692 writel(flcmncr_val, FLCMNCR(flctl));
693 break;
694 case 0:
695 flcmncr_val |= CE0_ENABLE;
696 writel(flcmncr_val, FLCMNCR(flctl));
697 break;
698 default:
699 BUG();
700 }
701}
702
703static void flctl_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
704{
705 struct sh_flctl *flctl = mtd_to_flctl(mtd);
706 int i, index = flctl->index;
707
708 for (i = 0; i < len; i++)
709 flctl->done_buff[index + i] = buf[i];
710 flctl->index += len;
711}
712
713static uint8_t flctl_read_byte(struct mtd_info *mtd)
714{
715 struct sh_flctl *flctl = mtd_to_flctl(mtd);
716 int index = flctl->index;
717 uint8_t data;
718
719 data = flctl->done_buff[index];
720 flctl->index++;
721 return data;
722}
723
010ab820
MD
724static uint16_t flctl_read_word(struct mtd_info *mtd)
725{
726 struct sh_flctl *flctl = mtd_to_flctl(mtd);
727 int index = flctl->index;
728 uint16_t data;
729 uint16_t *buf = (uint16_t *)&flctl->done_buff[index];
730
731 data = *buf;
732 flctl->index += 2;
733 return data;
734}
735
35a34799
YS
736static void flctl_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
737{
738 int i;
739
740 for (i = 0; i < len; i++)
741 buf[i] = flctl_read_byte(mtd);
742}
743
744static int flctl_verify_buf(struct mtd_info *mtd, const u_char *buf, int len)
745{
746 int i;
747
748 for (i = 0; i < len; i++)
749 if (buf[i] != flctl_read_byte(mtd))
750 return -EFAULT;
751 return 0;
752}
753
754static void flctl_register_init(struct sh_flctl *flctl, unsigned long val)
755{
756 writel(val, FLCMNCR(flctl));
757}
758
759static int flctl_chip_init_tail(struct mtd_info *mtd)
760{
761 struct sh_flctl *flctl = mtd_to_flctl(mtd);
762 struct nand_chip *chip = &flctl->chip;
763
764 if (mtd->writesize == 512) {
765 flctl->page_size = 0;
766 if (chip->chipsize > (32 << 20)) {
767 /* big than 32MB */
768 flctl->rw_ADRCNT = ADRCNT_4;
769 flctl->erase_ADRCNT = ADRCNT_3;
770 } else if (chip->chipsize > (2 << 16)) {
771 /* big than 128KB */
772 flctl->rw_ADRCNT = ADRCNT_3;
773 flctl->erase_ADRCNT = ADRCNT_2;
774 } else {
775 flctl->rw_ADRCNT = ADRCNT_2;
776 flctl->erase_ADRCNT = ADRCNT_1;
777 }
778 } else {
779 flctl->page_size = 1;
780 if (chip->chipsize > (128 << 20)) {
781 /* big than 128MB */
782 flctl->rw_ADRCNT = ADRCNT2_E;
783 flctl->erase_ADRCNT = ADRCNT_3;
784 } else if (chip->chipsize > (8 << 16)) {
785 /* big than 512KB */
786 flctl->rw_ADRCNT = ADRCNT_4;
787 flctl->erase_ADRCNT = ADRCNT_2;
788 } else {
789 flctl->rw_ADRCNT = ADRCNT_3;
790 flctl->erase_ADRCNT = ADRCNT_1;
791 }
792 }
793
794 if (flctl->hwecc) {
795 if (mtd->writesize == 512) {
796 chip->ecc.layout = &flctl_4secc_oob_16;
797 chip->badblock_pattern = &flctl_4secc_smallpage;
798 } else {
799 chip->ecc.layout = &flctl_4secc_oob_64;
800 chip->badblock_pattern = &flctl_4secc_largepage;
801 }
802
803 chip->ecc.size = 512;
804 chip->ecc.bytes = 10;
805 chip->ecc.read_page = flctl_read_page_hwecc;
806 chip->ecc.write_page = flctl_write_page_hwecc;
807 chip->ecc.mode = NAND_ECC_HW;
808
809 /* 4 symbols ECC enabled */
810 writel(readl(FLCMNCR(flctl)) | _4ECCEN | ECCPOS2 | ECCPOS_02,
811 FLCMNCR(flctl));
812 } else {
813 chip->ecc.mode = NAND_ECC_SOFT;
814 }
815
816 return 0;
817}
818
b79c7adf 819static int __devinit flctl_probe(struct platform_device *pdev)
35a34799
YS
820{
821 struct resource *res;
822 struct sh_flctl *flctl;
823 struct mtd_info *flctl_mtd;
824 struct nand_chip *nand;
825 struct sh_flctl_platform_data *pdata;
b79c7adf 826 int ret = -ENXIO;
35a34799
YS
827
828 pdata = pdev->dev.platform_data;
829 if (pdata == NULL) {
b79c7adf
MD
830 dev_err(&pdev->dev, "no platform data defined\n");
831 return -EINVAL;
35a34799
YS
832 }
833
834 flctl = kzalloc(sizeof(struct sh_flctl), GFP_KERNEL);
835 if (!flctl) {
b79c7adf 836 dev_err(&pdev->dev, "failed to allocate driver data\n");
35a34799
YS
837 return -ENOMEM;
838 }
839
840 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
841 if (!res) {
b79c7adf 842 dev_err(&pdev->dev, "failed to get I/O memory\n");
35a34799
YS
843 goto err;
844 }
845
cbd38a87 846 flctl->reg = ioremap(res->start, resource_size(res));
35a34799 847 if (flctl->reg == NULL) {
b79c7adf 848 dev_err(&pdev->dev, "failed to remap I/O memory\n");
35a34799
YS
849 goto err;
850 }
851
852 platform_set_drvdata(pdev, flctl);
853 flctl_mtd = &flctl->mtd;
854 nand = &flctl->chip;
855 flctl_mtd->priv = nand;
b79c7adf 856 flctl->pdev = pdev;
35a34799
YS
857 flctl->hwecc = pdata->has_hwecc;
858
859 flctl_register_init(flctl, pdata->flcmncr_val);
860
861 nand->options = NAND_NO_AUTOINCR;
862
863 /* Set address of hardware control function */
864 /* 20 us command delay time */
865 nand->chip_delay = 20;
866
867 nand->read_byte = flctl_read_byte;
868 nand->write_buf = flctl_write_buf;
869 nand->read_buf = flctl_read_buf;
870 nand->verify_buf = flctl_verify_buf;
871 nand->select_chip = flctl_select_chip;
872 nand->cmdfunc = flctl_cmdfunc;
873
010ab820
MD
874 if (pdata->flcmncr_val & SEL_16BIT) {
875 nand->options |= NAND_BUSWIDTH_16;
876 nand->read_word = flctl_read_word;
877 }
878
5e81e88a 879 ret = nand_scan_ident(flctl_mtd, 1, NULL);
35a34799
YS
880 if (ret)
881 goto err;
882
883 ret = flctl_chip_init_tail(flctl_mtd);
884 if (ret)
885 goto err;
886
887 ret = nand_scan_tail(flctl_mtd);
888 if (ret)
889 goto err;
890
ee0e87b1 891 mtd_device_register(flctl_mtd, pdata->parts, pdata->nr_parts);
35a34799
YS
892
893 return 0;
894
895err:
896 kfree(flctl);
897 return ret;
898}
899
b79c7adf 900static int __devexit flctl_remove(struct platform_device *pdev)
35a34799
YS
901{
902 struct sh_flctl *flctl = platform_get_drvdata(pdev);
903
904 nand_release(&flctl->mtd);
905 kfree(flctl);
906
907 return 0;
908}
909
910static struct platform_driver flctl_driver = {
35a34799
YS
911 .remove = flctl_remove,
912 .driver = {
913 .name = "sh_flctl",
914 .owner = THIS_MODULE,
915 },
916};
917
918static int __init flctl_nand_init(void)
919{
894572a3 920 return platform_driver_probe(&flctl_driver, flctl_probe);
35a34799
YS
921}
922
923static void __exit flctl_nand_cleanup(void)
924{
925 platform_driver_unregister(&flctl_driver);
926}
927
928module_init(flctl_nand_init);
929module_exit(flctl_nand_cleanup);
930
931MODULE_LICENSE("GPL");
932MODULE_AUTHOR("Yoshihiro Shimoda");
933MODULE_DESCRIPTION("SuperH FLCTL driver");
934MODULE_ALIAS("platform:sh_flctl");