diff options
author | Miquel Raynal <miquel.raynal@bootlin.com> | 2018-07-25 09:31:37 -0400 |
---|---|---|
committer | Miquel Raynal <miquel.raynal@bootlin.com> | 2018-07-31 03:46:07 -0400 |
commit | 73a27db8658125faadb857f1919559de8a5f71b0 (patch) | |
tree | d58e30e2a9c9204a89121630de24bbd765e6757c | |
parent | 4918b905736fddc67f14618d5c82f7edc5944db8 (diff) |
mtd: rawnand: cafe: convert driver to nand_scan()
Two helpers have been added to the core to do all kind of controller
side configuration/initialization between the detection phase and the
final NAND scan. Implement these hooks so that we can convert the driver
to just use nand_scan() instead of the nand_scan_ident() +
nand_scan_tail() pair.
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
Reviewed-by: Boris Brezillon <boris.brezillon@bootlin.com>
-rw-r--r-- | drivers/mtd/nand/raw/cafe_nand.c | 135 |
1 files changed, 78 insertions, 57 deletions
diff --git a/drivers/mtd/nand/raw/cafe_nand.c b/drivers/mtd/nand/raw/cafe_nand.c index ac0be933a490..1dbe43adcfe7 100644 --- a/drivers/mtd/nand/raw/cafe_nand.c +++ b/drivers/mtd/nand/raw/cafe_nand.c | |||
@@ -67,6 +67,7 @@ struct cafe_priv { | |||
67 | int nr_data; | 67 | int nr_data; |
68 | int data_pos; | 68 | int data_pos; |
69 | int page_addr; | 69 | int page_addr; |
70 | bool usedma; | ||
70 | dma_addr_t dmaaddr; | 71 | dma_addr_t dmaaddr; |
71 | unsigned char *dmabuf; | 72 | unsigned char *dmabuf; |
72 | }; | 73 | }; |
@@ -121,7 +122,7 @@ static void cafe_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) | |||
121 | struct nand_chip *chip = mtd_to_nand(mtd); | 122 | struct nand_chip *chip = mtd_to_nand(mtd); |
122 | struct cafe_priv *cafe = nand_get_controller_data(chip); | 123 | struct cafe_priv *cafe = nand_get_controller_data(chip); |
123 | 124 | ||
124 | if (usedma) | 125 | if (cafe->usedma) |
125 | memcpy(cafe->dmabuf + cafe->datalen, buf, len); | 126 | memcpy(cafe->dmabuf + cafe->datalen, buf, len); |
126 | else | 127 | else |
127 | memcpy_toio(cafe->mmio + CAFE_NAND_WRITE_DATA + cafe->datalen, buf, len); | 128 | memcpy_toio(cafe->mmio + CAFE_NAND_WRITE_DATA + cafe->datalen, buf, len); |
@@ -137,7 +138,7 @@ static void cafe_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) | |||
137 | struct nand_chip *chip = mtd_to_nand(mtd); | 138 | struct nand_chip *chip = mtd_to_nand(mtd); |
138 | struct cafe_priv *cafe = nand_get_controller_data(chip); | 139 | struct cafe_priv *cafe = nand_get_controller_data(chip); |
139 | 140 | ||
140 | if (usedma) | 141 | if (cafe->usedma) |
141 | memcpy(buf, cafe->dmabuf + cafe->datalen, len); | 142 | memcpy(buf, cafe->dmabuf + cafe->datalen, len); |
142 | else | 143 | else |
143 | memcpy_fromio(buf, cafe->mmio + CAFE_NAND_READ_DATA + cafe->datalen, len); | 144 | memcpy_fromio(buf, cafe->mmio + CAFE_NAND_READ_DATA + cafe->datalen, len); |
@@ -253,7 +254,7 @@ static void cafe_nand_cmdfunc(struct mtd_info *mtd, unsigned command, | |||
253 | /* NB: The datasheet lies -- we really should be subtracting 1 here */ | 254 | /* NB: The datasheet lies -- we really should be subtracting 1 here */ |
254 | cafe_writel(cafe, cafe->datalen, NAND_DATA_LEN); | 255 | cafe_writel(cafe, cafe->datalen, NAND_DATA_LEN); |
255 | cafe_writel(cafe, 0x90000000, NAND_IRQ); | 256 | cafe_writel(cafe, 0x90000000, NAND_IRQ); |
256 | if (usedma && (ctl1 & (3<<25))) { | 257 | if (cafe->usedma && (ctl1 & (3<<25))) { |
257 | uint32_t dmactl = 0xc0000000 + cafe->datalen; | 258 | uint32_t dmactl = 0xc0000000 + cafe->datalen; |
258 | /* If WR or RD bits set, set up DMA */ | 259 | /* If WR or RD bits set, set up DMA */ |
259 | if (ctl1 & (1<<26)) { | 260 | if (ctl1 & (1<<26)) { |
@@ -593,6 +594,76 @@ static int cafe_mul(int x) | |||
593 | return gf4096_mul(x, 0xe01); | 594 | return gf4096_mul(x, 0xe01); |
594 | } | 595 | } |
595 | 596 | ||
597 | static int cafe_nand_attach_chip(struct nand_chip *chip) | ||
598 | { | ||
599 | struct mtd_info *mtd = nand_to_mtd(chip); | ||
600 | struct cafe_priv *cafe = nand_get_controller_data(chip); | ||
601 | int err = 0; | ||
602 | |||
603 | cafe->dmabuf = dma_alloc_coherent(&cafe->pdev->dev, 2112, | ||
604 | &cafe->dmaaddr, GFP_KERNEL); | ||
605 | if (!cafe->dmabuf) | ||
606 | return -ENOMEM; | ||
607 | |||
608 | /* Set up DMA address */ | ||
609 | cafe_writel(cafe, lower_32_bits(cafe->dmaaddr), NAND_DMA_ADDR0); | ||
610 | cafe_writel(cafe, upper_32_bits(cafe->dmaaddr), NAND_DMA_ADDR1); | ||
611 | |||
612 | cafe_dev_dbg(&cafe->pdev->dev, "Set DMA address to %x (virt %p)\n", | ||
613 | cafe_readl(cafe, NAND_DMA_ADDR0), cafe->dmabuf); | ||
614 | |||
615 | /* Restore the DMA flag */ | ||
616 | cafe->usedma = usedma; | ||
617 | |||
618 | cafe->ctl2 = BIT(27); /* Reed-Solomon ECC */ | ||
619 | if (mtd->writesize == 2048) | ||
620 | cafe->ctl2 |= BIT(29); /* 2KiB page size */ | ||
621 | |||
622 | /* Set up ECC according to the type of chip we found */ | ||
623 | mtd_set_ooblayout(mtd, &cafe_ooblayout_ops); | ||
624 | if (mtd->writesize == 2048) { | ||
625 | cafe->nand.bbt_td = &cafe_bbt_main_descr_2048; | ||
626 | cafe->nand.bbt_md = &cafe_bbt_mirror_descr_2048; | ||
627 | } else if (mtd->writesize == 512) { | ||
628 | cafe->nand.bbt_td = &cafe_bbt_main_descr_512; | ||
629 | cafe->nand.bbt_md = &cafe_bbt_mirror_descr_512; | ||
630 | } else { | ||
631 | dev_warn(&cafe->pdev->dev, | ||
632 | "Unexpected NAND flash writesize %d. Aborting\n", | ||
633 | mtd->writesize); | ||
634 | err = -ENOTSUPP; | ||
635 | goto out_free_dma; | ||
636 | } | ||
637 | |||
638 | cafe->nand.ecc.mode = NAND_ECC_HW_SYNDROME; | ||
639 | cafe->nand.ecc.size = mtd->writesize; | ||
640 | cafe->nand.ecc.bytes = 14; | ||
641 | cafe->nand.ecc.strength = 4; | ||
642 | cafe->nand.ecc.write_page = cafe_nand_write_page_lowlevel; | ||
643 | cafe->nand.ecc.write_oob = cafe_nand_write_oob; | ||
644 | cafe->nand.ecc.read_page = cafe_nand_read_page; | ||
645 | cafe->nand.ecc.read_oob = cafe_nand_read_oob; | ||
646 | |||
647 | return 0; | ||
648 | |||
649 | out_free_dma: | ||
650 | dma_free_coherent(&cafe->pdev->dev, 2112, cafe->dmabuf, cafe->dmaaddr); | ||
651 | |||
652 | return err; | ||
653 | } | ||
654 | |||
655 | static void cafe_nand_detach_chip(struct nand_chip *chip) | ||
656 | { | ||
657 | struct cafe_priv *cafe = nand_get_controller_data(chip); | ||
658 | |||
659 | dma_free_coherent(&cafe->pdev->dev, 2112, cafe->dmabuf, cafe->dmaaddr); | ||
660 | } | ||
661 | |||
662 | static const struct nand_controller_ops cafe_nand_controller_ops = { | ||
663 | .attach_chip = cafe_nand_attach_chip, | ||
664 | .detach_chip = cafe_nand_detach_chip, | ||
665 | }; | ||
666 | |||
596 | static int cafe_nand_probe(struct pci_dev *pdev, | 667 | static int cafe_nand_probe(struct pci_dev *pdev, |
597 | const struct pci_device_id *ent) | 668 | const struct pci_device_id *ent) |
598 | { | 669 | { |
@@ -600,7 +671,6 @@ static int cafe_nand_probe(struct pci_dev *pdev, | |||
600 | struct cafe_priv *cafe; | 671 | struct cafe_priv *cafe; |
601 | uint32_t ctrl; | 672 | uint32_t ctrl; |
602 | int err = 0; | 673 | int err = 0; |
603 | int old_dma; | ||
604 | 674 | ||
605 | /* Very old versions shared the same PCI ident for all three | 675 | /* Very old versions shared the same PCI ident for all three |
606 | functions on the chip. Verify the class too... */ | 676 | functions on the chip. Verify the class too... */ |
@@ -708,62 +778,15 @@ static int cafe_nand_probe(struct pci_dev *pdev, | |||
708 | cafe_readl(cafe, GLOBAL_CTRL), | 778 | cafe_readl(cafe, GLOBAL_CTRL), |
709 | cafe_readl(cafe, GLOBAL_IRQ_MASK)); | 779 | cafe_readl(cafe, GLOBAL_IRQ_MASK)); |
710 | 780 | ||
711 | /* Do not use the DMA for the nand_scan_ident() */ | 781 | /* Do not use the DMA during the NAND identification */ |
712 | old_dma = usedma; | 782 | cafe->usedma = 0; |
713 | usedma = 0; | ||
714 | 783 | ||
715 | /* Scan to find existence of the device */ | 784 | /* Scan to find existence of the device */ |
716 | err = nand_scan_ident(mtd, 2, NULL); | 785 | cafe->nand.dummy_controller.ops = &cafe_nand_controller_ops; |
786 | err = nand_scan(mtd, 2); | ||
717 | if (err) | 787 | if (err) |
718 | goto out_irq; | 788 | goto out_irq; |
719 | 789 | ||
720 | cafe->dmabuf = dma_alloc_coherent(&cafe->pdev->dev, 2112, | ||
721 | &cafe->dmaaddr, GFP_KERNEL); | ||
722 | if (!cafe->dmabuf) { | ||
723 | err = -ENOMEM; | ||
724 | goto out_irq; | ||
725 | } | ||
726 | |||
727 | /* Set up DMA address */ | ||
728 | cafe_writel(cafe, lower_32_bits(cafe->dmaaddr), NAND_DMA_ADDR0); | ||
729 | cafe_writel(cafe, upper_32_bits(cafe->dmaaddr), NAND_DMA_ADDR1); | ||
730 | |||
731 | cafe_dev_dbg(&cafe->pdev->dev, "Set DMA address to %x (virt %p)\n", | ||
732 | cafe_readl(cafe, NAND_DMA_ADDR0), cafe->dmabuf); | ||
733 | |||
734 | /* Restore the DMA flag */ | ||
735 | usedma = old_dma; | ||
736 | |||
737 | cafe->ctl2 = 1<<27; /* Reed-Solomon ECC */ | ||
738 | if (mtd->writesize == 2048) | ||
739 | cafe->ctl2 |= 1<<29; /* 2KiB page size */ | ||
740 | |||
741 | /* Set up ECC according to the type of chip we found */ | ||
742 | mtd_set_ooblayout(mtd, &cafe_ooblayout_ops); | ||
743 | if (mtd->writesize == 2048) { | ||
744 | cafe->nand.bbt_td = &cafe_bbt_main_descr_2048; | ||
745 | cafe->nand.bbt_md = &cafe_bbt_mirror_descr_2048; | ||
746 | } else if (mtd->writesize == 512) { | ||
747 | cafe->nand.bbt_td = &cafe_bbt_main_descr_512; | ||
748 | cafe->nand.bbt_md = &cafe_bbt_mirror_descr_512; | ||
749 | } else { | ||
750 | pr_warn("Unexpected NAND flash writesize %d. Aborting\n", | ||
751 | mtd->writesize); | ||
752 | goto out_free_dma; | ||
753 | } | ||
754 | cafe->nand.ecc.mode = NAND_ECC_HW_SYNDROME; | ||
755 | cafe->nand.ecc.size = mtd->writesize; | ||
756 | cafe->nand.ecc.bytes = 14; | ||
757 | cafe->nand.ecc.strength = 4; | ||
758 | cafe->nand.ecc.write_page = cafe_nand_write_page_lowlevel; | ||
759 | cafe->nand.ecc.write_oob = cafe_nand_write_oob; | ||
760 | cafe->nand.ecc.read_page = cafe_nand_read_page; | ||
761 | cafe->nand.ecc.read_oob = cafe_nand_read_oob; | ||
762 | |||
763 | err = nand_scan_tail(mtd); | ||
764 | if (err) | ||
765 | goto out_free_dma; | ||
766 | |||
767 | pci_set_drvdata(pdev, mtd); | 790 | pci_set_drvdata(pdev, mtd); |
768 | 791 | ||
769 | mtd->name = "cafe_nand"; | 792 | mtd->name = "cafe_nand"; |
@@ -775,8 +798,6 @@ static int cafe_nand_probe(struct pci_dev *pdev, | |||
775 | 798 | ||
776 | out_cleanup_nand: | 799 | out_cleanup_nand: |
777 | nand_cleanup(&cafe->nand); | 800 | nand_cleanup(&cafe->nand); |
778 | out_free_dma: | ||
779 | dma_free_coherent(&cafe->pdev->dev, 2112, cafe->dmabuf, cafe->dmaaddr); | ||
780 | out_irq: | 801 | out_irq: |
781 | /* Disable NAND IRQ in global IRQ mask register */ | 802 | /* Disable NAND IRQ in global IRQ mask register */ |
782 | cafe_writel(cafe, ~1 & cafe_readl(cafe, GLOBAL_IRQ_MASK), GLOBAL_IRQ_MASK); | 803 | cafe_writel(cafe, ~1 & cafe_readl(cafe, GLOBAL_IRQ_MASK), GLOBAL_IRQ_MASK); |