#define ECC_ENCCON             (0x00)
 #define ECC_ENCCNFG            (0x04)
-#define                ECC_MODE_SHIFT          (5)
 #define                ECC_MS_SHIFT            (16)
 #define ECC_ENCDIADDR          (0x08)
 #define ECC_ENCIDLE            (0x0C)
-#define ECC_ENCIRQ_EN          (0x80)
-#define ECC_ENCIRQ_STA         (0x84)
 #define ECC_DECCON             (0x100)
 #define ECC_DECCNFG            (0x104)
 #define                DEC_EMPTY_EN            BIT(31)
 #define                DEC_CNFG_CORRECT        (0x3 << 12)
 #define ECC_DECIDLE            (0x10C)
 #define ECC_DECENUM0           (0x114)
-#define ECC_DECDONE            (0x124)
-#define ECC_DECIRQ_EN          (0x200)
-#define ECC_DECIRQ_STA         (0x204)
 
 #define ECC_TIMEOUT            (500000)
 
 #define ECC_IDLE_REG(op)       ((op) == ECC_ENCODE ? ECC_ENCIDLE : ECC_DECIDLE)
 #define ECC_CTL_REG(op)                ((op) == ECC_ENCODE ? ECC_ENCCON : ECC_DECCON)
-#define ECC_IRQ_REG(op)                ((op) == ECC_ENCODE ? \
-                                       ECC_ENCIRQ_EN : ECC_DECIRQ_EN)
 
 struct mtk_ecc_caps {
        u32 err_mask;
        const u8 *ecc_strength;
+       const u32 *ecc_regs;
        u8 num_ecc_strength;
-       u32 encode_parity_reg0;
+       u8 ecc_mode_shift;
+       u32 parity_bits;
        int pg_irq_sel;
 };
 
        40, 44, 48, 52, 56, 60, 68, 72, 80
 };
 
