diff options
| author | Pekon Gupta <pekon@ti.com> | 2014-02-17 02:41:23 -0500 |
|---|---|---|
| committer | Brian Norris <computersforpeace@gmail.com> | 2014-02-23 17:49:56 -0500 |
| commit | eae39cb4934d3daab3ec828c5201c955b2e56af9 (patch) | |
| tree | f8bb7cc273f5d0db9e41425568ce16cc4394f145 | |
| parent | 28fa65e643ed7cf753e89db20745e264c41f3682 (diff) | |
mtd: nand: omap: fix ecclayout to be in sync with u-boot NAND driver
Fixes: commit a919e51161b58ed7e6e663daba99ab7d558808f3
mtd: nand: omap2: clean-up BCHx_HW and BCHx_SW ECC configurations in device_probe
Fixes ecclayout mismatch introduced in above commit for following ecc-schemes:
- OMAP_ECC_BCH4_CODE_HW_DETECTION_SW
- OMAP_ECC_BCH8_CODE_HW_DETECTION_SW
However, this patch also touches other ecc-schemes as the fix required
refactoring common code, into ecc-scheme specific code.
This patch aligns ecc-layout for below ecc-schemes as per reference [1],[2],[3]
+---+------------+-------------++-------------+-------------+
|OOB|BCH8_CODE_HW|BCH8_CODE_HW_||HAM1_CODE_HW |HAM1_CODE_HW |
|pos| | DETECTION_SW||(x8 device) |(x16 device) |
+---+------------+-------------++-------------+-------------+
| 0 |BADBLK_MARK | BADBLK_MARK || BADBLK_MARK | BADBLK_MARK |
| 1 |BADBLK_MARK | BADBLK_MARK || eccpos[0] | BADBLK_MARK |
| 2 | eccpos[0] | eccpos[0] || eccpos[1] | eccpos[0] |
| 3 | eccpos[1] | eccpos[1] || eccpos[2] | eccpos[1] |
| 4 | eccpos[2] | eccpos[2] || eccpos[3] | eccpos[2] |
| 5 | eccpos[3] | eccpos[3] || eccpos[4] | eccpos[3] |
| 6 | eccpos[4] | eccpos[4] || eccpos[5] | eccpos[4] |
| 7 | eccpos[5] | eccpos[5] || eccpos[6] | eccpos[5] |
| 8 | eccpos[6] | eccpos[6] || eccpos[7] | eccpos[6] |
| 9 | eccpos[7] | eccpos[7] || eccpos[8] | eccpos[7] |
|10 | eccpos[8] | eccpos[8] || eccpos[9] | eccpos[8] |
|11 | eccpos[9] | eccpos[9] || eccpos[10] | eccpos[9] |
|12 | eccpos[10] | eccpos[10] || eccpos[11] | eccpos[10] |
|13 | eccpos[11] | eccpos[11] || oobfree[0] | eccpos[11] |
|14 | eccpos[12] | eccpos[12] || oobfree[1] | oobfree[0] |
|15 | eccpos[13] | <reserved> || oobfree[2] | oobfree[1] |
+---+------------+-------------++-------------+-------------+
|16 | eccpos[14] | eccpos[13] || oobfree[3] | oobfree[2] |
|...| [...] | [...] || [...] | [...] |
|56 | eccpos[54] | eccpos[51] || oobfree[43] | oobfree[42] |
|57 | eccpos[55] | <reserved> || oobfree[44] | oobfree[43] |
+===+============+=============+==============+=============+
|58 | oobfree[0] | oobfree[0] || oobfree[45] | oobfree[44] |
|59 | oobfree[1] | oobfree[1] || oobfree[46] | oobfree[45] |
|60 | oobfree[2] | oobfree[2] || oobfree[47] | oobfree[46] |
|61 | oobfree[3] | oobfree[3] || oobfree[48] | oobfree[47] |
|62 | oobfree[4] | oobfree[4] || oobfree[49] | oobfree[48] |
|63 | oobfree[5] | oobfree[5] || oobfree[50] | oobfree[49] |
+---+------------+-------------+--------------+-------------+
[1] ecc-layout expected by ROM code, as specified in SoC TRM under:
Chapter="Initialization"
Section="Device Initialization by ROM code"
Sub-Section="Memory Booting"
Heading="NAND"
Figure="ECC Locations in NAND Spare Areas"
[2] ecc-layout updates in u-boot
http://lists.denx.de/pipermail/u-boot/2013-November/167551.html
[3] u-boot configurations to match above ecc-layout are documented at
https://processors.wiki.ti.com/index.php/Linux_Core_NAND_User%27s_Guide
CC: <stable@vger.kernel.org> # 3.13.x+
Reported-by: Enric Balletbo Serra <eballetbo@iseebcn.com>
Tested-by: Enric Balletbo i Serra <eballetbo@gmail.com>
Tested-by: Stefan Roese <sr@denx.de>
Signed-off-by: Pekon Gupta <pekon@ti.com>
Signed-off-by: Brian Norris <computersforpeace@gmail.com>
| -rw-r--r-- | drivers/mtd/nand/omap2.c | 31 |
1 files changed, 23 insertions, 8 deletions
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c index ef4190a02b7b..34ef941e3bfb 100644 --- a/drivers/mtd/nand/omap2.c +++ b/drivers/mtd/nand/omap2.c | |||
| @@ -1633,6 +1633,7 @@ static int omap_nand_probe(struct platform_device *pdev) | |||
| 1633 | int i; | 1633 | int i; |
| 1634 | dma_cap_mask_t mask; | 1634 | dma_cap_mask_t mask; |
| 1635 | unsigned sig; | 1635 | unsigned sig; |
| 1636 | unsigned oob_index; | ||
| 1636 | struct resource *res; | 1637 | struct resource *res; |
| 1637 | struct mtd_part_parser_data ppdata = {}; | 1638 | struct mtd_part_parser_data ppdata = {}; |
| 1638 | 1639 | ||
| @@ -1826,9 +1827,11 @@ static int omap_nand_probe(struct platform_device *pdev) | |||
| 1826 | (mtd->writesize / | 1827 | (mtd->writesize / |
| 1827 | nand_chip->ecc.size); | 1828 | nand_chip->ecc.size); |
| 1828 | if (nand_chip->options & NAND_BUSWIDTH_16) | 1829 | if (nand_chip->options & NAND_BUSWIDTH_16) |
| 1829 | ecclayout->eccpos[0] = BADBLOCK_MARKER_LENGTH; | 1830 | oob_index = BADBLOCK_MARKER_LENGTH; |
| 1830 | else | 1831 | else |
| 1831 | ecclayout->eccpos[0] = 1; | 1832 | oob_index = 1; |
| 1833 | for (i = 0; i < ecclayout->eccbytes; i++, oob_index++) | ||
| 1834 | ecclayout->eccpos[i] = oob_index; | ||
| 1832 | ecclayout->oobfree->offset = ecclayout->eccpos[0] + | 1835 | ecclayout->oobfree->offset = ecclayout->eccpos[0] + |
| 1833 | ecclayout->eccbytes; | 1836 | ecclayout->eccbytes; |
| 1834 | break; | 1837 | break; |
| @@ -1847,7 +1850,12 @@ static int omap_nand_probe(struct platform_device *pdev) | |||
| 1847 | ecclayout->eccbytes = nand_chip->ecc.bytes * | 1850 | ecclayout->eccbytes = nand_chip->ecc.bytes * |
| 1848 | (mtd->writesize / | 1851 | (mtd->writesize / |
| 1849 | nand_chip->ecc.size); | 1852 | nand_chip->ecc.size); |
| 1850 | ecclayout->eccpos[0] = BADBLOCK_MARKER_LENGTH; | 1853 | oob_index = BADBLOCK_MARKER_LENGTH; |
| 1854 | for (i = 0; i < ecclayout->eccbytes; i++, oob_index++) { | ||
| 1855 | ecclayout->eccpos[i] = oob_index; | ||
| 1856 | if (((i + 1) % nand_chip->ecc.bytes) == 0) | ||
| 1857 | oob_index++; | ||
| 1858 | } | ||
| 1851 | ecclayout->oobfree->offset = ecclayout->eccpos[0] + | 1859 | ecclayout->oobfree->offset = ecclayout->eccpos[0] + |
| 1852 | ecclayout->eccbytes; | 1860 | ecclayout->eccbytes; |
| 1853 | /* software bch library is used for locating errors */ | 1861 | /* software bch library is used for locating errors */ |
| @@ -1883,7 +1891,9 @@ static int omap_nand_probe(struct platform_device *pdev) | |||
| 1883 | ecclayout->eccbytes = nand_chip->ecc.bytes * | 1891 | ecclayout->eccbytes = nand_chip->ecc.bytes * |
| 1884 | (mtd->writesize / | 1892 | (mtd->writesize / |
| 1885 | nand_chip->ecc.size); | 1893 | nand_chip->ecc.size); |
| 1886 | ecclayout->eccpos[0] = BADBLOCK_MARKER_LENGTH; | 1894 | oob_index = BADBLOCK_MARKER_LENGTH; |
| 1895 | for (i = 0; i < ecclayout->eccbytes; i++, oob_index++) | ||
| 1896 | ecclayout->eccpos[i] = oob_index; | ||
| 1887 | ecclayout->oobfree->offset = ecclayout->eccpos[0] + | 1897 | ecclayout->oobfree->offset = ecclayout->eccpos[0] + |
| 1888 | ecclayout->eccbytes; | 1898 | ecclayout->eccbytes; |
| 1889 | /* This ECC scheme requires ELM H/W block */ | 1899 | /* This ECC scheme requires ELM H/W block */ |
| @@ -1913,7 +1923,12 @@ static int omap_nand_probe(struct platform_device *pdev) | |||
| 1913 | ecclayout->eccbytes = nand_chip->ecc.bytes * | 1923 | ecclayout->eccbytes = nand_chip->ecc.bytes * |
| 1914 | (mtd->writesize / | 1924 | (mtd->writesize / |
| 1915 | nand_chip->ecc.size); | 1925 | nand_chip->ecc.size); |
| 1916 | ecclayout->eccpos[0] = BADBLOCK_MARKER_LENGTH; | 1926 | oob_index = BADBLOCK_MARKER_LENGTH; |
| 1927 | for (i = 0; i < ecclayout->eccbytes; i++, oob_index++) { | ||
| 1928 | ecclayout->eccpos[i] = oob_index; | ||
| 1929 | if (((i + 1) % nand_chip->ecc.bytes) == 0) | ||
| 1930 | oob_index++; | ||
| 1931 | } | ||
| 1917 | ecclayout->oobfree->offset = ecclayout->eccpos[0] + | 1932 | ecclayout->oobfree->offset = ecclayout->eccpos[0] + |
| 1918 | ecclayout->eccbytes; | 1933 | ecclayout->eccbytes; |
| 1919 | /* software bch library is used for locating errors */ | 1934 | /* software bch library is used for locating errors */ |
| @@ -1956,7 +1971,9 @@ static int omap_nand_probe(struct platform_device *pdev) | |||
| 1956 | ecclayout->eccbytes = nand_chip->ecc.bytes * | 1971 | ecclayout->eccbytes = nand_chip->ecc.bytes * |
| 1957 | (mtd->writesize / | 1972 | (mtd->writesize / |
| 1958 | nand_chip->ecc.size); | 1973 | nand_chip->ecc.size); |
| 1959 | ecclayout->eccpos[0] = BADBLOCK_MARKER_LENGTH; | 1974 | oob_index = BADBLOCK_MARKER_LENGTH; |
| 1975 | for (i = 0; i < ecclayout->eccbytes; i++, oob_index++) | ||
| 1976 | ecclayout->eccpos[i] = oob_index; | ||
| 1960 | ecclayout->oobfree->offset = ecclayout->eccpos[0] + | 1977 | ecclayout->oobfree->offset = ecclayout->eccpos[0] + |
| 1961 | ecclayout->eccbytes; | 1978 | ecclayout->eccbytes; |
| 1962 | break; | 1979 | break; |
| @@ -1975,8 +1992,6 @@ static int omap_nand_probe(struct platform_device *pdev) | |||
| 1975 | /* populate remaining ECC layout data */ | 1992 | /* populate remaining ECC layout data */ |
| 1976 | ecclayout->oobfree->length = mtd->oobsize - (BADBLOCK_MARKER_LENGTH + | 1993 | ecclayout->oobfree->length = mtd->oobsize - (BADBLOCK_MARKER_LENGTH + |
| 1977 | ecclayout->eccbytes); | 1994 | ecclayout->eccbytes); |
| 1978 | for (i = 1; i < ecclayout->eccbytes; i++) | ||
| 1979 | ecclayout->eccpos[i] = ecclayout->eccpos[0] + i; | ||
| 1980 | /* check if NAND device's OOB is enough to store ECC signatures */ | 1995 | /* check if NAND device's OOB is enough to store ECC signatures */ |
| 1981 | if (mtd->oobsize < (ecclayout->eccbytes + BADBLOCK_MARKER_LENGTH)) { | 1996 | if (mtd->oobsize < (ecclayout->eccbytes + BADBLOCK_MARKER_LENGTH)) { |
| 1982 | pr_err("not enough OOB bytes required = %d, available=%d\n", | 1997 | pr_err("not enough OOB bytes required = %d, available=%d\n", |
