mtd: nand: fsmc: get rid of IO_ADDR_[R|W]
authorMiquel Raynal <miquel.raynal@bootlin.com>
Fri, 16 Feb 2018 14:22:47 +0000 (15:22 +0100)
committerBoris Brezillon <boris.brezillon@bootlin.com>
Sat, 17 Feb 2018 08:25:46 +0000 (09:25 +0100)
Remove the use of IO_ADDR_[R|W] in the fsmc_nand driver. Instead, use a
pointer to the control registers to avoid doing several arithmetic
operations (including a multiplication) each time a control register is
read or written.

All references to IO_ADDR_[R|W] are not entirely removed from the driver
as, at this time, these values are needed by the NAND core in the
default ->read/write_byte/word() hooks. These references will be
entirely removed when switching to ->exec_op(), that does not make use
of these hooks anymore.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
drivers/mtd/nand/raw/fsmc_nand.c

index 7e66268..75a825d 100644 (file)
 #define ECC3                   0x1C
 #define FSMC_NAND_BANK_SZ      0x20
 
-#define FSMC_NAND_REG(base, bank, reg)         (base + FSMC_NOR_REG_SIZE + \
-                                               (FSMC_NAND_BANK_SZ * (bank)) + \
-                                               reg)
-
 #define FSMC_BUSY_WAIT_TIMEOUT (1 * HZ)
 
 struct fsmc_nand_timings {
@@ -143,7 +139,7 @@ enum access_mode {
  * @data_va:           NAND port for Data.
  * @cmd_va:            NAND port for Command.
  * @addr_va:           NAND port for Address.
- * @regs_va:           FSMC regs base address.
+ * @regs_va:           Registers base address for a given bank.
  */
 struct fsmc_nand_data {
        u32                     pid;
@@ -265,8 +261,6 @@ static void fsmc_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
 {
        struct nand_chip *this = mtd_to_nand(mtd);
        struct fsmc_nand_data *host = mtd_to_fsmc(mtd);
-       void __iomem *regs = host->regs_va;
-       unsigned int bank = host->bank;
 
        if (ctrl & NAND_CTRL_CHANGE) {
                u32 pc;
@@ -282,12 +276,12 @@ static void fsmc_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
                        this->IO_ADDR_W = host->data_va;
                }
 
-               pc = readl(FSMC_NAND_REG(regs, bank, PC));
+               pc = readl(host->regs_va + PC);
                if (ctrl & NAND_NCE)
                        pc |= FSMC_ENABLE;
                else
                        pc &= ~FSMC_ENABLE;
-               writel_relaxed(pc, FSMC_NAND_REG(regs, bank, PC));
+               writel_relaxed(pc, host->regs_va + PC);
        }
 
        mb();
@@ -307,8 +301,6 @@ static void fsmc_nand_setup(struct fsmc_nand_data *host,
 {
        uint32_t value = FSMC_DEVTYPE_NAND | FSMC_ENABLE | FSMC_WAITON;
        uint32_t tclr, tar, thiz, thold, twait, tset;
-       unsigned int bank = host->bank;
-       void __iomem *regs = host->regs_va;
 
        tclr = (tims->tclr & FSMC_TCLR_MASK) << FSMC_TCLR_SHIFT;
        tar = (tims->tar & FSMC_TAR_MASK) << FSMC_TAR_SHIFT;
@@ -318,18 +310,14 @@ static void fsmc_nand_setup(struct fsmc_nand_data *host,
        tset = (tims->tset & FSMC_TSET_MASK) << FSMC_TSET_SHIFT;
 
        if (host->nand.options & NAND_BUSWIDTH_16)
-               writel_relaxed(value | FSMC_DEVWID_16,
-                               FSMC_NAND_REG(regs, bank, PC));
+               writel_relaxed(value | FSMC_DEVWID_16, host->regs_va + PC);
        else
-               writel_relaxed(value | FSMC_DEVWID_8,
-                               FSMC_NAND_REG(regs, bank, PC));
-
-       writel_relaxed(readl(FSMC_NAND_REG(regs, bank, PC)) | tclr | tar,
-                       FSMC_NAND_REG(regs, bank, PC));
-       writel_relaxed(thiz | thold | twait | tset,
-                       FSMC_NAND_REG(regs, bank, COMM));
-       writel_relaxed(thiz | thold | twait | tset,
-                       FSMC_NAND_REG(regs, bank, ATTRIB));
+               writel_relaxed(value | FSMC_DEVWID_8, host->regs_va + PC);
+
+       writel_relaxed(readl(host->regs_va + PC) | tclr | tar,
+                      host->regs_va + PC);
+       writel_relaxed(thiz | thold | twait | tset, host->regs_va + COMM);
+       writel_relaxed(thiz | thold | twait | tset, host->regs_va + ATTRIB);
 }
 
 static int fsmc_calc_timings(struct fsmc_nand_data *host,
@@ -419,15 +407,13 @@ static int fsmc_setup_data_interface(struct mtd_info *mtd, int csline,
 static void fsmc_enable_hwecc(struct mtd_info *mtd, int mode)
 {
        struct fsmc_nand_data *host = mtd_to_fsmc(mtd);
-       void __iomem *regs = host->regs_va;
-       uint32_t bank = host->bank;
-
-       writel_relaxed(readl(FSMC_NAND_REG(regs, bank, PC)) & ~FSMC_ECCPLEN_256,
-                       FSMC_NAND_REG(regs, bank, PC));
-       writel_relaxed(readl(FSMC_NAND_REG(regs, bank, PC)) & ~FSMC_ECCEN,
-                       FSMC_NAND_REG(regs, bank, PC));
-       writel_relaxed(readl(FSMC_NAND_REG(regs, bank, PC)) | FSMC_ECCEN,
-                       FSMC_NAND_REG(regs, bank, PC));
+
+       writel_relaxed(readl(host->regs_va + PC) & ~FSMC_ECCPLEN_256,
+                      host->regs_va + PC);
+       writel_relaxed(readl(host->regs_va + PC) & ~FSMC_ECCEN,
+                      host->regs_va + PC);
+       writel_relaxed(readl(host->regs_va + PC) | FSMC_ECCEN,
+                      host->regs_va + PC);
 }
 
 /*
@@ -439,13 +425,11 @@ static int fsmc_read_hwecc_ecc4(struct mtd_info *mtd, const uint8_t *data,
                                uint8_t *ecc)
 {
        struct fsmc_nand_data *host = mtd_to_fsmc(mtd);
-       void __iomem *regs = host->regs_va;
-       uint32_t bank = host->bank;
        uint32_t ecc_tmp;
        unsigned long deadline = jiffies + FSMC_BUSY_WAIT_TIMEOUT;
 
        do {
-               if (readl_relaxed(FSMC_NAND_REG(regs, bank, STS)) & FSMC_CODE_RDY)
+               if (readl_relaxed(host->regs_va + STS) & FSMC_CODE_RDY)
                        break;
                else
                        cond_resched();
@@ -456,25 +440,25 @@ static int fsmc_read_hwecc_ecc4(struct mtd_info *mtd, const uint8_t *data,
                return -ETIMEDOUT;
        }
 
-       ecc_tmp = readl_relaxed(FSMC_NAND_REG(regs, bank, ECC1));
+       ecc_tmp = readl_relaxed(host->regs_va + ECC1);
        ecc[0] = (uint8_t) (ecc_tmp >> 0);
        ecc[1] = (uint8_t) (ecc_tmp >> 8);
        ecc[2] = (uint8_t) (ecc_tmp >> 16);
        ecc[3] = (uint8_t) (ecc_tmp >> 24);
 
-       ecc_tmp = readl_relaxed(FSMC_NAND_REG(regs, bank, ECC2));
+       ecc_tmp = readl_relaxed(host->regs_va + ECC2);
        ecc[4] = (uint8_t) (ecc_tmp >> 0);
        ecc[5] = (uint8_t) (ecc_tmp >> 8);
        ecc[6] = (uint8_t) (ecc_tmp >> 16);
        ecc[7] = (uint8_t) (ecc_tmp >> 24);
 
-       ecc_tmp = readl_relaxed(FSMC_NAND_REG(regs, bank, ECC3));
+       ecc_tmp = readl_relaxed(host->regs_va + ECC3);
        ecc[8] = (uint8_t) (ecc_tmp >> 0);
        ecc[9] = (uint8_t) (ecc_tmp >> 8);
        ecc[10] = (uint8_t) (ecc_tmp >> 16);
        ecc[11] = (uint8_t) (ecc_tmp >> 24);
 
-       ecc_tmp = readl_relaxed(FSMC_NAND_REG(regs, bank, STS));
+       ecc_tmp = readl_relaxed(host->regs_va + STS);
        ecc[12] = (uint8_t) (ecc_tmp >> 16);
 
        return 0;
@@ -489,11 +473,9 @@ static int fsmc_read_hwecc_ecc1(struct mtd_info *mtd, const uint8_t *data,
                                uint8_t *ecc)
 {
        struct fsmc_nand_data *host = mtd_to_fsmc(mtd);
-       void __iomem *regs = host->regs_va;
-       uint32_t bank = host->bank;
        uint32_t ecc_tmp;
 
-       ecc_tmp = readl_relaxed(FSMC_NAND_REG(regs, bank, ECC1));
+       ecc_tmp = readl_relaxed(host->regs_va + ECC1);
        ecc[0] = (uint8_t) (ecc_tmp >> 0);
        ecc[1] = (uint8_t) (ecc_tmp >> 8);
        ecc[2] = (uint8_t) (ecc_tmp >> 16);
@@ -598,18 +580,18 @@ unmap_dma:
  */
 static void fsmc_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
 {
+       struct fsmc_nand_data *host  = mtd_to_fsmc(mtd);
        int i;
-       struct nand_chip *chip = mtd_to_nand(mtd);
 
        if (IS_ALIGNED((uint32_t)buf, sizeof(uint32_t)) &&
                        IS_ALIGNED(len, sizeof(uint32_t))) {
                uint32_t *p = (uint32_t *)buf;
                len = len >> 2;
                for (i = 0; i < len; i++)
-                       writel_relaxed(p[i], chip->IO_ADDR_W);
+                       writel_relaxed(p[i], host->data_va);
        } else {
                for (i = 0; i < len; i++)
-                       writeb_relaxed(buf[i], chip->IO_ADDR_W);
+                       writeb_relaxed(buf[i], host->data_va);
        }
 }
 
@@ -621,18 +603,18 @@ static void fsmc_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
  */
 static void fsmc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
 {
+       struct fsmc_nand_data *host  = mtd_to_fsmc(mtd);
        int i;
-       struct nand_chip *chip = mtd_to_nand(mtd);
 
        if (IS_ALIGNED((uint32_t)buf, sizeof(uint32_t)) &&
                        IS_ALIGNED(len, sizeof(uint32_t))) {
                uint32_t *p = (uint32_t *)buf;
                len = len >> 2;
                for (i = 0; i < len; i++)
-                       p[i] = readl_relaxed(chip->IO_ADDR_R);
+                       p[i] = readl_relaxed(host->data_va);
        } else {
                for (i = 0; i < len; i++)
-                       buf[i] = readb_relaxed(chip->IO_ADDR_R);
+                       buf[i] = readb_relaxed(host->data_va);
        }
 }
 
@@ -754,13 +736,11 @@ static int fsmc_bch8_correct_data(struct mtd_info *mtd, uint8_t *dat,
 {
        struct nand_chip *chip = mtd_to_nand(mtd);
        struct fsmc_nand_data *host = mtd_to_fsmc(mtd);
-       void __iomem *regs = host->regs_va;
-       unsigned int bank = host->bank;
        uint32_t err_idx[8];
        uint32_t num_err, i;
        uint32_t ecc1, ecc2, ecc3, ecc4;
 
-       num_err = (readl_relaxed(FSMC_NAND_REG(regs, bank, STS)) >> 10) & 0xF;
+       num_err = (readl_relaxed(host->regs_va + STS) >> 10) & 0xF;
 
        /* no bit flipping */
        if (likely(num_err == 0))
@@ -803,10 +783,10 @@ static int fsmc_bch8_correct_data(struct mtd_info *mtd, uint8_t *dat,
         * uint64_t array and error offset indexes are populated in err_idx
         * array
         */
-       ecc1 = readl_relaxed(FSMC_NAND_REG(regs, bank, ECC1));
-       ecc2 = readl_relaxed(FSMC_NAND_REG(regs, bank, ECC2));
-       ecc3 = readl_relaxed(FSMC_NAND_REG(regs, bank, ECC3));
-       ecc4 = readl_relaxed(FSMC_NAND_REG(regs, bank, STS));
+       ecc1 = readl_relaxed(host->regs_va + ECC1);
+       ecc2 = readl_relaxed(host->regs_va + ECC2);
+       ecc3 = readl_relaxed(host->regs_va + ECC3);
+       ecc4 = readl_relaxed(host->regs_va + STS);
 
        err_idx[0] = (ecc1 >> 0) & 0x1FFF;
        err_idx[1] = (ecc1 >> 13) & 0x1FFF;
@@ -889,6 +869,7 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
        struct mtd_info *mtd;
        struct nand_chip *nand;
        struct resource *res;
+       void __iomem *base;
        dma_cap_mask_t mask;
        int ret = 0;
        u32 pid;
@@ -923,9 +904,12 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
                return PTR_ERR(host->cmd_va);
 
        res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "fsmc_regs");
-       host->regs_va = devm_ioremap_resource(&pdev->dev, res);
-       if (IS_ERR(host->regs_va))
-               return PTR_ERR(host->regs_va);
+       base = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(base))
+               return PTR_ERR(base);
+
+       host->regs_va = base + FSMC_NOR_REG_SIZE +
+               (host->bank * FSMC_NAND_BANK_SZ);
 
        host->clk = devm_clk_get(&pdev->dev, NULL);
        if (IS_ERR(host->clk)) {
@@ -942,7 +926,7 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
         * AMBA PrimeCell bus. However it is not a PrimeCell.
         */
        for (pid = 0, i = 0; i < 4; i++)
-               pid |= (readl(host->regs_va + resource_size(res) - 0x20 + 4 * i) & 255) << (i * 8);
+               pid |= (readl(base + resource_size(res) - 0x20 + 4 * i) & 255) << (i * 8);
        host->pid = pid;
        dev_info(&pdev->dev, "FSMC device partno %03x, manufacturer %02x, "
                 "revision %02x, config %02x\n",