+enum mtk_ecc_regs {
+       ECC_ENCPAR00,
+       ECC_ENCIRQ_EN,
+       ECC_ENCIRQ_STA,
+       ECC_DECDONE,
+       ECC_DECIRQ_EN,
+       ECC_DECIRQ_STA,
+};
+
+static int mt2701_ecc_regs[] = {
+       [ECC_ENCPAR00] =        0x10,
+       [ECC_ENCIRQ_EN] =       0x80,
+       [ECC_ENCIRQ_STA] =      0x84,
+       [ECC_DECDONE] =         0x124,
+       [ECC_DECIRQ_EN] =       0x200,
+       [ECC_DECIRQ_STA] =      0x204,
+};
+
+static int mt2712_ecc_regs[] = {
+       [ECC_ENCPAR00] =        0x300,
+       [ECC_ENCIRQ_EN] =       0x80,
+       [ECC_ENCIRQ_STA] =      0x84,
+       [ECC_DECDONE] =         0x124,
+       [ECC_DECIRQ_EN] =       0x200,
+       [ECC_DECIRQ_STA] =      0x204,
+};
+
 static inline void mtk_ecc_wait_idle(struct mtk_ecc *ecc,
                                     enum mtk_ecc_operation op)
 {
 static irqreturn_t mtk_ecc_irq(int irq, void *id)
 {
        struct mtk_ecc *ecc = id;
-       enum mtk_ecc_operation op;
        u32 dec, enc;
 
-       dec = readw(ecc->regs + ECC_DECIRQ_STA) & ECC_IRQ_EN;
+       dec = readw(ecc->regs + ecc->caps->ecc_regs[ECC_DECIRQ_STA])
+                   & ECC_IRQ_EN;
        if (dec) {
-               op = ECC_DECODE;
-               dec = readw(ecc->regs + ECC_DECDONE);
+               dec = readw(ecc->regs + ecc->caps->ecc_regs[ECC_DECDONE]);
                if (dec & ecc->sectors) {
                        /*
                         * Clear decode IRQ status once again to ensure that
                         * there will be no extra IRQ.
                         */
-                       readw(ecc->regs + ECC_DECIRQ_STA);
+                       readw(ecc->regs + ecc->caps->ecc_regs[ECC_DECIRQ_STA]);
                        ecc->sectors = 0;
                        complete(&ecc->done);
                } else {
                        return IRQ_HANDLED;
                }
        } else {
-               enc = readl(ecc->regs + ECC_ENCIRQ_STA) & ECC_IRQ_EN;
-               if (enc) {
-                       op = ECC_ENCODE;
+               enc = readl(ecc->regs + ecc->caps->ecc_regs[ECC_ENCIRQ_STA])
+                     & ECC_IRQ_EN;
+               if (enc)
                        complete(&ecc->done);
-               } else {
+               else
                        return IRQ_NONE;
-               }
        }
 
        return IRQ_HANDLED;
                /* configure ECC encoder (in bits) */
                enc_sz = config->len << 3;
 
-               reg = ecc_bit | (config->mode << ECC_MODE_SHIFT);
+               reg = ecc_bit | (config->mode << ecc->caps->ecc_mode_shift);
                reg |= (enc_sz << ECC_MS_SHIFT);
                writel(reg, ecc->regs + ECC_ENCCNFG);
 
        } else {
                /* configure ECC decoder (in bits) */
                dec_sz = (config->len << 3) +
-                                       config->strength * ECC_PARITY_BITS;
+                        config->strength * ecc->caps->parity_bits;
 
-               reg = ecc_bit | (config->mode << ECC_MODE_SHIFT);
+               reg = ecc_bit | (config->mode << ecc->caps->ecc_mode_shift);
                reg |= (dec_sz << ECC_MS_SHIFT) | DEC_CNFG_CORRECT;
                reg |= DEC_EMPTY_EN;
                writel(reg, ecc->regs + ECC_DECCNFG);
                 */
                if (ecc->caps->pg_irq_sel && config->mode == ECC_NFI_MODE)
                        reg_val |= ECC_PG_IRQ_SEL;
-               writew(reg_val, ecc->regs + ECC_IRQ_REG(op));
+               if (op == ECC_ENCODE)
+                       writew(reg_val, ecc->regs +
+                              ecc->caps->ecc_regs[ECC_ENCIRQ_EN]);
+               else
+                       writew(reg_val, ecc->regs +
+                              ecc->caps->ecc_regs[ECC_DECIRQ_EN]);
        }
 
        writew(ECC_OP_ENABLE, ecc->regs + ECC_CTL_REG(op));
 
        /* disable it */
        mtk_ecc_wait_idle(ecc, op);
-       if (op == ECC_DECODE)
+       if (op == ECC_DECODE) {
                /*
                 * Clear decode IRQ status in case there is a timeout to wait
                 * decode IRQ.
                 */
-               readw(ecc->regs + ECC_DECIRQ_STA);
-       writew(0, ecc->regs + ECC_IRQ_REG(op));
+               readw(ecc->regs + ecc->caps->ecc_regs[ECC_DECDONE]);
+               writew(0, ecc->regs + ecc->caps->ecc_regs[ECC_DECIRQ_EN]);
+       } else {
+               writew(0, ecc->regs + ecc->caps->ecc_regs[ECC_ENCIRQ_EN]);
+       }
+
        writew(ECC_OP_DISABLE, ecc->regs + ECC_CTL_REG(op));
 
        mutex_unlock(&ecc->lock);
        mtk_ecc_wait_idle(ecc, ECC_ENCODE);
 
        /* Program ECC bytes to OOB: per sector oob = FDM + ECC + SPARE */
-       len = (config->strength * ECC_PARITY_BITS + 7) >> 3;
+       len = (config->strength * ecc->caps->parity_bits + 7) >> 3;
 
        /* write the parity bytes generated by the ECC back to temp buffer */
        __ioread32_copy(ecc->eccdata,
-                       ecc->regs + ecc->caps->encode_parity_reg0,
+                       ecc->regs + ecc->caps->ecc_regs[ECC_ENCPAR00],
                        round_up(len, 4));
 
        /* copy into possibly unaligned OOB region with actual length */
 }
 EXPORT_SYMBOL(mtk_ecc_adjust_strength);
 
+unsigned int mtk_ecc_get_parity_bits(struct mtk_ecc *ecc)
+{
+       return ecc->caps->parity_bits;
+}
+EXPORT_SYMBOL(mtk_ecc_get_parity_bits);
+
 static const struct mtk_ecc_caps mtk_ecc_caps_mt2701 = {
        .err_mask = 0x3f,
        .ecc_strength = ecc_strength_mt2701,
+       .ecc_regs = mt2701_ecc_regs,
        .num_ecc_strength = 20,
-       .encode_parity_reg0 = 0x10,
+       .ecc_mode_shift = 5,
+       .parity_bits = 14,
        .pg_irq_sel = 0,
 };
 
 static const struct mtk_ecc_caps mtk_ecc_caps_mt2712 = {
        .err_mask = 0x7f,
        .ecc_strength = ecc_strength_mt2712,
+       .ecc_regs = mt2712_ecc_regs,
        .num_ecc_strength = 23,
-       .encode_parity_reg0 = 0x300,
+       .ecc_mode_shift = 5,
+       .parity_bits = 14,
        .pg_irq_sel = 1,
 };
 
 
        max_eccdata_size = ecc->caps->num_ecc_strength - 1;
        max_eccdata_size = ecc->caps->ecc_strength[max_eccdata_size];
