123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380 |
- From fd1a1eabf2473e769b5cafc704e0336d11f61961 Mon Sep 17 00:00:00 2001
- From: RogerCC Lin <[email protected]>
- Date: Thu, 30 Nov 2017 22:10:44 +0800
- Subject: [PATCH 166/224] mtd: nand: mtk: Support different MTK NAND flash
- controller IP
- MT7622 uses an MTK's earlier NAND flash controller IP which support
- different sector size, max spare size per sector and paraity bits...,
- some register's offset and definition also been changed in the NAND
- flash controller, this patch is the preparation to support MT7622
- NAND flash controller.
- MT7622 NFC and ECC engine are similar to MT2701's, except below
- differences:
- (1)MT7622 NFC's max sector size(ECC data size) is 512 bytes, and
- MT2701's is 1024, and MT7622's max sector number is 8.
- (2)The parity bit of MT7622 is 13, MT2701 is 14.
- (3)MT7622 ECC supports less ECC strength, max to 16 bit ecc strength.
- (4)MT7622 supports less spare size per sector, max spare size per
- sector is 28 bytes.
- (5)Some register's offset are different, include ECC_ENCIRQ_EN,
- ECC_ENCIRQ_STA, ECC_DECDONE, ECC_DECIRQ_EN and ECC_DECIRQ_STA.
- (6)ENC_MODE of ECC_ENCCNFG register is moved from bit 5-6 to bit 4-5.
- Signed-off-by: RogerCC Lin <[email protected]>
- Signed-off-by: Boris Brezillon <[email protected]>
- ---
- drivers/mtd/nand/mtk_ecc.c | 100 ++++++++++++++++++++++++++++++--------------
- drivers/mtd/nand/mtk_ecc.h | 3 +-
- drivers/mtd/nand/mtk_nand.c | 27 ++++++++----
- 3 files changed, 89 insertions(+), 41 deletions(-)
- --- a/drivers/mtd/nand/mtk_ecc.c
- +++ b/drivers/mtd/nand/mtk_ecc.c
- @@ -34,34 +34,28 @@
-
- #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;
- };
-
- @@ -89,6 +83,33 @@ static const u8 ecc_strength_mt2712[] =
- 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)
- {
- @@ -107,32 +128,30 @@ static inline void mtk_ecc_wait_idle(str
- 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;
- @@ -160,7 +179,7 @@ static int mtk_ecc_config(struct mtk_ecc
- /* 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);
-
- @@ -171,9 +190,9 @@ static int mtk_ecc_config(struct mtk_ecc
- } 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);
- @@ -291,7 +310,12 @@ int mtk_ecc_enable(struct mtk_ecc *ecc,
- */
- 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));
- @@ -310,13 +334,17 @@ void mtk_ecc_disable(struct mtk_ecc *ecc
-
- /* 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);
- @@ -367,11 +395,11 @@ int mtk_ecc_encode(struct mtk_ecc *ecc,
- 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 */
- @@ -404,19 +432,29 @@ void mtk_ecc_adjust_strength(struct mtk_
- }
- 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,
- };
-
- @@ -452,7 +490,7 @@ static int mtk_ecc_probe(struct platform
-
- 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)
- --- a/drivers/mtd/nand/mtk_ecc.h
- +++ b/drivers/mtd/nand/mtk_ecc.h
- @@ -14,8 +14,6 @@
-
- #include <linux/types.h>
-
- -#define ECC_PARITY_BITS (14)
- -
- enum mtk_ecc_mode {ECC_DMA_MODE = 0, ECC_NFI_MODE = 1};
- enum mtk_ecc_operation {ECC_ENCODE, ECC_DECODE};
-
- @@ -43,6 +41,7 @@ int mtk_ecc_wait_done(struct mtk_ecc *,
- int mtk_ecc_enable(struct mtk_ecc *, struct mtk_ecc_config *);
- void mtk_ecc_disable(struct mtk_ecc *);
- void mtk_ecc_adjust_strength(struct mtk_ecc *ecc, u32 *p);
- +unsigned int mtk_ecc_get_parity_bits(struct mtk_ecc *ecc);
-
- struct mtk_ecc *of_mtk_ecc_get(struct device_node *);
- void mtk_ecc_release(struct mtk_ecc *);
- --- a/drivers/mtd/nand/mtk_nand.c
- +++ b/drivers/mtd/nand/mtk_nand.c
- @@ -97,7 +97,6 @@
-
- #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) \
- @@ -109,6 +108,8 @@ struct mtk_nfc_caps {
- 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 {
- @@ -450,7 +451,7 @@ static inline u8 mtk_nfc_read_byte(struc
- * 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 */
- @@ -481,7 +482,7 @@ static void mtk_nfc_write_byte(struct mt
- 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);
- @@ -1126,9 +1127,11 @@ static void mtk_nfc_set_fdm(struct mtk_n
- {
- 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)
- @@ -1208,7 +1211,8 @@ static int mtk_nfc_ecc_init(struct devic
- * 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 {
- @@ -1223,7 +1227,8 @@ static int mtk_nfc_ecc_init(struct devic
- 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;
-
- /*
- @@ -1233,10 +1238,12 @@ static int mtk_nfc_ecc_init(struct devic
- */
- 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);
- }
- }
-
- @@ -1389,6 +1396,8 @@ static const struct mtk_nfc_caps mtk_nfc
- .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 = {
- @@ -1396,6 +1405,8 @@ static const struct mtk_nfc_caps mtk_nfc
- .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[] = {
|