Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[MTD] [NAND] sh_flctl: fix compile error

Fix compile error because the first patch was broken -- the file got
truncated.

Signed-off-by: Yoshihiro Shimoda <shimoda.yoshihiro@renesas.com>
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>

authored by

Yoshihiro Shimoda and committed by
David Woodhouse
35a34799 be8f78b8

+577
+577
drivers/mtd/nand/sh_flctl.c
··· 299 299 break; 300 300 case NAND_CMD_PAGEPROG: 301 301 addr_len_bytes = flctl->rw_ADRCNT; 302 + flcmdcr_val |= DOCMD2_E | CDSRC_E | SELRW; 303 + break; 304 + case NAND_CMD_READID: 305 + flcmncr_val &= ~SNAND_E; 306 + addr_len_bytes = ADRCNT_1; 307 + break; 308 + case NAND_CMD_STATUS: 309 + case NAND_CMD_RESET: 310 + flcmncr_val &= ~SNAND_E; 311 + flcmdcr_val &= ~(DOADR_E | DOSR_E); 312 + break; 313 + default: 314 + break; 315 + } 316 + 317 + /* Set address bytes parameter */ 318 + flcmdcr_val |= addr_len_bytes; 319 + 320 + /* Now actually write */ 321 + writel(flcmncr_val, FLCMNCR(flctl)); 322 + writel(flcmdcr_val, FLCMDCR(flctl)); 323 + writel(flcmcdr_val, FLCMCDR(flctl)); 324 + } 325 + 326 + static int flctl_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, 327 + uint8_t *buf) 328 + { 329 + int i, eccsize = chip->ecc.size; 330 + int eccbytes = chip->ecc.bytes; 331 + int eccsteps = chip->ecc.steps; 332 + uint8_t *p = buf; 333 + struct sh_flctl *flctl = mtd_to_flctl(mtd); 334 + 335 + for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) 336 + chip->read_buf(mtd, p, eccsize); 337 + 338 + for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { 339 + if (flctl->hwecc_cant_correct[i]) 340 + mtd->ecc_stats.failed++; 341 + else 342 + mtd->ecc_stats.corrected += 0; 343 + } 344 + 345 + return 0; 346 + } 347 + 348 + static void flctl_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, 349 + const uint8_t *buf) 350 + { 351 + int i, eccsize = chip->ecc.size; 352 + int eccbytes = chip->ecc.bytes; 353 + int eccsteps = chip->ecc.steps; 354 + const uint8_t *p = buf; 355 + 356 + for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) 357 + chip->write_buf(mtd, p, eccsize); 358 + } 359 + 360 + static void execmd_read_page_sector(struct mtd_info *mtd, int page_addr) 361 + { 362 + struct sh_flctl *flctl = mtd_to_flctl(mtd); 363 + int sector, page_sectors; 364 + 365 + if (flctl->page_size) 366 + page_sectors = 4; 367 + else 368 + page_sectors = 1; 369 + 370 + writel(readl(FLCMNCR(flctl)) | ACM_SACCES_MODE | _4ECCCORRECT, 371 + FLCMNCR(flctl)); 372 + 373 + set_cmd_regs(mtd, NAND_CMD_READ0, 374 + (NAND_CMD_READSTART << 8) | NAND_CMD_READ0); 375 + 376 + for (sector = 0; sector < page_sectors; sector++) { 377 + int ret; 378 + 379 + empty_fifo(flctl); 380 + writel(readl(FLCMDCR(flctl)) | 1, FLCMDCR(flctl)); 381 + writel(page_addr << 2 | sector, FLADR(flctl)); 382 + 383 + start_translation(flctl); 384 + read_fiforeg(flctl, 512, 512 * sector); 385 + 386 + ret = read_ecfiforeg(flctl, 387 + &flctl->done_buff[mtd->writesize + 16 * sector]); 388 + 389 + if (ret) 390 + flctl->hwecc_cant_correct[sector] = 1; 391 + 392 + writel(0x0, FL4ECCCR(flctl)); 393 + wait_completion(flctl); 394 + } 395 + writel(readl(FLCMNCR(flctl)) & ~(ACM_SACCES_MODE | _4ECCCORRECT), 396 + FLCMNCR(flctl)); 397 + } 398 + 399 + static void execmd_read_oob(struct mtd_info *mtd, int page_addr) 400 + { 401 + struct sh_flctl *flctl = mtd_to_flctl(mtd); 402 + 403 + set_cmd_regs(mtd, NAND_CMD_READ0, 404 + (NAND_CMD_READSTART << 8) | NAND_CMD_READ0); 405 + 406 + empty_fifo(flctl); 407 + if (flctl->page_size) { 408 + int i; 409 + /* In case that the page size is 2k */ 410 + for (i = 0; i < 16 * 3; i++) 411 + flctl->done_buff[i] = 0xFF; 412 + 413 + set_addr(mtd, 3 * 528 + 512, page_addr); 414 + writel(16, FLDTCNTR(flctl)); 415 + 416 + start_translation(flctl); 417 + read_fiforeg(flctl, 16, 16 * 3); 418 + wait_completion(flctl); 419 + } else { 420 + /* In case that the page size is 512b */ 421 + set_addr(mtd, 512, page_addr); 422 + writel(16, FLDTCNTR(flctl)); 423 + 424 + start_translation(flctl); 425 + read_fiforeg(flctl, 16, 0); 426 + wait_completion(flctl); 427 + } 428 + } 429 + 430 + static void execmd_write_page_sector(struct mtd_info *mtd) 431 + { 432 + struct sh_flctl *flctl = mtd_to_flctl(mtd); 433 + int i, page_addr = flctl->seqin_page_addr; 434 + int sector, page_sectors; 435 + 436 + if (flctl->page_size) 437 + page_sectors = 4; 438 + else 439 + page_sectors = 1; 440 + 441 + writel(readl(FLCMNCR(flctl)) | ACM_SACCES_MODE, FLCMNCR(flctl)); 442 + 443 + set_cmd_regs(mtd, NAND_CMD_PAGEPROG, 444 + (NAND_CMD_PAGEPROG << 8) | NAND_CMD_SEQIN); 445 + 446 + for (sector = 0; sector < page_sectors; sector++) { 447 + empty_fifo(flctl); 448 + writel(readl(FLCMDCR(flctl)) | 1, FLCMDCR(flctl)); 449 + writel(page_addr << 2 | sector, FLADR(flctl)); 450 + 451 + start_translation(flctl); 452 + write_fiforeg(flctl, 512, 512 * sector); 453 + 454 + for (i = 0; i < 4; i++) { 455 + wait_wecfifo_ready(flctl); /* wait for write ready */ 456 + writel(0xFFFFFFFF, FLECFIFO(flctl)); 457 + } 458 + wait_completion(flctl); 459 + } 460 + 461 + writel(readl(FLCMNCR(flctl)) & ~ACM_SACCES_MODE, FLCMNCR(flctl)); 462 + } 463 + 464 + static void execmd_write_oob(struct mtd_info *mtd) 465 + { 466 + struct sh_flctl *flctl = mtd_to_flctl(mtd); 467 + int page_addr = flctl->seqin_page_addr; 468 + int sector, page_sectors; 469 + 470 + if (flctl->page_size) { 471 + sector = 3; 472 + page_sectors = 4; 473 + } else { 474 + sector = 0; 475 + page_sectors = 1; 476 + } 477 + 478 + set_cmd_regs(mtd, NAND_CMD_PAGEPROG, 479 + (NAND_CMD_PAGEPROG << 8) | NAND_CMD_SEQIN); 480 + 481 + for (; sector < page_sectors; sector++) { 482 + empty_fifo(flctl); 483 + set_addr(mtd, sector * 528 + 512, page_addr); 484 + writel(16, FLDTCNTR(flctl)); /* set read size */ 485 + 486 + start_translation(flctl); 487 + write_fiforeg(flctl, 16, 16 * sector); 488 + wait_completion(flctl); 489 + } 490 + } 491 + 492 + static void flctl_cmdfunc(struct mtd_info *mtd, unsigned int command, 493 + int column, int page_addr) 494 + { 495 + struct sh_flctl *flctl = mtd_to_flctl(mtd); 496 + uint32_t read_cmd = 0; 497 + 498 + flctl->read_bytes = 0; 499 + if (command != NAND_CMD_PAGEPROG) 500 + flctl->index = 0; 501 + 502 + switch (command) { 503 + case NAND_CMD_READ1: 504 + case NAND_CMD_READ0: 505 + if (flctl->hwecc) { 506 + /* read page with hwecc */ 507 + execmd_read_page_sector(mtd, page_addr); 508 + break; 509 + } 510 + empty_fifo(flctl); 511 + if (flctl->page_size) 512 + set_cmd_regs(mtd, command, (NAND_CMD_READSTART << 8) 513 + | command); 514 + else 515 + set_cmd_regs(mtd, command, command); 516 + 517 + set_addr(mtd, 0, page_addr); 518 + 519 + flctl->read_bytes = mtd->writesize + mtd->oobsize; 520 + flctl->index += column; 521 + goto read_normal_exit; 522 + 523 + case NAND_CMD_READOOB: 524 + if (flctl->hwecc) { 525 + /* read page with hwecc */ 526 + execmd_read_oob(mtd, page_addr); 527 + break; 528 + } 529 + 530 + empty_fifo(flctl); 531 + if (flctl->page_size) { 532 + set_cmd_regs(mtd, command, (NAND_CMD_READSTART << 8) 533 + | NAND_CMD_READ0); 534 + set_addr(mtd, mtd->writesize, page_addr); 535 + } else { 536 + set_cmd_regs(mtd, command, command); 537 + set_addr(mtd, 0, page_addr); 538 + } 539 + flctl->read_bytes = mtd->oobsize; 540 + goto read_normal_exit; 541 + 542 + case NAND_CMD_READID: 543 + empty_fifo(flctl); 544 + set_cmd_regs(mtd, command, command); 545 + set_addr(mtd, 0, 0); 546 + 547 + flctl->read_bytes = 4; 548 + writel(flctl->read_bytes, FLDTCNTR(flctl)); /* set read size */ 549 + start_translation(flctl); 550 + read_datareg(flctl, 0); /* read and end */ 551 + break; 552 + 553 + case NAND_CMD_ERASE1: 554 + flctl->erase1_page_addr = page_addr; 555 + break; 556 + 557 + case NAND_CMD_ERASE2: 558 + set_cmd_regs(mtd, NAND_CMD_ERASE1, 559 + (command << 8) | NAND_CMD_ERASE1); 560 + set_addr(mtd, -1, flctl->erase1_page_addr); 561 + start_translation(flctl); 562 + wait_completion(flctl); 563 + break; 564 + 565 + case NAND_CMD_SEQIN: 566 + if (!flctl->page_size) { 567 + /* output read command */ 568 + if (column >= mtd->writesize) { 569 + column -= mtd->writesize; 570 + read_cmd = NAND_CMD_READOOB; 571 + } else if (column < 256) { 572 + read_cmd = NAND_CMD_READ0; 573 + } else { 574 + column -= 256; 575 + read_cmd = NAND_CMD_READ1; 576 + } 577 + } 578 + flctl->seqin_column = column; 579 + flctl->seqin_page_addr = page_addr; 580 + flctl->seqin_read_cmd = read_cmd; 581 + break; 582 + 583 + case NAND_CMD_PAGEPROG: 584 + empty_fifo(flctl); 585 + if (!flctl->page_size) { 586 + set_cmd_regs(mtd, NAND_CMD_SEQIN, 587 + flctl->seqin_read_cmd); 588 + set_addr(mtd, -1, -1); 589 + writel(0, FLDTCNTR(flctl)); /* set 0 size */ 590 + start_translation(flctl); 591 + wait_completion(flctl); 592 + } 593 + if (flctl->hwecc) { 594 + /* write page with hwecc */ 595 + if (flctl->seqin_column == mtd->writesize) 596 + execmd_write_oob(mtd); 597 + else if (!flctl->seqin_column) 598 + execmd_write_page_sector(mtd); 599 + else 600 + printk(KERN_ERR "Invalid address !?\n"); 601 + break; 602 + } 603 + set_cmd_regs(mtd, command, (command << 8) | NAND_CMD_SEQIN); 604 + set_addr(mtd, flctl->seqin_column, flctl->seqin_page_addr); 605 + writel(flctl->index, FLDTCNTR(flctl)); /* set write size */ 606 + start_translation(flctl); 607 + write_fiforeg(flctl, flctl->index, 0); 608 + wait_completion(flctl); 609 + break; 610 + 611 + case NAND_CMD_STATUS: 612 + set_cmd_regs(mtd, command, command); 613 + set_addr(mtd, -1, -1); 614 + 615 + flctl->read_bytes = 1; 616 + writel(flctl->read_bytes, FLDTCNTR(flctl)); /* set read size */ 617 + start_translation(flctl); 618 + read_datareg(flctl, 0); /* read and end */ 619 + break; 620 + 621 + case NAND_CMD_RESET: 622 + set_cmd_regs(mtd, command, command); 623 + set_addr(mtd, -1, -1); 624 + 625 + writel(0, FLDTCNTR(flctl)); /* set 0 size */ 626 + start_translation(flctl); 627 + wait_completion(flctl); 628 + break; 629 + 630 + default: 631 + break; 632 + } 633 + return; 634 + 635 + read_normal_exit: 636 + writel(flctl->read_bytes, FLDTCNTR(flctl)); /* set read size */ 637 + start_translation(flctl); 638 + read_fiforeg(flctl, flctl->read_bytes, 0); 639 + wait_completion(flctl); 640 + return; 641 + } 642 + 643 + static void flctl_select_chip(struct mtd_info *mtd, int chipnr) 644 + { 645 + struct sh_flctl *flctl = mtd_to_flctl(mtd); 646 + uint32_t flcmncr_val = readl(FLCMNCR(flctl)); 647 + 648 + switch (chipnr) { 649 + case -1: 650 + flcmncr_val &= ~CE0_ENABLE; 651 + writel(flcmncr_val, FLCMNCR(flctl)); 652 + break; 653 + case 0: 654 + flcmncr_val |= CE0_ENABLE; 655 + writel(flcmncr_val, FLCMNCR(flctl)); 656 + break; 657 + default: 658 + BUG(); 659 + } 660 + } 661 + 662 + static void flctl_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) 663 + { 664 + struct sh_flctl *flctl = mtd_to_flctl(mtd); 665 + int i, index = flctl->index; 666 + 667 + for (i = 0; i < len; i++) 668 + flctl->done_buff[index + i] = buf[i]; 669 + flctl->index += len; 670 + } 671 + 672 + static uint8_t flctl_read_byte(struct mtd_info *mtd) 673 + { 674 + struct sh_flctl *flctl = mtd_to_flctl(mtd); 675 + int index = flctl->index; 676 + uint8_t data; 677 + 678 + data = flctl->done_buff[index]; 679 + flctl->index++; 680 + return data; 681 + } 682 + 683 + static void flctl_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) 684 + { 685 + int i; 686 + 687 + for (i = 0; i < len; i++) 688 + buf[i] = flctl_read_byte(mtd); 689 + } 690 + 691 + static int flctl_verify_buf(struct mtd_info *mtd, const u_char *buf, int len) 692 + { 693 + int i; 694 + 695 + for (i = 0; i < len; i++) 696 + if (buf[i] != flctl_read_byte(mtd)) 697 + return -EFAULT; 698 + return 0; 699 + } 700 + 701 + static void flctl_register_init(struct sh_flctl *flctl, unsigned long val) 702 + { 703 + writel(val, FLCMNCR(flctl)); 704 + } 705 + 706 + static int flctl_chip_init_tail(struct mtd_info *mtd) 707 + { 708 + struct sh_flctl *flctl = mtd_to_flctl(mtd); 709 + struct nand_chip *chip = &flctl->chip; 710 + 711 + if (mtd->writesize == 512) { 712 + flctl->page_size = 0; 713 + if (chip->chipsize > (32 << 20)) { 714 + /* big than 32MB */ 715 + flctl->rw_ADRCNT = ADRCNT_4; 716 + flctl->erase_ADRCNT = ADRCNT_3; 717 + } else if (chip->chipsize > (2 << 16)) { 718 + /* big than 128KB */ 719 + flctl->rw_ADRCNT = ADRCNT_3; 720 + flctl->erase_ADRCNT = ADRCNT_2; 721 + } else { 722 + flctl->rw_ADRCNT = ADRCNT_2; 723 + flctl->erase_ADRCNT = ADRCNT_1; 724 + } 725 + } else { 726 + flctl->page_size = 1; 727 + if (chip->chipsize > (128 << 20)) { 728 + /* big than 128MB */ 729 + flctl->rw_ADRCNT = ADRCNT2_E; 730 + flctl->erase_ADRCNT = ADRCNT_3; 731 + } else if (chip->chipsize > (8 << 16)) { 732 + /* big than 512KB */ 733 + flctl->rw_ADRCNT = ADRCNT_4; 734 + flctl->erase_ADRCNT = ADRCNT_2; 735 + } else { 736 + flctl->rw_ADRCNT = ADRCNT_3; 737 + flctl->erase_ADRCNT = ADRCNT_1; 738 + } 739 + } 740 + 741 + if (flctl->hwecc) { 742 + if (mtd->writesize == 512) { 743 + chip->ecc.layout = &flctl_4secc_oob_16; 744 + chip->badblock_pattern = &flctl_4secc_smallpage; 745 + } else { 746 + chip->ecc.layout = &flctl_4secc_oob_64; 747 + chip->badblock_pattern = &flctl_4secc_largepage; 748 + } 749 + 750 + chip->ecc.size = 512; 751 + chip->ecc.bytes = 10; 752 + chip->ecc.read_page = flctl_read_page_hwecc; 753 + chip->ecc.write_page = flctl_write_page_hwecc; 754 + chip->ecc.mode = NAND_ECC_HW; 755 + 756 + /* 4 symbols ECC enabled */ 757 + writel(readl(FLCMNCR(flctl)) | _4ECCEN | ECCPOS2 | ECCPOS_02, 758 + FLCMNCR(flctl)); 759 + } else { 760 + chip->ecc.mode = NAND_ECC_SOFT; 761 + } 762 + 763 + return 0; 764 + } 765 + 766 + static int __init flctl_probe(struct platform_device *pdev) 767 + { 768 + struct resource *res; 769 + struct sh_flctl *flctl; 770 + struct mtd_info *flctl_mtd; 771 + struct nand_chip *nand; 772 + struct sh_flctl_platform_data *pdata; 773 + int ret; 774 + 775 + pdata = pdev->dev.platform_data; 776 + if (pdata == NULL) { 777 + printk(KERN_ERR "sh_flctl platform_data not found.\n"); 778 + return -ENODEV; 779 + } 780 + 781 + flctl = kzalloc(sizeof(struct sh_flctl), GFP_KERNEL); 782 + if (!flctl) { 783 + printk(KERN_ERR "Unable to allocate NAND MTD dev structure.\n"); 784 + return -ENOMEM; 785 + } 786 + 787 + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 788 + if (!res) { 789 + printk(KERN_ERR "%s: resource not found.\n", __func__); 790 + ret = -ENODEV; 791 + goto err; 792 + } 793 + 794 + flctl->reg = ioremap(res->start, res->end - res->start + 1); 795 + if (flctl->reg == NULL) { 796 + printk(KERN_ERR "%s: ioremap error.\n", __func__); 797 + ret = -ENOMEM; 798 + goto err; 799 + } 800 + 801 + platform_set_drvdata(pdev, flctl); 802 + flctl_mtd = &flctl->mtd; 803 + nand = &flctl->chip; 804 + flctl_mtd->priv = nand; 805 + flctl->hwecc = pdata->has_hwecc; 806 + 807 + flctl_register_init(flctl, pdata->flcmncr_val); 808 + 809 + nand->options = NAND_NO_AUTOINCR; 810 + 811 + /* Set address of hardware control function */ 812 + /* 20 us command delay time */ 813 + nand->chip_delay = 20; 814 + 815 + nand->read_byte = flctl_read_byte; 816 + nand->write_buf = flctl_write_buf; 817 + nand->read_buf = flctl_read_buf; 818 + nand->verify_buf = flctl_verify_buf; 819 + nand->select_chip = flctl_select_chip; 820 + nand->cmdfunc = flctl_cmdfunc; 821 + 822 + ret = nand_scan_ident(flctl_mtd, 1); 823 + if (ret) 824 + goto err; 825 + 826 + ret = flctl_chip_init_tail(flctl_mtd); 827 + if (ret) 828 + goto err; 829 + 830 + ret = nand_scan_tail(flctl_mtd); 831 + if (ret) 832 + goto err; 833 + 834 + add_mtd_partitions(flctl_mtd, pdata->parts, pdata->nr_parts); 835 + 836 + return 0; 837 + 838 + err: 839 + kfree(flctl); 840 + return ret; 841 + } 842 + 843 + static int __exit flctl_remove(struct platform_device *pdev) 844 + { 845 + struct sh_flctl *flctl = platform_get_drvdata(pdev); 846 + 847 + nand_release(&flctl->mtd); 848 + kfree(flctl); 849 + 850 + return 0; 851 + } 852 + 853 + static struct platform_driver flctl_driver = { 854 + .probe = flctl_probe, 855 + .remove = flctl_remove, 856 + .driver = { 857 + .name = "sh_flctl", 858 + .owner = THIS_MODULE, 859 + }, 860 + }; 861 + 862 + static int __init flctl_nand_init(void) 863 + { 864 + return platform_driver_register(&flctl_driver); 865 + } 866 + 867 + static void __exit flctl_nand_cleanup(void) 868 + { 869 + platform_driver_unregister(&flctl_driver); 870 + } 871 + 872 + module_init(flctl_nand_init); 873 + module_exit(flctl_nand_cleanup); 874 + 875 + MODULE_LICENSE("GPL"); 876 + MODULE_AUTHOR("Yoshihiro Shimoda"); 877 + MODULE_DESCRIPTION("SuperH FLCTL driver"); 878 + MODULE_ALIAS("platform:sh_flctl");