diff options
author | Pekon Gupta <pekon@ti.com> | 2013-10-24 08:50:23 -0400 |
---|---|---|
committer | Brian Norris <computersforpeace@gmail.com> | 2013-11-07 02:33:10 -0500 |
commit | 32d42a855a6f1445373f3d680e9125344aca294c (patch) | |
tree | 3831d11370ec53ab0a30ec38b1545288b47a2abe /drivers/mtd/nand/omap2.c | |
parent | b491da7233d5dc1a24d46ca1ad0209900329c5d0 (diff) |
mtd: nand: omap: use drivers/mtd/nand/nand_bch.c wrapper for BCH ECC instead of lib/bch.c
generic frame-work in mtd/nand/nand_bch.c is a wrapper above lib/bch.h which
encapsulates all control information specific to BCH ecc algorithm in software.
Thus this patch:
(1) replace omap specific implementations with equivalent wrapper in nand_bch.c
so that generic code from nand_bch.c is re-used. like;
omap3_correct_data_bch() -> nand_bch_correct_data()
omap3_free_bch() -> nand_bch_free()
(2) replace direct calls to lib/bch.c with wrapper functions defined in nand_bch.c
init_bch() -> nand_bch_init()
Signed-off-by: Pekon Gupta <pekon@ti.com>
Tested-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
Signed-off-by: Brian Norris <computersforpeace@gmail.com>
Diffstat (limited to 'drivers/mtd/nand/omap2.c')
-rw-r--r-- | drivers/mtd/nand/omap2.c | 96 |
1 files changed, 22 insertions, 74 deletions
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c index b6a08b23853b..93aa35c8260c 100644 --- a/drivers/mtd/nand/omap2.c +++ b/drivers/mtd/nand/omap2.c | |||
@@ -25,7 +25,7 @@ | |||
25 | #include <linux/of.h> | 25 | #include <linux/of.h> |
26 | #include <linux/of_device.h> | 26 | #include <linux/of_device.h> |
27 | 27 | ||
28 | #include <linux/bch.h> | 28 | #include <linux/mtd/nand_bch.h> |
29 | #include <linux/platform_data/elm.h> | 29 | #include <linux/platform_data/elm.h> |
30 | 30 | ||
31 | #include <linux/platform_data/mtd-nand-omap2.h> | 31 | #include <linux/platform_data/mtd-nand-omap2.h> |
@@ -140,7 +140,6 @@ | |||
140 | #define BCH_ECC_SIZE1 0x20 /* ecc_size1 = 32 */ | 140 | #define BCH_ECC_SIZE1 0x20 /* ecc_size1 = 32 */ |
141 | 141 | ||
142 | #define BADBLOCK_MARKER_LENGTH 2 | 142 | #define BADBLOCK_MARKER_LENGTH 2 |
143 | #define OMAP_ECC_BCH8_POLYNOMIAL 0x201b | ||
144 | 143 | ||
145 | #ifdef CONFIG_MTD_NAND_OMAP_BCH | 144 | #ifdef CONFIG_MTD_NAND_OMAP_BCH |
146 | static u_char bch8_vector[] = {0xf3, 0xdb, 0x14, 0x16, 0x8b, 0xd2, 0xbe, 0xcc, | 145 | static u_char bch8_vector[] = {0xf3, 0xdb, 0x14, 0x16, 0x8b, 0xd2, 0xbe, 0xcc, |
@@ -173,7 +172,6 @@ struct omap_nand_info { | |||
173 | int buf_len; | 172 | int buf_len; |
174 | struct gpmc_nand_regs reg; | 173 | struct gpmc_nand_regs reg; |
175 | /* fields specific for BCHx_HW ECC scheme */ | 174 | /* fields specific for BCHx_HW ECC scheme */ |
176 | struct bch_control *bch; | ||
177 | bool is_elm_used; | 175 | bool is_elm_used; |
178 | struct device *elm_dev; | 176 | struct device *elm_dev; |
179 | struct device_node *of_node; | 177 | struct device_node *of_node; |
@@ -1507,43 +1505,7 @@ static int omap_elm_correct_data(struct mtd_info *mtd, u_char *data, | |||
1507 | 1505 | ||
1508 | return stat; | 1506 | return stat; |
1509 | } | 1507 | } |
1510 | #endif /* CONFIG_MTD_NAND_OMAP_BCH */ | ||
1511 | 1508 | ||
1512 | #ifdef CONFIG_MTD_NAND_ECC_BCH | ||
1513 | /** | ||
1514 | * omap3_correct_data_bch - Decode received data and correct errors | ||
1515 | * @mtd: MTD device structure | ||
1516 | * @data: page data | ||
1517 | * @read_ecc: ecc read from nand flash | ||
1518 | * @calc_ecc: ecc read from HW ECC registers | ||
1519 | */ | ||
1520 | static int omap3_correct_data_bch(struct mtd_info *mtd, u_char *data, | ||
1521 | u_char *read_ecc, u_char *calc_ecc) | ||
1522 | { | ||
1523 | int i, count; | ||
1524 | /* cannot correct more than 8 errors */ | ||
1525 | unsigned int errloc[8]; | ||
1526 | struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, | ||
1527 | mtd); | ||
1528 | |||
1529 | count = decode_bch(info->bch, NULL, 512, read_ecc, calc_ecc, NULL, | ||
1530 | errloc); | ||
1531 | if (count > 0) { | ||
1532 | /* correct errors */ | ||
1533 | for (i = 0; i < count; i++) { | ||
1534 | /* correct data only, not ecc bytes */ | ||
1535 | if (errloc[i] < 8*512) | ||
1536 | data[errloc[i]/8] ^= 1 << (errloc[i] & 7); | ||
1537 | pr_debug("corrected bitflip %u\n", errloc[i]); | ||
1538 | } | ||
1539 | } else if (count < 0) { | ||
1540 | pr_err("ecc unrecoverable error\n"); | ||
1541 | } | ||
1542 | return count; | ||
1543 | } | ||
1544 | #endif /* CONFIG_MTD_NAND_ECC_BCH */ | ||
1545 | |||
1546 | #ifdef CONFIG_MTD_NAND_OMAP_BCH | ||
1547 | /** | 1509 | /** |
1548 | * omap_write_page_bch - BCH ecc based write page function for entire page | 1510 | * omap_write_page_bch - BCH ecc based write page function for entire page |
1549 | * @mtd: mtd info structure | 1511 | * @mtd: mtd info structure |
@@ -1660,28 +1622,6 @@ static int is_elm_present(struct omap_nand_info *info, | |||
1660 | } | 1622 | } |
1661 | #endif /* CONFIG_MTD_NAND_ECC_BCH */ | 1623 | #endif /* CONFIG_MTD_NAND_ECC_BCH */ |
1662 | 1624 | ||
1663 | #ifdef CONFIG_MTD_NAND_ECC_BCH | ||
1664 | /** | ||
1665 | * omap3_free_bch - Release BCH ecc resources | ||
1666 | * @mtd: MTD device structure | ||
1667 | */ | ||
1668 | static void omap3_free_bch(struct mtd_info *mtd) | ||
1669 | { | ||
1670 | struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, | ||
1671 | mtd); | ||
1672 | if (info->bch) { | ||
1673 | free_bch(info->bch); | ||
1674 | info->bch = NULL; | ||
1675 | } | ||
1676 | } | ||
1677 | |||
1678 | #else | ||
1679 | |||
1680 | static void omap3_free_bch(struct mtd_info *mtd) | ||
1681 | { | ||
1682 | } | ||
1683 | #endif /* CONFIG_MTD_NAND_ECC_BCH */ | ||
1684 | |||
1685 | static int omap_nand_probe(struct platform_device *pdev) | 1625 | static int omap_nand_probe(struct platform_device *pdev) |
1686 | { | 1626 | { |
1687 | struct omap_nand_info *info; | 1627 | struct omap_nand_info *info; |
@@ -1714,13 +1654,13 @@ static int omap_nand_probe(struct platform_device *pdev) | |||
1714 | info->pdev = pdev; | 1654 | info->pdev = pdev; |
1715 | info->gpmc_cs = pdata->cs; | 1655 | info->gpmc_cs = pdata->cs; |
1716 | info->reg = pdata->reg; | 1656 | info->reg = pdata->reg; |
1717 | info->bch = NULL; | ||
1718 | info->of_node = pdata->of_node; | 1657 | info->of_node = pdata->of_node; |
1719 | mtd = &info->mtd; | 1658 | mtd = &info->mtd; |
1720 | mtd->priv = &info->nand; | 1659 | mtd->priv = &info->nand; |
1721 | mtd->name = dev_name(&pdev->dev); | 1660 | mtd->name = dev_name(&pdev->dev); |
1722 | mtd->owner = THIS_MODULE; | 1661 | mtd->owner = THIS_MODULE; |
1723 | nand_chip = &info->nand; | 1662 | nand_chip = &info->nand; |
1663 | nand_chip->ecc.priv = NULL; | ||
1724 | nand_chip->options |= NAND_SKIP_BBTSCAN; | 1664 | nand_chip->options |= NAND_SKIP_BBTSCAN; |
1725 | 1665 | ||
1726 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1666 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
@@ -1903,7 +1843,7 @@ static int omap_nand_probe(struct platform_device *pdev) | |||
1903 | nand_chip->ecc.bytes = 7; | 1843 | nand_chip->ecc.bytes = 7; |
1904 | nand_chip->ecc.strength = 4; | 1844 | nand_chip->ecc.strength = 4; |
1905 | nand_chip->ecc.hwctl = omap3_enable_hwecc_bch; | 1845 | nand_chip->ecc.hwctl = omap3_enable_hwecc_bch; |
1906 | nand_chip->ecc.correct = omap3_correct_data_bch; | 1846 | nand_chip->ecc.correct = nand_bch_correct_data; |
1907 | nand_chip->ecc.calculate = omap3_calculate_ecc_bch4; | 1847 | nand_chip->ecc.calculate = omap3_calculate_ecc_bch4; |
1908 | /* define ECC layout */ | 1848 | /* define ECC layout */ |
1909 | ecclayout->eccbytes = nand_chip->ecc.bytes * | 1849 | ecclayout->eccbytes = nand_chip->ecc.bytes * |
@@ -1913,10 +1853,11 @@ static int omap_nand_probe(struct platform_device *pdev) | |||
1913 | ecclayout->oobfree->offset = ecclayout->eccpos[0] + | 1853 | ecclayout->oobfree->offset = ecclayout->eccpos[0] + |
1914 | ecclayout->eccbytes; | 1854 | ecclayout->eccbytes; |
1915 | /* software bch library is used for locating errors */ | 1855 | /* software bch library is used for locating errors */ |
1916 | info->bch = init_bch(nand_chip->ecc.bytes, | 1856 | nand_chip->ecc.priv = nand_bch_init(mtd, |
1917 | nand_chip->ecc.strength, | 1857 | nand_chip->ecc.size, |
1918 | OMAP_ECC_BCH8_POLYNOMIAL); | 1858 | nand_chip->ecc.bytes, |
1919 | if (!info->bch) { | 1859 | &nand_chip->ecc.layout); |
1860 | if (!nand_chip->ecc.priv) { | ||
1920 | pr_err("nand: error: unable to use s/w BCH library\n"); | 1861 | pr_err("nand: error: unable to use s/w BCH library\n"); |
1921 | err = -EINVAL; | 1862 | err = -EINVAL; |
1922 | } | 1863 | } |
@@ -1968,7 +1909,7 @@ static int omap_nand_probe(struct platform_device *pdev) | |||
1968 | nand_chip->ecc.bytes = 13; | 1909 | nand_chip->ecc.bytes = 13; |
1969 | nand_chip->ecc.strength = 8; | 1910 | nand_chip->ecc.strength = 8; |
1970 | nand_chip->ecc.hwctl = omap3_enable_hwecc_bch; | 1911 | nand_chip->ecc.hwctl = omap3_enable_hwecc_bch; |
1971 | nand_chip->ecc.correct = omap3_correct_data_bch; | 1912 | nand_chip->ecc.correct = nand_bch_correct_data; |
1972 | nand_chip->ecc.calculate = omap3_calculate_ecc_bch8; | 1913 | nand_chip->ecc.calculate = omap3_calculate_ecc_bch8; |
1973 | /* define ECC layout */ | 1914 | /* define ECC layout */ |
1974 | ecclayout->eccbytes = nand_chip->ecc.bytes * | 1915 | ecclayout->eccbytes = nand_chip->ecc.bytes * |
@@ -1978,10 +1919,11 @@ static int omap_nand_probe(struct platform_device *pdev) | |||
1978 | ecclayout->oobfree->offset = ecclayout->eccpos[0] + | 1919 | ecclayout->oobfree->offset = ecclayout->eccpos[0] + |
1979 | ecclayout->eccbytes; | 1920 | ecclayout->eccbytes; |
1980 | /* software bch library is used for locating errors */ | 1921 | /* software bch library is used for locating errors */ |
1981 | info->bch = init_bch(nand_chip->ecc.bytes, | 1922 | nand_chip->ecc.priv = nand_bch_init(mtd, |
1982 | nand_chip->ecc.strength, | 1923 | nand_chip->ecc.size, |
1983 | OMAP_ECC_BCH8_POLYNOMIAL); | 1924 | nand_chip->ecc.bytes, |
1984 | if (!info->bch) { | 1925 | &nand_chip->ecc.layout); |
1926 | if (!nand_chip->ecc.priv) { | ||
1985 | pr_err("nand: error: unable to use s/w BCH library\n"); | 1927 | pr_err("nand: error: unable to use s/w BCH library\n"); |
1986 | err = -EINVAL; | 1928 | err = -EINVAL; |
1987 | goto out_release_mem_region; | 1929 | goto out_release_mem_region; |
@@ -2067,7 +2009,10 @@ out_release_mem_region: | |||
2067 | free_irq(info->gpmc_irq_fifo, info); | 2009 | free_irq(info->gpmc_irq_fifo, info); |
2068 | release_mem_region(info->phys_base, info->mem_size); | 2010 | release_mem_region(info->phys_base, info->mem_size); |
2069 | out_free_info: | 2011 | out_free_info: |
2070 | omap3_free_bch(mtd); | 2012 | if (nand_chip->ecc.priv) { |
2013 | nand_bch_free(nand_chip->ecc.priv); | ||
2014 | nand_chip->ecc.priv = NULL; | ||
2015 | } | ||
2071 | kfree(info); | 2016 | kfree(info); |
2072 | 2017 | ||
2073 | return err; | 2018 | return err; |
@@ -2079,7 +2024,10 @@ static int omap_nand_remove(struct platform_device *pdev) | |||
2079 | struct nand_chip *nand_chip = mtd->priv; | 2024 | struct nand_chip *nand_chip = mtd->priv; |
2080 | struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, | 2025 | struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, |
2081 | mtd); | 2026 | mtd); |
2082 | omap3_free_bch(mtd); | 2027 | if (nand_chip->ecc.priv) { |
2028 | nand_bch_free(nand_chip->ecc.priv); | ||
2029 | nand_chip->ecc.priv = NULL; | ||
2030 | } | ||
2083 | 2031 | ||
2084 | if (info->dma) | 2032 | if (info->dma) |
2085 | dma_release_channel(info->dma); | 2033 | dma_release_channel(info->dma); |