diff options
author | RogerCC Lin <rogercc.lin@mediatek.com> | 2016-09-18 22:53:26 -0400 |
---|---|---|
committer | Boris Brezillon <boris.brezillon@free-electrons.com> | 2016-09-19 05:57:04 -0400 |
commit | 559e58e7ed2dadc310f174e609ead8a3e8acfc4e (patch) | |
tree | 9c0ac8720cf9981916b58c53fecf687798f986a7 | |
parent | 7a353289925f01cb188ebc6fc4f4a33456b7de44 (diff) |
mtd: nand: fix chances to create incomplete ECC data when writing
When mtk_nfc_do_write_page() comparing the sector number,because the
sector number field is at the 12th-bit position of NFI_BYTELEN
register,the masked register should be shifted 12 bits before being
compared.The result of this bug may cause the second subpage has
incomplete ECC parity bytes.
Signed-off-by: RogerCC Lin <rogercc.lin@mediatek.com>
Fixes: 1d6b1e464950 ("mtd: mediatek: driver for MTK Smart Device")
Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>
-rw-r--r-- | drivers/mtd/nand/mtk_nand.c | 7 |
1 files changed, 5 insertions, 2 deletions
diff --git a/drivers/mtd/nand/mtk_nand.c b/drivers/mtd/nand/mtk_nand.c index ddaa2acb9dd7..5223a2182ee4 100644 --- a/drivers/mtd/nand/mtk_nand.c +++ b/drivers/mtd/nand/mtk_nand.c | |||
@@ -93,6 +93,9 @@ | |||
93 | #define NFI_FSM_MASK (0xf << 16) | 93 | #define NFI_FSM_MASK (0xf << 16) |
94 | #define NFI_ADDRCNTR (0x70) | 94 | #define NFI_ADDRCNTR (0x70) |
95 | #define CNTR_MASK GENMASK(16, 12) | 95 | #define CNTR_MASK GENMASK(16, 12) |
96 | #define ADDRCNTR_SEC_SHIFT (12) | ||
97 | #define ADDRCNTR_SEC(val) \ | ||
98 | (((val) & CNTR_MASK) >> ADDRCNTR_SEC_SHIFT) | ||
96 | #define NFI_STRADDR (0x80) | 99 | #define NFI_STRADDR (0x80) |
97 | #define NFI_BYTELEN (0x84) | 100 | #define NFI_BYTELEN (0x84) |
98 | #define NFI_CSEL (0x90) | 101 | #define NFI_CSEL (0x90) |
@@ -699,7 +702,7 @@ static int mtk_nfc_do_write_page(struct mtd_info *mtd, struct nand_chip *chip, | |||
699 | } | 702 | } |
700 | 703 | ||
701 | ret = readl_poll_timeout_atomic(nfc->regs + NFI_ADDRCNTR, reg, | 704 | ret = readl_poll_timeout_atomic(nfc->regs + NFI_ADDRCNTR, reg, |
702 | (reg & CNTR_MASK) >= chip->ecc.steps, | 705 | ADDRCNTR_SEC(reg) >= chip->ecc.steps, |
703 | 10, MTK_TIMEOUT); | 706 | 10, MTK_TIMEOUT); |
704 | if (ret) | 707 | if (ret) |
705 | dev_err(dev, "hwecc write timeout\n"); | 708 | dev_err(dev, "hwecc write timeout\n"); |
@@ -902,7 +905,7 @@ static int mtk_nfc_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, | |||
902 | dev_warn(nfc->dev, "read ahb/dma done timeout\n"); | 905 | dev_warn(nfc->dev, "read ahb/dma done timeout\n"); |
903 | 906 | ||
904 | rc = readl_poll_timeout_atomic(nfc->regs + NFI_BYTELEN, reg, | 907 | rc = readl_poll_timeout_atomic(nfc->regs + NFI_BYTELEN, reg, |
905 | (reg & CNTR_MASK) >= sectors, 10, | 908 | ADDRCNTR_SEC(reg) >= sectors, 10, |
906 | MTK_TIMEOUT); | 909 | MTK_TIMEOUT); |
907 | if (rc < 0) { | 910 | if (rc < 0) { |
908 | dev_err(nfc->dev, "subpage done timeout\n"); | 911 | dev_err(nfc->dev, "subpage done timeout\n"); |