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