-       max_eccdata_size = (max_eccdata_size * ECC_PARITY_BITS + 7) >> 3;
+       max_eccdata_size = (max_eccdata_size * ecc->caps->parity_bits + 7) >> 3;
        max_eccdata_size = round_up(max_eccdata_size, 4);
        ecc->eccdata = devm_kzalloc(dev, max_eccdata_size, GFP_KERNEL);
        if (!ecc->eccdata)
 
 
 #define MTK_TIMEOUT            (500000)
 #define MTK_RESET_TIMEOUT      (1000000)
-#define MTK_MAX_SECTOR         (16)
 #define MTK_NAND_MAX_NSELS     (2)
 #define MTK_NFC_MIN_SPARE      (16)
 #define ACCTIMING(tpoecs, tprecs, tc2r, tw2r, twh, twst, trlt) \
        u8 num_spare_size;
        u8 pageformat_spare_shift;
        u8 nfi_clk_div;
+       u8 max_sector;
+       u32 max_sector_size;
 };
 
 struct mtk_nfc_bad_mark_ctl {
                 * set to max sector to allow the HW to continue reading over
                 * unaligned accesses
                 */
-               reg = (MTK_MAX_SECTOR << CON_SEC_SHIFT) | CON_BRD;
+               reg = (nfc->caps->max_sector << CON_SEC_SHIFT) | CON_BRD;
                nfi_writel(nfc, reg, NFI_CON);
 
                /* trigger to fetch data */
                reg = nfi_readw(nfc, NFI_CNFG) | CNFG_BYTE_RW;
                nfi_writew(nfc, reg, NFI_CNFG);
 
-               reg = MTK_MAX_SECTOR << CON_SEC_SHIFT | CON_BWR;
+               reg = nfc->caps->max_sector << CON_SEC_SHIFT | CON_BWR;
                nfi_writel(nfc, reg, NFI_CON);
 
                nfi_writew(nfc, STAR_EN, NFI_STRDATA);
 {
        struct nand_chip *nand = mtd_to_nand(mtd);
        struct mtk_nfc_nand_chip *chip = to_mtk_nand(nand);
+       struct mtk_nfc *nfc = nand_get_controller_data(nand);
        u32 ecc_bytes;
 
-       ecc_bytes = DIV_ROUND_UP(nand->ecc.strength * ECC_PARITY_BITS, 8);
+       ecc_bytes = DIV_ROUND_UP(nand->ecc.strength *
+                                mtk_ecc_get_parity_bits(nfc->ecc), 8);
 
        fdm->reg_size = chip->spare_per_sector - ecc_bytes;
        if (fdm->reg_size > NFI_FDM_MAX_SIZE)
                 * this controller only supports 512 and 1024 sizes
                 */
                if (nand->ecc.size < 1024) {
-                       if (mtd->writesize > 512) {
+                       if (mtd->writesize > 512 &&
+                           nfc->caps->max_sector_size > 512) {
                                nand->ecc.size = 1024;
                                nand->ecc.strength <<= 1;
                        } else {
                        return ret;
 
                /* calculate oob bytes except ecc parity data */
-               free = ((nand->ecc.strength * ECC_PARITY_BITS) + 7) >> 3;
+               free = (nand->ecc.strength * mtk_ecc_get_parity_bits(nfc->ecc)
+                       + 7) >> 3;
                free = spare - free;
 
                /*
                 */
                if (free > NFI_FDM_MAX_SIZE) {
                        spare -= NFI_FDM_MAX_SIZE;
-                       nand->ecc.strength = (spare << 3) / ECC_PARITY_BITS;
+                       nand->ecc.strength = (spare << 3) /
+                                            mtk_ecc_get_parity_bits(nfc->ecc);
                } else if (free < 0) {
                        spare -= NFI_FDM_MIN_SIZE;
-                       nand->ecc.strength = (spare << 3) / ECC_PARITY_BITS;
+                       nand->ecc.strength = (spare << 3) /
+                                            mtk_ecc_get_parity_bits(nfc->ecc);
                }
        }
 
        .num_spare_size = 16,
        .pageformat_spare_shift = 4,
        .nfi_clk_div = 1,
+       .max_sector = 16,
+       .max_sector_size = 1024,
 };
 
 static const struct mtk_nfc_caps mtk_nfc_caps_mt2712 = {
        .num_spare_size = 19,
        .pageformat_spare_shift = 16,
        .nfi_clk_div = 2,
+       .max_sector = 16,
+       .max_sector_size = 1024,
 };
 
 static const struct of_device_id mtk_nfc_id_table[] = {