cfi_flash: Fix logical continuations
[oweals/u-boot.git] / drivers / mtd / nand / mxc_nand.c
index 62d69650638ba277774f1db7b2a51b47787e3aa0..764391c8d2c9e14fba160923c1fbf9f39b58fd32 100644 (file)
@@ -3,19 +3,7 @@
  * Copyright 2008 Sascha Hauer, kernel@pengutronix.de
  * Copyright 2009 Ilya Yanok, <yanok@emcraft.com>
  *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301, USA.
+ * SPDX-License-Identifier:    GPL-2.0+
  */
 
 #include <common.h>
        defined(CONFIG_MX51) || defined(CONFIG_MX53)
 #include <asm/arch/imx-regs.h>
 #endif
-#include <fsl_nfc.h>
+#include "mxc_nand.h"
 
 #define DRIVER_NAME "mxc_nand"
 
-typedef enum {false, true} bool;
-
 struct mxc_nand_host {
-       struct mtd_info                 mtd;
        struct nand_chip                *nand;
 
-       struct fsl_nfc_regs __iomem     *regs;
+       struct mxc_nand_regs __iomem    *regs;
 #ifdef MXC_NFC_V3_2
-       struct fsl_nfc_ip_regs __iomem  *ip_regs;
+       struct mxc_nand_ip_regs __iomem *ip_regs;
 #endif
        int                             spare_only;
        int                             status_request;
@@ -147,7 +132,7 @@ static void wait_op_done(struct mxc_nand_host *host, int max_retries,
                udelay(1);
        }
        if (max_retries < 0) {
-               MTDDEBUG(MTD_DEBUG_LEVEL0, "%s(%d): INT not set\n",
+               pr_debug("%s(%d): INT not set\n",
                                __func__, param);
        }
 }
@@ -158,7 +143,7 @@ static void wait_op_done(struct mxc_nand_host *host, int max_retries,
  */
 static void send_cmd(struct mxc_nand_host *host, uint16_t cmd)
 {
-       MTDDEBUG(MTD_DEBUG_LEVEL3, "send_cmd(host, 0x%x)\n", cmd);
+       pr_debug("send_cmd(host, 0x%x)\n", cmd);
 
        writenfc(cmd, &host->regs->flash_cmd);
        writenfc(NFC_CMD, &host->regs->operation);
@@ -174,7 +159,7 @@ static void send_cmd(struct mxc_nand_host *host, uint16_t cmd)
  */
 static void send_addr(struct mxc_nand_host *host, uint16_t addr)
 {
-       MTDDEBUG(MTD_DEBUG_LEVEL3, "send_addr(host, 0x%x)\n", addr);
+       pr_debug("send_addr(host, 0x%x)\n", addr);
 
        writenfc(addr, &host->regs->flash_addr);
        writenfc(NFC_ADDR, &host->regs->operation);
@@ -191,7 +176,7 @@ static void send_prog_page(struct mxc_nand_host *host, uint8_t buf_id,
                        int spare_only)
 {
        if (spare_only)
-               MTDDEBUG(MTD_DEBUG_LEVEL1, "send_prog_page (%d)\n", spare_only);
+               pr_debug("send_prog_page (%d)\n", spare_only);
 
        if (is_mxc_nfc_21() || is_mxc_nfc_32()) {
                int i;
@@ -241,7 +226,7 @@ static void send_prog_page(struct mxc_nand_host *host, uint8_t buf_id,
 static void send_read_page(struct mxc_nand_host *host, uint8_t buf_id,
                int spare_only)
 {
-       MTDDEBUG(MTD_DEBUG_LEVEL3, "send_read_page (%d)\n", spare_only);
+       pr_debug("send_read_page (%d)\n", spare_only);
 
 #if defined(MXC_NFC_V1) || defined(MXC_NFC_V2_1)
        writenfc(buf_id, &host->regs->buf_addr);
@@ -365,8 +350,8 @@ static int mxc_nand_dev_ready(struct mtd_info *mtd)
 
 static void _mxc_nand_enable_hwecc(struct mtd_info *mtd, int on)
 {
-       struct nand_chip *nand_chip = mtd->priv;
-       struct mxc_nand_host *host = nand_chip->priv;
+       struct nand_chip *nand_chip = mtd_to_nand(mtd);
+       struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
 #if defined(MXC_NFC_V1) || defined(MXC_NFC_V2_1)
        uint16_t tmp = readnfc(&host->regs->config1);
 
@@ -398,17 +383,16 @@ static void mxc_nand_enable_hwecc(struct mtd_info *mtd, int mode)
 #if defined(MXC_NFC_V2_1) || defined(MXC_NFC_V3_2)
 static int mxc_nand_read_oob_syndrome(struct mtd_info *mtd,
                                      struct nand_chip *chip,
-                                     int page, int sndcmd)
+                                     int page)
 {
-       struct mxc_nand_host *host = chip->priv;
+       struct mxc_nand_host *host = nand_get_controller_data(chip);
        uint8_t *buf = chip->oob_poi;
        int length = mtd->oobsize;
        int eccpitch = chip->ecc.bytes + chip->ecc.prepad + chip->ecc.postpad;
        uint8_t *bufpoi = buf;
        int i, toread;
 
-       MTDDEBUG(MTD_DEBUG_LEVEL0,
-                       "%s: Reading OOB area of page %u to oob %p\n",
+       pr_debug("%s: Reading OOB area of page %u to oob %p\n",
                         __func__, page, buf);
 
        chip->cmdfunc(mtd, NAND_CMD_READOOB, mtd->writesize, page);
@@ -452,9 +436,10 @@ static int mxc_nand_read_oob_syndrome(struct mtd_info *mtd,
 static int mxc_nand_read_page_raw_syndrome(struct mtd_info *mtd,
                                           struct nand_chip *chip,
                                           uint8_t *buf,
+                                          int oob_required,
                                           int page)
 {
-       struct mxc_nand_host *host = chip->priv;
+       struct mxc_nand_host *host = nand_get_controller_data(chip);
        int eccsize = chip->ecc.size;
        int eccbytes = chip->ecc.bytes;
        int eccpitch = eccbytes + chip->ecc.prepad + chip->ecc.postpad;
@@ -463,7 +448,7 @@ static int mxc_nand_read_page_raw_syndrome(struct mtd_info *mtd,
        int n;
 
        _mxc_nand_enable_hwecc(mtd, 0);
-       chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, host->page_addr);
+       chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page);
 
        for (n = 0, steps = chip->ecc.steps; steps > 0; n++, steps--) {
                host->col_addr = n * eccsize;
@@ -496,9 +481,10 @@ static int mxc_nand_read_page_raw_syndrome(struct mtd_info *mtd,
 static int mxc_nand_read_page_syndrome(struct mtd_info *mtd,
                                       struct nand_chip *chip,
                                       uint8_t *buf,
+                                      int oob_required,
                                       int page)
 {
-       struct mxc_nand_host *host = chip->priv;
+       struct mxc_nand_host *host = nand_get_controller_data(chip);
        int n, eccsize = chip->ecc.size;
        int eccbytes = chip->ecc.bytes;
        int eccpitch = eccbytes + chip->ecc.prepad + chip->ecc.postpad;
@@ -506,8 +492,8 @@ static int mxc_nand_read_page_syndrome(struct mtd_info *mtd,
        uint8_t *p = buf;
        uint8_t *oob = chip->oob_poi;
 
-       MTDDEBUG(MTD_DEBUG_LEVEL1, "Reading page %u to buf %p oob %p\n",
-             host->page_addr, buf, oob);
+       pr_debug("Reading page %u to buf %p oob %p\n",
+                page, buf, oob);
 
        /* first read the data area and the available portion of OOB */
        for (n = 0; eccsteps; n++, eccsteps--, p += eccsize) {
@@ -545,7 +531,7 @@ static int mxc_nand_read_page_syndrome(struct mtd_info *mtd,
 
        /* Then switch ECC off and read the OOB area to get the ECC code */
        _mxc_nand_enable_hwecc(mtd, 0);
-       chip->cmdfunc(mtd, NAND_CMD_READOOB, mtd->writesize, host->page_addr);
+       chip->cmdfunc(mtd, NAND_CMD_READOOB, mtd->writesize, page);
        eccsteps = chip->ecc.steps;
        oob = chip->oob_poi + chip->ecc.prepad;
        for (n = 0; eccsteps; n++, eccsteps--, p += eccsize) {
@@ -562,7 +548,7 @@ static int mxc_nand_read_page_syndrome(struct mtd_info *mtd,
 static int mxc_nand_write_oob_syndrome(struct mtd_info *mtd,
                                       struct nand_chip *chip, int page)
 {
-       struct mxc_nand_host *host = chip->priv;
+       struct mxc_nand_host *host = nand_get_controller_data(chip);
        int eccpitch = chip->ecc.bytes + chip->ecc.prepad + chip->ecc.postpad;
        int length = mtd->oobsize;
        int i, len, status, steps = chip->ecc.steps;
@@ -585,11 +571,12 @@ static int mxc_nand_write_oob_syndrome(struct mtd_info *mtd,
        return status & NAND_STATUS_FAIL ? -EIO : 0;
 }
 
-static void mxc_nand_write_page_raw_syndrome(struct mtd_info *mtd,
+static int mxc_nand_write_page_raw_syndrome(struct mtd_info *mtd,
                                             struct nand_chip *chip,
-                                            const uint8_t *buf)
+                                            const uint8_t *buf,
+                                            int oob_required, int page)
 {
-       struct mxc_nand_host *host = chip->priv;
+       struct mxc_nand_host *host = nand_get_controller_data(chip);
        int eccsize = chip->ecc.size;
        int eccbytes = chip->ecc.bytes;
        int eccpitch = eccbytes + chip->ecc.prepad + chip->ecc.postpad;
@@ -621,13 +608,15 @@ static void mxc_nand_write_page_raw_syndrome(struct mtd_info *mtd,
        size = mtd->oobsize - (oob - chip->oob_poi);
        if (size)
                chip->write_buf(mtd, oob, size);
+       return 0;
 }
 
-static void mxc_nand_write_page_syndrome(struct mtd_info *mtd,
+static int mxc_nand_write_page_syndrome(struct mtd_info *mtd,
                                         struct nand_chip *chip,
-                                        const uint8_t *buf)
+                                        const uint8_t *buf,
+                                        int oob_required, int page)
 {
-       struct mxc_nand_host *host = chip->priv;
+       struct mxc_nand_host *host = nand_get_controller_data(chip);
        int i, n, eccsize = chip->ecc.size;
        int eccbytes = chip->ecc.bytes;
        int eccpitch = eccbytes + chip->ecc.prepad + chip->ecc.postpad;
@@ -664,13 +653,14 @@ static void mxc_nand_write_page_syndrome(struct mtd_info *mtd,
        i = mtd->oobsize - (oob - chip->oob_poi);
        if (i)
                chip->write_buf(mtd, oob, i);
+       return 0;
 }
 
 static int mxc_nand_correct_data(struct mtd_info *mtd, u_char *dat,
                                 u_char *read_ecc, u_char *calc_ecc)
 {
-       struct nand_chip *nand_chip = mtd->priv;
-       struct mxc_nand_host *host = nand_chip->priv;
+       struct nand_chip *nand_chip = mtd_to_nand(mtd);
+       struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
        uint32_t ecc_status = readl(&host->regs->ecc_status_result);
        int subpages = mtd->writesize / nand_chip->subpagesize;
        int pg2blk_shift = nand_chip->phys_erase_shift -
@@ -689,7 +679,7 @@ static int mxc_nand_correct_data(struct mtd_info *mtd, u_char *dat,
                                       mtd->writesize / nand_chip->subpagesize
                                            - subpages);
                        }
-                       return -1;
+                       return -EBADMSG;
                }
                ecc_status >>= 4;
                subpages--;
@@ -708,8 +698,8 @@ static int mxc_nand_correct_data(struct mtd_info *mtd, u_char *dat,
 static int mxc_nand_correct_data(struct mtd_info *mtd, u_char *dat,
                                 u_char *read_ecc, u_char *calc_ecc)
 {
-       struct nand_chip *nand_chip = mtd->priv;
-       struct mxc_nand_host *host = nand_chip->priv;
+       struct nand_chip *nand_chip = mtd_to_nand(mtd);
+       struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
 
        /*
         * 1-Bit errors are automatically corrected in HW.  No need for
@@ -719,9 +709,8 @@ static int mxc_nand_correct_data(struct mtd_info *mtd, u_char *dat,
        uint16_t ecc_status = readnfc(&host->regs->ecc_status_result);
 
        if (((ecc_status & 0x3) == 2) || ((ecc_status >> 2) == 2)) {
-               MTDDEBUG(MTD_DEBUG_LEVEL0,
-                     "MXC_NAND: HWECC uncorrectable 2-bit ECC error\n");
-               return -1;
+               pr_debug("MXC_NAND: HWECC uncorrectable 2-bit ECC error\n");
+               return -EBADMSG;
        }
 
        return 0;
@@ -737,8 +726,8 @@ static int mxc_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
 
 static u_char mxc_nand_read_byte(struct mtd_info *mtd)
 {
-       struct nand_chip *nand_chip = mtd->priv;
-       struct mxc_nand_host *host = nand_chip->priv;
+       struct nand_chip *nand_chip = mtd_to_nand(mtd);
+       struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
        uint8_t ret = 0;
        uint16_t col;
        uint16_t __iomem *main_buf =
@@ -777,13 +766,12 @@ static u_char mxc_nand_read_byte(struct mtd_info *mtd)
 
 static uint16_t mxc_nand_read_word(struct mtd_info *mtd)
 {
-       struct nand_chip *nand_chip = mtd->priv;
-       struct mxc_nand_host *host = nand_chip->priv;
+       struct nand_chip *nand_chip = mtd_to_nand(mtd);
+       struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
        uint16_t col, ret;
        uint16_t __iomem *p;
 
-       MTDDEBUG(MTD_DEBUG_LEVEL3,
-             "mxc_nand_read_word(col = %d)\n", host->col_addr);
+       pr_debug("mxc_nand_read_word(col = %d)\n", host->col_addr);
 
        col = host->col_addr;
        /* Adjust saved column address */
@@ -829,13 +817,12 @@ static uint16_t mxc_nand_read_word(struct mtd_info *mtd)
 static void mxc_nand_write_buf(struct mtd_info *mtd,
                                const u_char *buf, int len)
 {
-       struct nand_chip *nand_chip = mtd->priv;
-       struct mxc_nand_host *host = nand_chip->priv;
+       struct nand_chip *nand_chip = mtd_to_nand(mtd);
+       struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
        int n, col, i = 0;
 
-       MTDDEBUG(MTD_DEBUG_LEVEL3,
-             "mxc_nand_write_buf(col = %d, len = %d)\n", host->col_addr,
-             len);
+       pr_debug("mxc_nand_write_buf(col = %d, len = %d)\n", host->col_addr,
+                len);
 
        col = host->col_addr;
 
@@ -846,8 +833,7 @@ static void mxc_nand_write_buf(struct mtd_info *mtd,
        n = mtd->writesize + mtd->oobsize - col;
        n = min(len, n);
 
-       MTDDEBUG(MTD_DEBUG_LEVEL3,
-             "%s:%d: col = %d, n = %d\n", __func__, __LINE__, col, n);
+       pr_debug("%s:%d: col = %d, n = %d\n", __func__, __LINE__, col, n);
 
        while (n > 0) {
                void __iomem *p;
@@ -859,8 +845,8 @@ static void mxc_nand_write_buf(struct mtd_info *mtd,
                                                mtd->writesize + (col & ~3);
                }
 
-               MTDDEBUG(MTD_DEBUG_LEVEL3, "%s:%d: p = %p\n", __func__,
-                     __LINE__, p);
+               pr_debug("%s:%d: p = %p\n", __func__,
+                        __LINE__, p);
 
                if (((col | (unsigned long)&buf[i]) & 3) || n < 4) {
                        union {
@@ -882,9 +868,8 @@ static void mxc_nand_write_buf(struct mtd_info *mtd,
 
                        m = min(n, m) & ~3;
 
-                       MTDDEBUG(MTD_DEBUG_LEVEL3,
-                             "%s:%d: n = %d, m = %d, i = %d, col = %d\n",
-                             __func__,  __LINE__, n, m, i, col);
+                       pr_debug("%s:%d: n = %d, m = %d, i = %d, col = %d\n",
+                                __func__,  __LINE__, n, m, i, col);
 
                        mxc_nand_memcpy32(p, (uint32_t *)&buf[i], m);
                        col += m;
@@ -903,12 +888,12 @@ static void mxc_nand_write_buf(struct mtd_info *mtd,
  */
 static void mxc_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
 {
-       struct nand_chip *nand_chip = mtd->priv;
-       struct mxc_nand_host *host = nand_chip->priv;
+       struct nand_chip *nand_chip = mtd_to_nand(mtd);
+       struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
        int n, col, i = 0;
 
-       MTDDEBUG(MTD_DEBUG_LEVEL3,
-             "mxc_nand_read_buf(col = %d, len = %d)\n", host->col_addr, len);
+       pr_debug("mxc_nand_read_buf(col = %d, len = %d)\n", host->col_addr,
+                len);
 
        col = host->col_addr;
 
@@ -957,38 +942,14 @@ static void mxc_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
        host->col_addr = col;
 }
 
-/*
- * Used by the upper layer to verify the data in NAND Flash
- * with the data in the buf.
- */
-static int mxc_nand_verify_buf(struct mtd_info *mtd,
-                               const u_char *buf, int len)
-{
-       u_char tmp[256];
-       uint bsize;
-
-       while (len) {
-               bsize = min(len, 256);
-               mxc_nand_read_buf(mtd, tmp, bsize);
-
-               if (memcmp(buf, tmp, bsize))
-                       return 1;
-
-               buf += bsize;
-               len -= bsize;
-       }
-
-       return 0;
-}
-
 /*
  * This function is used by upper layer for select and
  * deselect of the NAND chip
  */
 static void mxc_nand_select_chip(struct mtd_info *mtd, int chip)
 {
-       struct nand_chip *nand_chip = mtd->priv;
-       struct mxc_nand_host *host = nand_chip->priv;
+       struct nand_chip *nand_chip = mtd_to_nand(mtd);
+       struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
 
        switch (chip) {
        case -1:
@@ -1014,12 +975,11 @@ static void mxc_nand_select_chip(struct mtd_info *mtd, int chip)
 void mxc_nand_command(struct mtd_info *mtd, unsigned command,
                                int column, int page_addr)
 {
-       struct nand_chip *nand_chip = mtd->priv;
-       struct mxc_nand_host *host = nand_chip->priv;
+       struct nand_chip *nand_chip = mtd_to_nand(mtd);
+       struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
 
-       MTDDEBUG(MTD_DEBUG_LEVEL3,
-             "mxc_nand_command (cmd = 0x%x, col = 0x%x, page = 0x%x)\n",
-             command, column, page_addr);
+       pr_debug("mxc_nand_command (cmd = 0x%x, col = 0x%x, page = 0x%x)\n",
+                command, column, page_addr);
 
        /* Reset command state information */
        host->status_request = false;
@@ -1190,20 +1150,19 @@ int board_nand_init(struct nand_chip *this)
 #endif
 
 #ifdef CONFIG_SYS_NAND_USE_FLASH_BBT
-       this->options |= NAND_USE_FLASH_BBT;
+       this->bbt_options |= NAND_BBT_USE_FLASH;
        this->bbt_td = &bbt_main_descr;
        this->bbt_md = &bbt_mirror_descr;
 #endif
 
        /* structures must be linked */
-       mtd = &host->mtd;
-       mtd->priv = this;
+       mtd = &this->mtd;
        host->nand = this;
 
        /* 5 us command delay time */
        this->chip_delay = 5;
 
-       this->priv = host;
+       nand_set_controller_data(this, host);
        this->dev_ready = mxc_nand_dev_ready;
        this->cmdfunc = mxc_nand_command;
        this->select_chip = mxc_nand_select_chip;
@@ -1211,12 +1170,11 @@ int board_nand_init(struct nand_chip *this)
        this->read_word = mxc_nand_read_word;
        this->write_buf = mxc_nand_write_buf;
        this->read_buf = mxc_nand_read_buf;
-       this->verify_buf = mxc_nand_verify_buf;
 
-       host->regs = (struct fsl_nfc_regs __iomem *)CONFIG_MXC_NAND_REGS_BASE;
+       host->regs = (struct mxc_nand_regs __iomem *)CONFIG_MXC_NAND_REGS_BASE;
 #ifdef MXC_NFC_V3_2
        host->ip_regs =
-               (struct fsl_nfc_ip_regs __iomem *)CONFIG_MXC_NAND_IP_REGS_BASE;
+               (struct mxc_nand_ip_regs __iomem *)CONFIG_MXC_NAND_IP_REGS_BASE;
 #endif
        host->clk_act = 1;
 
@@ -1238,6 +1196,11 @@ int board_nand_init(struct nand_chip *this)
                this->ecc.mode = NAND_ECC_HW;
        }
 
+       if (is_mxc_nfc_1())
+               this->ecc.strength = 1;
+       else
+               this->ecc.strength = 4;
+
        host->pagesize_2k = 0;
 
        this->ecc.size = 512;