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