summaryrefslogtreecommitdiff
path: root/drivers/mtd
diff options
context:
space:
mode:
authorHans de Goede <hdegoede@redhat.com>2015-08-15 12:41:09 +0200
committerHans de Goede <hdegoede@redhat.com>2015-08-31 08:43:41 +0200
commit008ac1dfe0815476cca819c16e06616c12c303b7 (patch)
tree28aa28cf4e37f8f361f755c0aced74769838d17f /drivers/mtd
parent2a43973f64bce7dba1a5aabd18f2268f062aa0ef (diff)
downloadu-boot-imx-008ac1dfe0815476cca819c16e06616c12c303b7.zip
u-boot-imx-008ac1dfe0815476cca819c16e06616c12c303b7.tar.gz
u-boot-imx-008ac1dfe0815476cca819c16e06616c12c303b7.tar.bz2
sunxi_nand_spl: Use kernel driver algorithm for determining ecc_mode / _off
Sync the code for figuring out the ecc_mode and ecc_offset with the linux kernel v4.1. Keeping this in sync seems like a good idea in general, and it fixes / adds support for ecc strengths of 56, 60 and 64 bits. Signed-off-by: Hans de Goede <hdegoede@redhat.com> Acked-by: Ian Campbell <ijc@hellion.org.uk>
Diffstat (limited to 'drivers/mtd')
-rw-r--r--drivers/mtd/nand/sunxi_nand_spl.c58
1 files changed, 12 insertions, 46 deletions
diff --git a/drivers/mtd/nand/sunxi_nand_spl.c b/drivers/mtd/nand/sunxi_nand_spl.c
index 663c03e..61eb393 100644
--- a/drivers/mtd/nand/sunxi_nand_spl.c
+++ b/drivers/mtd/nand/sunxi_nand_spl.c
@@ -181,60 +181,26 @@ static void nand_read_page(unsigned int real_addr, dma_addr_t dst,
int syndrome, uint32_t *ecc_errors)
{
uint32_t val;
- int ecc_off = 0;
+ int i, ecc_off = 0;
uint16_t ecc_mode = 0;
uint16_t rand_seed;
uint32_t page;
uint16_t column;
uint32_t oob_offset;
+ static const u8 strengths[] = { 16, 24, 28, 32, 40, 48, 56, 60, 64 };
- switch (CONFIG_NAND_SUNXI_SPL_ECC_STRENGTH) {
- case 16:
- ecc_mode = 0;
- ecc_off = 0x20;
- break;
- case 24:
- ecc_mode = 1;
- ecc_off = 0x2e;
- break;
- case 28:
- ecc_mode = 2;
- ecc_off = 0x32;
- break;
- case 32:
- ecc_mode = 3;
- ecc_off = 0x3c;
- break;
- case 40:
- ecc_mode = 4;
- ecc_off = 0x4a;
- break;
- case 48:
- ecc_mode = 4;
- ecc_off = 0x52;
- break;
- case 56:
- ecc_mode = 4;
- ecc_off = 0x60;
- break;
- case 60:
- ecc_mode = 4;
- ecc_off = 0x0;
- break;
- case 64:
- ecc_mode = 4;
- ecc_off = 0x0;
- break;
- default:
- ecc_mode = 0;
- ecc_off = 0;
+ for (i = 0; i < ARRAY_SIZE(strengths); i++) {
+ if (CONFIG_NAND_SUNXI_SPL_ECC_STRENGTH == strengths[i]) {
+ ecc_mode = i;
+ break;
+ }
}
- if (ecc_off == 0) {
- printf("Unsupported ECC strength (%d)!\n",
- CONFIG_NAND_SUNXI_SPL_ECC_STRENGTH);
- return;
- }
+ /* HW ECC always request ECC bytes for 1024 bytes blocks */
+ ecc_off = DIV_ROUND_UP(CONFIG_NAND_SUNXI_SPL_ECC_STRENGTH * fls(8 * 1024), 8);
+ /* HW ECC always work with even numbers of ECC bytes */
+ ecc_off += (ecc_off & 1);
+ ecc_off += 4; /* prepad */
page = real_addr / CONFIG_NAND_SUNXI_SPL_PAGE_SIZE;
column = real_addr % CONFIG_NAND_SUNXI_SPL_PAGE_SIZE;