summaryrefslogtreecommitdiffstats
path: root/drivers/mtd/nand/gpmi-nand
diff options
context:
space:
mode:
authorBoris Brezillon <boris.brezillon@bootlin.com>2018-02-05 23:02:04 +0100
committerBoris Brezillon <boris.brezillon@bootlin.com>2018-02-16 10:09:34 +0100
commit93db446a424cee9387b532995e6b516667079555 (patch)
tree39c7900ae38d890fb971ea5fc6f194f7e66fa797 /drivers/mtd/nand/gpmi-nand
parentmtd: nand: Add missing copyright information (diff)
downloadlinux-93db446a424cee9387b532995e6b516667079555.tar.xz
linux-93db446a424cee9387b532995e6b516667079555.zip
mtd: nand: move raw NAND related code to the raw/ subdir
As part of the process of sharing more code between different NAND based devices, we need to move all raw NAND related code to the raw/ subdirectory. Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
Diffstat (limited to 'drivers/mtd/nand/gpmi-nand')
-rw-r--r--drivers/mtd/nand/gpmi-nand/Makefile3
-rw-r--r--drivers/mtd/nand/gpmi-nand/bch-regs.h128
-rw-r--r--drivers/mtd/nand/gpmi-nand/gpmi-lib.c1510
-rw-r--r--drivers/mtd/nand/gpmi-nand/gpmi-nand.c2182
-rw-r--r--drivers/mtd/nand/gpmi-nand/gpmi-nand.h315
-rw-r--r--drivers/mtd/nand/gpmi-nand/gpmi-regs.h187
6 files changed, 0 insertions, 4325 deletions
diff --git a/drivers/mtd/nand/gpmi-nand/Makefile b/drivers/mtd/nand/gpmi-nand/Makefile
deleted file mode 100644
index 3a462487c35e..000000000000
--- a/drivers/mtd/nand/gpmi-nand/Makefile
+++ /dev/null
@@ -1,3 +0,0 @@
-obj-$(CONFIG_MTD_NAND_GPMI_NAND) += gpmi_nand.o
-gpmi_nand-objs += gpmi-nand.o
-gpmi_nand-objs += gpmi-lib.o
diff --git a/drivers/mtd/nand/gpmi-nand/bch-regs.h b/drivers/mtd/nand/gpmi-nand/bch-regs.h
deleted file mode 100644
index 05bb91f2f4c4..000000000000
--- a/drivers/mtd/nand/gpmi-nand/bch-regs.h
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Freescale GPMI NAND Flash Driver
- *
- * Copyright 2008-2011 Freescale Semiconductor, Inc.
- * Copyright 2008 Embedded Alley Solutions, Inc.
- *
- * 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.
- */
-#ifndef __GPMI_NAND_BCH_REGS_H
-#define __GPMI_NAND_BCH_REGS_H
-
-#define HW_BCH_CTRL 0x00000000
-#define HW_BCH_CTRL_SET 0x00000004
-#define HW_BCH_CTRL_CLR 0x00000008
-#define HW_BCH_CTRL_TOG 0x0000000c
-
-#define BM_BCH_CTRL_COMPLETE_IRQ_EN (1 << 8)
-#define BM_BCH_CTRL_COMPLETE_IRQ (1 << 0)
-
-#define HW_BCH_STATUS0 0x00000010
-#define HW_BCH_MODE 0x00000020
-#define HW_BCH_ENCODEPTR 0x00000030
-#define HW_BCH_DATAPTR 0x00000040
-#define HW_BCH_METAPTR 0x00000050
-#define HW_BCH_LAYOUTSELECT 0x00000070
-
-#define HW_BCH_FLASH0LAYOUT0 0x00000080
-
-#define BP_BCH_FLASH0LAYOUT0_NBLOCKS 24
-#define BM_BCH_FLASH0LAYOUT0_NBLOCKS (0xff << BP_BCH_FLASH0LAYOUT0_NBLOCKS)
-#define BF_BCH_FLASH0LAYOUT0_NBLOCKS(v) \
- (((v) << BP_BCH_FLASH0LAYOUT0_NBLOCKS) & BM_BCH_FLASH0LAYOUT0_NBLOCKS)
-
-#define BP_BCH_FLASH0LAYOUT0_META_SIZE 16
-#define BM_BCH_FLASH0LAYOUT0_META_SIZE (0xff << BP_BCH_FLASH0LAYOUT0_META_SIZE)
-#define BF_BCH_FLASH0LAYOUT0_META_SIZE(v) \
- (((v) << BP_BCH_FLASH0LAYOUT0_META_SIZE)\
- & BM_BCH_FLASH0LAYOUT0_META_SIZE)
-
-#define BP_BCH_FLASH0LAYOUT0_ECC0 12
-#define BM_BCH_FLASH0LAYOUT0_ECC0 (0xf << BP_BCH_FLASH0LAYOUT0_ECC0)
-#define MX6Q_BP_BCH_FLASH0LAYOUT0_ECC0 11
-#define MX6Q_BM_BCH_FLASH0LAYOUT0_ECC0 (0x1f << MX6Q_BP_BCH_FLASH0LAYOUT0_ECC0)
-#define BF_BCH_FLASH0LAYOUT0_ECC0(v, x) \
- (GPMI_IS_MX6(x) \
- ? (((v) << MX6Q_BP_BCH_FLASH0LAYOUT0_ECC0) \
- & MX6Q_BM_BCH_FLASH0LAYOUT0_ECC0) \
- : (((v) << BP_BCH_FLASH0LAYOUT0_ECC0) \
- & BM_BCH_FLASH0LAYOUT0_ECC0) \
- )
-
-#define MX6Q_BP_BCH_FLASH0LAYOUT0_GF_13_14 10
-#define MX6Q_BM_BCH_FLASH0LAYOUT0_GF_13_14 \
- (0x1 << MX6Q_BP_BCH_FLASH0LAYOUT0_GF_13_14)
-#define BF_BCH_FLASH0LAYOUT0_GF(v, x) \
- ((GPMI_IS_MX6(x) && ((v) == 14)) \
- ? (((1) << MX6Q_BP_BCH_FLASH0LAYOUT0_GF_13_14) \
- & MX6Q_BM_BCH_FLASH0LAYOUT0_GF_13_14) \
- : 0 \
- )
-
-#define BP_BCH_FLASH0LAYOUT0_DATA0_SIZE 0
-#define BM_BCH_FLASH0LAYOUT0_DATA0_SIZE \
- (0xfff << BP_BCH_FLASH0LAYOUT0_DATA0_SIZE)
-#define MX6Q_BM_BCH_FLASH0LAYOUT0_DATA0_SIZE \
- (0x3ff << BP_BCH_FLASH0LAYOUT0_DATA0_SIZE)
-#define BF_BCH_FLASH0LAYOUT0_DATA0_SIZE(v, x) \
- (GPMI_IS_MX6(x) \
- ? (((v) >> 2) & MX6Q_BM_BCH_FLASH0LAYOUT0_DATA0_SIZE) \
- : ((v) & BM_BCH_FLASH0LAYOUT0_DATA0_SIZE) \
- )
-
-#define HW_BCH_FLASH0LAYOUT1 0x00000090
-
-#define BP_BCH_FLASH0LAYOUT1_PAGE_SIZE 16
-#define BM_BCH_FLASH0LAYOUT1_PAGE_SIZE \
- (0xffff << BP_BCH_FLASH0LAYOUT1_PAGE_SIZE)
-#define BF_BCH_FLASH0LAYOUT1_PAGE_SIZE(v) \
- (((v) << BP_BCH_FLASH0LAYOUT1_PAGE_SIZE) \
- & BM_BCH_FLASH0LAYOUT1_PAGE_SIZE)
-
-#define BP_BCH_FLASH0LAYOUT1_ECCN 12
-#define BM_BCH_FLASH0LAYOUT1_ECCN (0xf << BP_BCH_FLASH0LAYOUT1_ECCN)
-#define MX6Q_BP_BCH_FLASH0LAYOUT1_ECCN 11
-#define MX6Q_BM_BCH_FLASH0LAYOUT1_ECCN (0x1f << MX6Q_BP_BCH_FLASH0LAYOUT1_ECCN)
-#define BF_BCH_FLASH0LAYOUT1_ECCN(v, x) \
- (GPMI_IS_MX6(x) \
- ? (((v) << MX6Q_BP_BCH_FLASH0LAYOUT1_ECCN) \
- & MX6Q_BM_BCH_FLASH0LAYOUT1_ECCN) \
- : (((v) << BP_BCH_FLASH0LAYOUT1_ECCN) \
- & BM_BCH_FLASH0LAYOUT1_ECCN) \
- )
-
-#define MX6Q_BP_BCH_FLASH0LAYOUT1_GF_13_14 10
-#define MX6Q_BM_BCH_FLASH0LAYOUT1_GF_13_14 \
- (0x1 << MX6Q_BP_BCH_FLASH0LAYOUT1_GF_13_14)
-#define BF_BCH_FLASH0LAYOUT1_GF(v, x) \
- ((GPMI_IS_MX6(x) && ((v) == 14)) \
- ? (((1) << MX6Q_BP_BCH_FLASH0LAYOUT1_GF_13_14) \
- & MX6Q_BM_BCH_FLASH0LAYOUT1_GF_13_14) \
- : 0 \
- )
-
-#define BP_BCH_FLASH0LAYOUT1_DATAN_SIZE 0
-#define BM_BCH_FLASH0LAYOUT1_DATAN_SIZE \
- (0xfff << BP_BCH_FLASH0LAYOUT1_DATAN_SIZE)
-#define MX6Q_BM_BCH_FLASH0LAYOUT1_DATAN_SIZE \
- (0x3ff << BP_BCH_FLASH0LAYOUT1_DATAN_SIZE)
-#define BF_BCH_FLASH0LAYOUT1_DATAN_SIZE(v, x) \
- (GPMI_IS_MX6(x) \
- ? (((v) >> 2) & MX6Q_BM_BCH_FLASH0LAYOUT1_DATAN_SIZE) \
- : ((v) & BM_BCH_FLASH0LAYOUT1_DATAN_SIZE) \
- )
-
-#define HW_BCH_VERSION 0x00000160
-#endif
diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-lib.c b/drivers/mtd/nand/gpmi-nand/gpmi-lib.c
deleted file mode 100644
index 97787246af41..000000000000
--- a/drivers/mtd/nand/gpmi-nand/gpmi-lib.c
+++ /dev/null
@@ -1,1510 +0,0 @@
-/*
- * Freescale GPMI NAND Flash Driver
- *
- * Copyright (C) 2008-2011 Freescale Semiconductor, Inc.
- * Copyright (C) 2008 Embedded Alley Solutions, Inc.
- *
- * 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.
- */
-#include <linux/delay.h>
-#include <linux/clk.h>
-#include <linux/slab.h>
-
-#include "gpmi-nand.h"
-#include "gpmi-regs.h"
-#include "bch-regs.h"
-
-static struct timing_threshold timing_default_threshold = {
- .max_data_setup_cycles = (BM_GPMI_TIMING0_DATA_SETUP >>
- BP_GPMI_TIMING0_DATA_SETUP),
- .internal_data_setup_in_ns = 0,
- .max_sample_delay_factor = (BM_GPMI_CTRL1_RDN_DELAY >>
- BP_GPMI_CTRL1_RDN_DELAY),
- .max_dll_clock_period_in_ns = 32,
- .max_dll_delay_in_ns = 16,
-};
-
-#define MXS_SET_ADDR 0x4
-#define MXS_CLR_ADDR 0x8
-/*
- * Clear the bit and poll it cleared. This is usually called with
- * a reset address and mask being either SFTRST(bit 31) or CLKGATE
- * (bit 30).
- */
-static int clear_poll_bit(void __iomem *addr, u32 mask)
-{
- int timeout = 0x400;
-
- /* clear the bit */
- writel(mask, addr + MXS_CLR_ADDR);
-
- /*
- * SFTRST needs 3 GPMI clocks to settle, the reference manual
- * recommends to wait 1us.
- */
- udelay(1);
-
- /* poll the bit becoming clear */
- while ((readl(addr) & mask) && --timeout)
- /* nothing */;
-
- return !timeout;
-}
-
-#define MODULE_CLKGATE (1 << 30)
-#define MODULE_SFTRST (1 << 31)
-/*
- * The current mxs_reset_block() will do two things:
- * [1] enable the module.
- * [2] reset the module.
- *
- * In most of the cases, it's ok.
- * But in MX23, there is a hardware bug in the BCH block (see erratum #2847).
- * If you try to soft reset the BCH block, it becomes unusable until
- * the next hard reset. This case occurs in the NAND boot mode. When the board
- * boots by NAND, the ROM of the chip will initialize the BCH blocks itself.
- * So If the driver tries to reset the BCH again, the BCH will not work anymore.
- * You will see a DMA timeout in this case. The bug has been fixed
- * in the following chips, such as MX28.
- *
- * To avoid this bug, just add a new parameter `just_enable` for
- * the mxs_reset_block(), and rewrite it here.
- */
-static int gpmi_reset_block(void __iomem *reset_addr, bool just_enable)
-{
- int ret;
- int timeout = 0x400;
-
- /* clear and poll SFTRST */
- ret = clear_poll_bit(reset_addr, MODULE_SFTRST);
- if (unlikely(ret))
- goto error;
-
- /* clear CLKGATE */
- writel(MODULE_CLKGATE, reset_addr + MXS_CLR_ADDR);
-
- if (!just_enable) {
- /* set SFTRST to reset the block */
- writel(MODULE_SFTRST, reset_addr + MXS_SET_ADDR);
- udelay(1);
-
- /* poll CLKGATE becoming set */
- while ((!(readl(reset_addr) & MODULE_CLKGATE)) && --timeout)
- /* nothing */;
- if (unlikely(!timeout))
- goto error;
- }
-
- /* clear and poll SFTRST */
- ret = clear_poll_bit(reset_addr, MODULE_SFTRST);
- if (unlikely(ret))
- goto error;
-
- /* clear and poll CLKGATE */
- ret = clear_poll_bit(reset_addr, MODULE_CLKGATE);
- if (unlikely(ret))
- goto error;
-
- return 0;
-
-error:
- pr_err("%s(%p): module reset timeout\n", __func__, reset_addr);
- return -ETIMEDOUT;
-}
-
-static int __gpmi_enable_clk(struct gpmi_nand_data *this, bool v)
-{
- struct clk *clk;
- int ret;
- int i;
-
- for (i = 0; i < GPMI_CLK_MAX; i++) {
- clk = this->resources.clock[i];
- if (!clk)
- break;
-
- if (v) {
- ret = clk_prepare_enable(clk);
- if (ret)
- goto err_clk;
- } else {
- clk_disable_unprepare(clk);
- }
- }
- return 0;
-
-err_clk:
- for (; i > 0; i--)
- clk_disable_unprepare(this->resources.clock[i - 1]);
- return ret;
-}
-
-#define gpmi_enable_clk(x) __gpmi_enable_clk(x, true)
-#define gpmi_disable_clk(x) __gpmi_enable_clk(x, false)
-
-int gpmi_init(struct gpmi_nand_data *this)
-{
- struct resources *r = &this->resources;
- int ret;
-
- ret = gpmi_enable_clk(this);
- if (ret)
- return ret;
- ret = gpmi_reset_block(r->gpmi_regs, false);
- if (ret)
- goto err_out;
-
- /*
- * Reset BCH here, too. We got failures otherwise :(
- * See later BCH reset for explanation of MX23 handling
- */
- ret = gpmi_reset_block(r->bch_regs, GPMI_IS_MX23(this));
- if (ret)
- goto err_out;
-
-
- /* Choose NAND mode. */
- writel(BM_GPMI_CTRL1_GPMI_MODE, r->gpmi_regs + HW_GPMI_CTRL1_CLR);
-
- /* Set the IRQ polarity. */
- writel(BM_GPMI_CTRL1_ATA_IRQRDY_POLARITY,
- r->gpmi_regs + HW_GPMI_CTRL1_SET);
-
- /* Disable Write-Protection. */
- writel(BM_GPMI_CTRL1_DEV_RESET, r->gpmi_regs + HW_GPMI_CTRL1_SET);
-
- /* Select BCH ECC. */
- writel(BM_GPMI_CTRL1_BCH_MODE, r->gpmi_regs + HW_GPMI_CTRL1_SET);
-
- /*
- * Decouple the chip select from dma channel. We use dma0 for all
- * the chips.
- */
- writel(BM_GPMI_CTRL1_DECOUPLE_CS, r->gpmi_regs + HW_GPMI_CTRL1_SET);
-
- gpmi_disable_clk(this);
- return 0;
-err_out:
- gpmi_disable_clk(this);
- return ret;
-}
-
-/* This function is very useful. It is called only when the bug occur. */
-void gpmi_dump_info(struct gpmi_nand_data *this)
-{
- struct resources *r = &this->resources;
- struct bch_geometry *geo = &this->bch_geometry;
- u32 reg;
- int i;
-
- dev_err(this->dev, "Show GPMI registers :\n");
- for (i = 0; i <= HW_GPMI_DEBUG / 0x10 + 1; i++) {
- reg = readl(r->gpmi_regs + i * 0x10);
- dev_err(this->dev, "offset 0x%.3x : 0x%.8x\n", i * 0x10, reg);
- }
-
- /* start to print out the BCH info */
- dev_err(this->dev, "Show BCH registers :\n");
- for (i = 0; i <= HW_BCH_VERSION / 0x10 + 1; i++) {
- reg = readl(r->bch_regs + i * 0x10);
- dev_err(this->dev, "offset 0x%.3x : 0x%.8x\n", i * 0x10, reg);
- }
- dev_err(this->dev, "BCH Geometry :\n"
- "GF length : %u\n"
- "ECC Strength : %u\n"
- "Page Size in Bytes : %u\n"
- "Metadata Size in Bytes : %u\n"
- "ECC Chunk Size in Bytes: %u\n"
- "ECC Chunk Count : %u\n"
- "Payload Size in Bytes : %u\n"
- "Auxiliary Size in Bytes: %u\n"
- "Auxiliary Status Offset: %u\n"
- "Block Mark Byte Offset : %u\n"
- "Block Mark Bit Offset : %u\n",
- geo->gf_len,
- geo->ecc_strength,
- geo->page_size,
- geo->metadata_size,
- geo->ecc_chunk_size,
- geo->ecc_chunk_count,
- geo->payload_size,
- geo->auxiliary_size,
- geo->auxiliary_status_offset,
- geo->block_mark_byte_offset,
- geo->block_mark_bit_offset);
-}
-
-/* Configures the geometry for BCH. */
-int bch_set_geometry(struct gpmi_nand_data *this)
-{
- struct resources *r = &this->resources;
- struct bch_geometry *bch_geo = &this->bch_geometry;
- unsigned int block_count;
- unsigned int block_size;
- unsigned int metadata_size;
- unsigned int ecc_strength;
- unsigned int page_size;
- unsigned int gf_len;
- int ret;
-
- if (common_nfc_set_geometry(this))
- return !0;
-
- block_count = bch_geo->ecc_chunk_count - 1;
- block_size = bch_geo->ecc_chunk_size;
- metadata_size = bch_geo->metadata_size;
- ecc_strength = bch_geo->ecc_strength >> 1;
- page_size = bch_geo->page_size;
- gf_len = bch_geo->gf_len;
-
- ret = gpmi_enable_clk(this);
- if (ret)
- return ret;
-
- /*
- * Due to erratum #2847 of the MX23, the BCH cannot be soft reset on this
- * chip, otherwise it will lock up. So we skip resetting BCH on the MX23.
- * On the other hand, the MX28 needs the reset, because one case has been
- * seen where the BCH produced ECC errors constantly after 10000
- * consecutive reboots. The latter case has not been seen on the MX23
- * yet, still we don't know if it could happen there as well.
- */
- ret = gpmi_reset_block(r->bch_regs, GPMI_IS_MX23(this));
- if (ret)
- goto err_out;
-
- /* Configure layout 0. */
- writel(BF_BCH_FLASH0LAYOUT0_NBLOCKS(block_count)
- | BF_BCH_FLASH0LAYOUT0_META_SIZE(metadata_size)
- | BF_BCH_FLASH0LAYOUT0_ECC0(ecc_strength, this)
- | BF_BCH_FLASH0LAYOUT0_GF(gf_len, this)
- | BF_BCH_FLASH0LAYOUT0_DATA0_SIZE(block_size, this),
- r->bch_regs + HW_BCH_FLASH0LAYOUT0);
-
- writel(BF_BCH_FLASH0LAYOUT1_PAGE_SIZE(page_size)
- | BF_BCH_FLASH0LAYOUT1_ECCN(ecc_strength, this)
- | BF_BCH_FLASH0LAYOUT1_GF(gf_len, this)
- | BF_BCH_FLASH0LAYOUT1_DATAN_SIZE(block_size, this),
- r->bch_regs + HW_BCH_FLASH0LAYOUT1);
-
- /* Set *all* chip selects to use layout 0. */
- writel(0, r->bch_regs + HW_BCH_LAYOUTSELECT);
-
- /* Enable interrupts. */
- writel(BM_BCH_CTRL_COMPLETE_IRQ_EN,
- r->bch_regs + HW_BCH_CTRL_SET);
-
- gpmi_disable_clk(this);
- return 0;
-err_out:
- gpmi_disable_clk(this);
- return ret;
-}
-
-/* Converts time in nanoseconds to cycles. */
-static unsigned int ns_to_cycles(unsigned int time,
- unsigned int period, unsigned int min)
-{
- unsigned int k;
-
- k = (time + period - 1) / period;
- return max(k, min);
-}
-
-#define DEF_MIN_PROP_DELAY 5
-#define DEF_MAX_PROP_DELAY 9
-/* Apply timing to current hardware conditions. */
-static int gpmi_nfc_compute_hardware_timing(struct gpmi_nand_data *this,
- struct gpmi_nfc_hardware_timing *hw)
-{
- struct timing_threshold *nfc = &timing_default_threshold;
- struct resources *r = &this->resources;
- struct nand_chip *nand = &this->nand;
- struct nand_timing target = this->timing;
- bool improved_timing_is_available;
- unsigned long clock_frequency_in_hz;
- unsigned int clock_period_in_ns;
- bool dll_use_half_periods;
- unsigned int dll_delay_shift;
- unsigned int max_sample_delay_in_ns;
- unsigned int address_setup_in_cycles;
- unsigned int data_setup_in_ns;
- unsigned int data_setup_in_cycles;
- unsigned int data_hold_in_cycles;
- int ideal_sample_delay_in_ns;
- unsigned int sample_delay_factor;
- int tEYE;
- unsigned int min_prop_delay_in_ns = DEF_MIN_PROP_DELAY;
- unsigned int max_prop_delay_in_ns = DEF_MAX_PROP_DELAY;
-
- /*
- * If there are multiple chips, we need to relax the timings to allow
- * for signal distortion due to higher capacitance.
- */
- if (nand->numchips > 2) {
- target.data_setup_in_ns += 10;
- target.data_hold_in_ns += 10;
- target.address_setup_in_ns += 10;
- } else if (nand->numchips > 1) {
- target.data_setup_in_ns += 5;
- target.data_hold_in_ns += 5;
- target.address_setup_in_ns += 5;
- }
-
- /* Check if improved timing information is available. */
- improved_timing_is_available =
- (target.tREA_in_ns >= 0) &&
- (target.tRLOH_in_ns >= 0) &&
- (target.tRHOH_in_ns >= 0);
-
- /* Inspect the clock. */
- nfc->clock_frequency_in_hz = clk_get_rate(r->clock[0]);
- clock_frequency_in_hz = nfc->clock_frequency_in_hz;
- clock_period_in_ns = NSEC_PER_SEC / clock_frequency_in_hz;
-
- /*
- * The NFC quantizes setup and hold parameters in terms of clock cycles.
- * Here, we quantize the setup and hold timing parameters to the
- * next-highest clock period to make sure we apply at least the
- * specified times.
- *
- * For data setup and data hold, the hardware interprets a value of zero
- * as the largest possible delay. This is not what's intended by a zero
- * in the input parameter, so we impose a minimum of one cycle.
- */
- data_setup_in_cycles = ns_to_cycles(target.data_setup_in_ns,
- clock_period_in_ns, 1);
- data_hold_in_cycles = ns_to_cycles(target.data_hold_in_ns,
- clock_period_in_ns, 1);
- address_setup_in_cycles = ns_to_cycles(target.address_setup_in_ns,
- clock_period_in_ns, 0);
-
- /*
- * The clock's period affects the sample delay in a number of ways:
- *
- * (1) The NFC HAL tells us the maximum clock period the sample delay
- * DLL can tolerate. If the clock period is greater than half that
- * maximum, we must configure the DLL to be driven by half periods.
- *
- * (2) We need to convert from an ideal sample delay, in ns, to a
- * "sample delay factor," which the NFC uses. This factor depends on
- * whether we're driving the DLL with full or half periods.
- * Paraphrasing the reference manual:
- *
- * AD = SDF x 0.125 x RP
- *
- * where:
- *
- * AD is the applied delay, in ns.
- * SDF is the sample delay factor, which is dimensionless.
- * RP is the reference period, in ns, which is a full clock period
- * if the DLL is being driven by full periods, or half that if
- * the DLL is being driven by half periods.
- *
- * Let's re-arrange this in a way that's more useful to us:
- *
- * 8
- * SDF = AD x ----
- * RP
- *
- * The reference period is either the clock period or half that, so this
- * is:
- *
- * 8 AD x DDF
- * SDF = AD x ----- = --------
- * f x P P
- *
- * where:
- *
- * f is 1 or 1/2, depending on how we're driving the DLL.
- * P is the clock period.
- * DDF is the DLL Delay Factor, a dimensionless value that
- * incorporates all the constants in the conversion.
- *
- * DDF will be either 8 or 16, both of which are powers of two. We can
- * reduce the cost of this conversion by using bit shifts instead of
- * multiplication or division. Thus:
- *
- * AD << DDS
- * SDF = ---------
- * P
- *
- * or
- *
- * AD = (SDF >> DDS) x P
- *
- * where:
- *
- * DDS is the DLL Delay Shift, the logarithm to base 2 of the DDF.
- */
- if (clock_period_in_ns > (nfc->max_dll_clock_period_in_ns >> 1)) {
- dll_use_half_periods = true;
- dll_delay_shift = 3 + 1;
- } else {
- dll_use_half_periods = false;
- dll_delay_shift = 3;
- }
-
- /*
- * Compute the maximum sample delay the NFC allows, under current
- * conditions. If the clock is running too slowly, no sample delay is
- * possible.
- */
- if (clock_period_in_ns > nfc->max_dll_clock_period_in_ns)
- max_sample_delay_in_ns = 0;
- else {
- /*
- * Compute the delay implied by the largest sample delay factor
- * the NFC allows.
- */
- max_sample_delay_in_ns =
- (nfc->max_sample_delay_factor * clock_period_in_ns) >>
- dll_delay_shift;
-
- /*
- * Check if the implied sample delay larger than the NFC
- * actually allows.
- */
- if (max_sample_delay_in_ns > nfc->max_dll_delay_in_ns)
- max_sample_delay_in_ns = nfc->max_dll_delay_in_ns;
- }
-
- /*
- * Check if improved timing information is available. If not, we have to
- * use a less-sophisticated algorithm.
- */
- if (!improved_timing_is_available) {
- /*
- * Fold the read setup time required by the NFC into the ideal
- * sample delay.
- */
- ideal_sample_delay_in_ns = target.gpmi_sample_delay_in_ns +
- nfc->internal_data_setup_in_ns;
-
- /*
- * The ideal sample delay may be greater than the maximum
- * allowed by the NFC. If so, we can trade off sample delay time
- * for more data setup time.
- *
- * In each iteration of the following loop, we add a cycle to
- * the data setup time and subtract a corresponding amount from
- * the sample delay until we've satisified the constraints or
- * can't do any better.
- */
- while ((ideal_sample_delay_in_ns > max_sample_delay_in_ns) &&
- (data_setup_in_cycles < nfc->max_data_setup_cycles)) {
-
- data_setup_in_cycles++;
- ideal_sample_delay_in_ns -= clock_period_in_ns;
-
- if (ideal_sample_delay_in_ns < 0)
- ideal_sample_delay_in_ns = 0;
-
- }
-
- /*
- * Compute the sample delay factor that corresponds most closely
- * to the ideal sample delay. If the result is too large for the
- * NFC, use the maximum value.
- *
- * Notice that we use the ns_to_cycles function to compute the
- * sample delay factor. We do this because the form of the
- * computation is the same as that for calculating cycles.
- */
- sample_delay_factor =
- ns_to_cycles(
- ideal_sample_delay_in_ns << dll_delay_shift,
- clock_period_in_ns, 0);
-
- if (sample_delay_factor > nfc->max_sample_delay_factor)
- sample_delay_factor = nfc->max_sample_delay_factor;
-
- /* Skip to the part where we return our results. */
- goto return_results;
- }
-
- /*
- * If control arrives here, we have more detailed timing information,
- * so we can use a better algorithm.
- */
-
- /*
- * Fold the read setup time required by the NFC into the maximum
- * propagation delay.
- */
- max_prop_delay_in_ns += nfc->internal_data_setup_in_ns;
-
- /*
- * Earlier, we computed the number of clock cycles required to satisfy
- * the data setup time. Now, we need to know the actual nanoseconds.
- */
- data_setup_in_ns = clock_period_in_ns * data_setup_in_cycles;
-
- /*
- * Compute tEYE, the width of the data eye when reading from the NAND
- * Flash. The eye width is fundamentally determined by the data setup
- * time, perturbed by propagation delays and some characteristics of the
- * NAND Flash device.
- *
- * start of the eye = max_prop_delay + tREA
- * end of the eye = min_prop_delay + tRHOH + data_setup
- */
- tEYE = (int)min_prop_delay_in_ns + (int)target.tRHOH_in_ns +
- (int)data_setup_in_ns;
-
- tEYE -= (int)max_prop_delay_in_ns + (int)target.tREA_in_ns;
-
- /*
- * The eye must be open. If it's not, we can try to open it by
- * increasing its main forcer, the data setup time.
- *
- * In each iteration of the following loop, we increase the data setup
- * time by a single clock cycle. We do this until either the eye is
- * open or we run into NFC limits.
- */
- while ((tEYE <= 0) &&
- (data_setup_in_cycles < nfc->max_data_setup_cycles)) {
- /* Give a cycle to data setup. */
- data_setup_in_cycles++;
- /* Synchronize the data setup time with the cycles. */
- data_setup_in_ns += clock_period_in_ns;
- /* Adjust tEYE accordingly. */
- tEYE += clock_period_in_ns;
- }
-
- /*
- * When control arrives here, the eye is open. The ideal time to sample
- * the data is in the center of the eye:
- *
- * end of the eye + start of the eye
- * --------------------------------- - data_setup
- * 2
- *
- * After some algebra, this simplifies to the code immediately below.
- */
- ideal_sample_delay_in_ns =
- ((int)max_prop_delay_in_ns +
- (int)target.tREA_in_ns +
- (int)min_prop_delay_in_ns +
- (int)target.tRHOH_in_ns -
- (int)data_setup_in_ns) >> 1;
-
- /*
- * The following figure illustrates some aspects of a NAND Flash read:
- *
- *
- * __ _____________________________________
- * RDN \_________________/
- *
- * <---- tEYE ----->
- * /-----------------\
- * Read Data ----------------------------< >---------
- * \-----------------/
- * ^ ^ ^ ^
- * | | | |
- * |<--Data Setup -->|<--Delay Time -->| |
- * | | | |
- * | | |
- * | |<-- Quantized Delay Time -->|
- * | | |
- *
- *
- * We have some issues we must now address:
- *
- * (1) The *ideal* sample delay time must not be negative. If it is, we
- * jam it to zero.
- *
- * (2) The *ideal* sample delay time must not be greater than that
- * allowed by the NFC. If it is, we can increase the data setup
- * time, which will reduce the delay between the end of the data
- * setup and the center of the eye. It will also make the eye
- * larger, which might help with the next issue...
- *
- * (3) The *quantized* sample delay time must not fall either before the
- * eye opens or after it closes (the latter is the problem
- * illustrated in the above figure).
- */
-
- /* Jam a negative ideal sample delay to zero. */
- if (ideal_sample_delay_in_ns < 0)
- ideal_sample_delay_in_ns = 0;
-
- /*
- * Extend the data setup as needed to reduce the ideal sample delay
- * below the maximum permitted by the NFC.
- */
- while ((ideal_sample_delay_in_ns > max_sample_delay_in_ns) &&
- (data_setup_in_cycles < nfc->max_data_setup_cycles)) {
-
- /* Give a cycle to data setup. */
- data_setup_in_cycles++;
- /* Synchronize the data setup time with the cycles. */
- data_setup_in_ns += clock_period_in_ns;
- /* Adjust tEYE accordingly. */
- tEYE += clock_period_in_ns;
-
- /*
- * Decrease the ideal sample delay by one half cycle, to keep it
- * in the middle of the eye.
- */
- ideal_sample_delay_in_ns -= (clock_period_in_ns >> 1);
-
- /* Jam a negative ideal sample delay to zero. */
- if (ideal_sample_delay_in_ns < 0)
- ideal_sample_delay_in_ns = 0;
- }
-
- /*
- * Compute the sample delay factor that corresponds to the ideal sample
- * delay. If the result is too large, then use the maximum allowed
- * value.
- *
- * Notice that we use the ns_to_cycles function to compute the sample
- * delay factor. We do this because the form of the computation is the
- * same as that for calculating cycles.
- */
- sample_delay_factor =
- ns_to_cycles(ideal_sample_delay_in_ns << dll_delay_shift,
- clock_period_in_ns, 0);
-
- if (sample_delay_factor > nfc->max_sample_delay_factor)
- sample_delay_factor = nfc->max_sample_delay_factor;
-
- /*
- * These macros conveniently encapsulate a computation we'll use to
- * continuously evaluate whether or not the data sample delay is inside
- * the eye.
- */
- #define IDEAL_DELAY ((int) ideal_sample_delay_in_ns)
-
- #define QUANTIZED_DELAY \
- ((int) ((sample_delay_factor * clock_period_in_ns) >> \
- dll_delay_shift))
-
- #define DELAY_ERROR (abs(QUANTIZED_DELAY - IDEAL_DELAY))
-
- #define SAMPLE_IS_NOT_WITHIN_THE_EYE (DELAY_ERROR > (tEYE >> 1))
-
- /*
- * While the quantized sample time falls outside the eye, reduce the
- * sample delay or extend the data setup to move the sampling point back
- * toward the eye. Do not allow the number of data setup cycles to
- * exceed the maximum allowed by the NFC.
- */
- while (SAMPLE_IS_NOT_WITHIN_THE_EYE &&
- (data_setup_in_cycles < nfc->max_data_setup_cycles)) {
- /*
- * If control arrives here, the quantized sample delay falls
- * outside the eye. Check if it's before the eye opens, or after
- * the eye closes.
- */
- if (QUANTIZED_DELAY > IDEAL_DELAY) {
- /*
- * If control arrives here, the quantized sample delay
- * falls after the eye closes. Decrease the quantized
- * delay time and then go back to re-evaluate.
- */
- if (sample_delay_factor != 0)
- sample_delay_factor--;
- continue;
- }
-
- /*
- * If control arrives here, the quantized sample delay falls
- * before the eye opens. Shift the sample point by increasing
- * data setup time. This will also make the eye larger.
- */
-
- /* Give a cycle to data setup. */
- data_setup_in_cycles++;
- /* Synchronize the data setup time with the cycles. */
- data_setup_in_ns += clock_period_in_ns;
- /* Adjust tEYE accordingly. */
- tEYE += clock_period_in_ns;
-
- /*
- * Decrease the ideal sample delay by one half cycle, to keep it
- * in the middle of the eye.
- */
- ideal_sample_delay_in_ns -= (clock_period_in_ns >> 1);
-
- /* ...and one less period for the delay time. */
- ideal_sample_delay_in_ns -= clock_period_in_ns;
-
- /* Jam a negative ideal sample delay to zero. */
- if (ideal_sample_delay_in_ns < 0)
- ideal_sample_delay_in_ns = 0;
-
- /*
- * We have a new ideal sample delay, so re-compute the quantized
- * delay.
- */
- sample_delay_factor =
- ns_to_cycles(
- ideal_sample_delay_in_ns << dll_delay_shift,
- clock_period_in_ns, 0);
-
- if (sample_delay_factor > nfc->max_sample_delay_factor)
- sample_delay_factor = nfc->max_sample_delay_factor;
- }
-
- /* Control arrives here when we're ready to return our results. */
-return_results:
- hw->data_setup_in_cycles = data_setup_in_cycles;
- hw->data_hold_in_cycles = data_hold_in_cycles;
- hw->address_setup_in_cycles = address_setup_in_cycles;
- hw->use_half_periods = dll_use_half_periods;
- hw->sample_delay_factor = sample_delay_factor;
- hw->device_busy_timeout = GPMI_DEFAULT_BUSY_TIMEOUT;
- hw->wrn_dly_sel = BV_GPMI_CTRL1_WRN_DLY_SEL_4_TO_8NS;
-
- /* Return success. */
- return 0;
-}
-
-/*
- * <1> Firstly, we should know what's the GPMI-clock means.
- * The GPMI-clock is the internal clock in the gpmi nand controller.
- * If you set 100MHz to gpmi nand controller, the GPMI-clock's period
- * is 10ns. Mark the GPMI-clock's period as GPMI-clock-period.
- *
- * <2> Secondly, we should know what's the frequency on the nand chip pins.
- * The frequency on the nand chip pins is derived from the GPMI-clock.
- * We can get it from the following equation:
- *
- * F = G / (DS + DH)
- *
- * F : the frequency on the nand chip pins.
- * G : the GPMI clock, such as 100MHz.
- * DS : GPMI_HW_GPMI_TIMING0:DATA_SETUP
- * DH : GPMI_HW_GPMI_TIMING0:DATA_HOLD
- *
- * <3> Thirdly, when the frequency on the nand chip pins is above 33MHz,
- * the nand EDO(extended Data Out) timing could be applied.
- * The GPMI implements a feedback read strobe to sample the read data.
- * The feedback read strobe can be delayed to support the nand EDO timing
- * where the read strobe may deasserts before the read data is valid, and
- * read data is valid for some time after read strobe.
- *
- * The following figure illustrates some aspects of a NAND Flash read:
- *
- * |<---tREA---->|
- * | |
- * | | |
- * |<--tRP-->| |
- * | | |
- * __ ___|__________________________________
- * RDN \________/ |
- * |
- * /---------\
- * Read Data --------------< >---------
- * \---------/
- * | |
- * |<-D->|
- * FeedbackRDN ________ ____________
- * \___________/
- *
- * D stands for delay, set in the HW_GPMI_CTRL1:RDN_DELAY.
- *
- *
- * <4> Now, we begin to describe how to compute the right RDN_DELAY.
- *
- * 4.1) From the aspect of the nand chip pins:
- * Delay = (tREA + C - tRP) {1}
- *
- * tREA : the maximum read access time. From the ONFI nand standards,
- * we know that tREA is 16ns in mode 5, tREA is 20ns is mode 4.
- * Please check it in : www.onfi.org
- * C : a constant for adjust the delay. default is 4.
- * tRP : the read pulse width.
- * Specified by the HW_GPMI_TIMING0:DATA_SETUP:
- * tRP = (GPMI-clock-period) * DATA_SETUP
- *
- * 4.2) From the aspect of the GPMI nand controller:
- * Delay = RDN_DELAY * 0.125 * RP {2}
- *
- * RP : the DLL reference period.
- * if (GPMI-clock-period > DLL_THRETHOLD)
- * RP = GPMI-clock-period / 2;
- * else
- * RP = GPMI-clock-period;
- *
- * Set the HW_GPMI_CTRL1:HALF_PERIOD if GPMI-clock-period
- * is greater DLL_THRETHOLD. In other SOCs, the DLL_THRETHOLD
- * is 16ns, but in mx6q, we use 12ns.
- *
- * 4.3) since {1} equals {2}, we get:
- *
- * (tREA + 4 - tRP) * 8
- * RDN_DELAY = --------------------- {3}
- * RP
- *
- * 4.4) We only support the fastest asynchronous mode of ONFI nand.
- * For some ONFI nand, the mode 4 is the fastest mode;
- * while for some ONFI nand, the mode 5 is the fastest mode.
- * So we only support the mode 4 and mode 5. It is no need to
- * support other modes.
- */
-static void gpmi_compute_edo_timing(struct gpmi_nand_data *this,
- struct gpmi_nfc_hardware_timing *hw)
-{
- struct resources *r = &this->resources;
- unsigned long rate = clk_get_rate(r->clock[0]);
- int mode = this->timing_mode;
- int dll_threshold = this->devdata->max_chain_delay;
- unsigned long delay;
- unsigned long clk_period;
- int t_rea;
- int c = 4;
- int t_rp;
- int rp;
-
- /*
- * [1] for GPMI_HW_GPMI_TIMING0:
- * The async mode requires 40MHz for mode 4, 50MHz for mode 5.
- * The GPMI can support 100MHz at most. So if we want to
- * get the 40MHz or 50MHz, we have to set DS=1, DH=1.
- * Set the ADDRESS_SETUP to 0 in mode 4.
- */
- hw->data_setup_in_cycles = 1;
- hw->data_hold_in_cycles = 1;
- hw->address_setup_in_cycles = ((mode == 5) ? 1 : 0);
-
- /* [2] for GPMI_HW_GPMI_TIMING1 */
- hw->device_busy_timeout = 0x9000;
-
- /* [3] for GPMI_HW_GPMI_CTRL1 */
- hw->wrn_dly_sel = BV_GPMI_CTRL1_WRN_DLY_SEL_NO_DELAY;
-
- /*
- * Enlarge 10 times for the numerator and denominator in {3}.
- * This make us to get more accurate result.
- */
- clk_period = NSEC_PER_SEC / (rate / 10);
- dll_threshold *= 10;
- t_rea = ((mode == 5) ? 16 : 20) * 10;
- c *= 10;
-
- t_rp = clk_period * 1; /* DATA_SETUP is 1 */
-
- if (clk_period > dll_threshold) {
- hw->use_half_periods = 1;
- rp = clk_period / 2;
- } else {
- hw->use_half_periods = 0;
- rp = clk_period;
- }
-
- /*
- * Multiply the numerator with 10, we could do a round off:
- * 7.8 round up to 8; 7.4 round down to 7.
- */
- delay = (((t_rea + c - t_rp) * 8) * 10) / rp;
- delay = (delay + 5) / 10;
-
- hw->sample_delay_factor = delay;
-}
-
-static int enable_edo_mode(struct gpmi_nand_data *this, int mode)
-{
- struct resources *r = &this->resources;
- struct nand_chip *nand = &this->nand;
- struct mtd_info *mtd = nand_to_mtd(nand);
- uint8_t *feature;
- unsigned long rate;
- int ret;
-
- feature = kzalloc(ONFI_SUBFEATURE_PARAM_LEN, GFP_KERNEL);
- if (!feature)
- return -ENOMEM;
-
- nand->select_chip(mtd, 0);
-
- /* [1] send SET FEATURE command to NAND */
- feature[0] = mode;
- ret = nand->onfi_set_features(mtd, nand,
- ONFI_FEATURE_ADDR_TIMING_MODE, feature);
- if (ret)
- goto err_out;
-
- /* [2] send GET FEATURE command to double-check the timing mode */
- memset(feature, 0, ONFI_SUBFEATURE_PARAM_LEN);
- ret = nand->onfi_get_features(mtd, nand,
- ONFI_FEATURE_ADDR_TIMING_MODE, feature);
- if (ret || feature[0] != mode)
- goto err_out;
-
- nand->select_chip(mtd, -1);
-
- /* [3] set the main IO clock, 100MHz for mode 5, 80MHz for mode 4. */
- rate = (mode == 5) ? 100000000 : 80000000;
- clk_set_rate(r->clock[0], rate);
-
- /* Let the gpmi_begin() re-compute the timing again. */
- this->flags &= ~GPMI_TIMING_INIT_OK;
-
- this->flags |= GPMI_ASYNC_EDO_ENABLED;
- this->timing_mode = mode;
- kfree(feature);
- dev_info(this->dev, "enable the asynchronous EDO mode %d\n", mode);
- return 0;
-
-err_out:
- nand->select_chip(mtd, -1);
- kfree(feature);
- dev_err(this->dev, "mode:%d ,failed in set feature.\n", mode);
- return -EINVAL;
-}
-
-int gpmi_extra_init(struct gpmi_nand_data *this)
-{
- struct nand_chip *chip = &this->nand;
-
- /* Enable the asynchronous EDO feature. */
- if (GPMI_IS_MX6(this) && chip->onfi_version) {
- int mode = onfi_get_async_timing_mode(chip);
-
- /* We only support the timing mode 4 and mode 5. */
- if (mode & ONFI_TIMING_MODE_5)
- mode = 5;
- else if (mode & ONFI_TIMING_MODE_4)
- mode = 4;
- else
- return 0;
-
- return enable_edo_mode(this, mode);
- }
- return 0;
-}
-
-/* Begin the I/O */
-void gpmi_begin(struct gpmi_nand_data *this)
-{
- struct resources *r = &this->resources;
- void __iomem *gpmi_regs = r->gpmi_regs;
- unsigned int clock_period_in_ns;
- uint32_t reg;
- unsigned int dll_wait_time_in_us;
- struct gpmi_nfc_hardware_timing hw;
- int ret;
-
- /* Enable the clock. */
- ret = gpmi_enable_clk(this);
- if (ret) {
- dev_err(this->dev, "We failed in enable the clk\n");
- goto err_out;
- }
-
- /* Only initialize the timing once */
- if (this->flags & GPMI_TIMING_INIT_OK)
- return;
- this->flags |= GPMI_TIMING_INIT_OK;
-
- if (this->flags & GPMI_ASYNC_EDO_ENABLED)
- gpmi_compute_edo_timing(this, &hw);
- else
- gpmi_nfc_compute_hardware_timing(this, &hw);
-
- /* [1] Set HW_GPMI_TIMING0 */
- reg = BF_GPMI_TIMING0_ADDRESS_SETUP(hw.address_setup_in_cycles) |
- BF_GPMI_TIMING0_DATA_HOLD(hw.data_hold_in_cycles) |
- BF_GPMI_TIMING0_DATA_SETUP(hw.data_setup_in_cycles);
-
- writel(reg, gpmi_regs + HW_GPMI_TIMING0);
-
- /* [2] Set HW_GPMI_TIMING1 */
- writel(BF_GPMI_TIMING1_BUSY_TIMEOUT(hw.device_busy_timeout),
- gpmi_regs + HW_GPMI_TIMING1);
-
- /* [3] The following code is to set the HW_GPMI_CTRL1. */
-
- /* Set the WRN_DLY_SEL */
- writel(BM_GPMI_CTRL1_WRN_DLY_SEL, gpmi_regs + HW_GPMI_CTRL1_CLR);
- writel(BF_GPMI_CTRL1_WRN_DLY_SEL(hw.wrn_dly_sel),
- gpmi_regs + HW_GPMI_CTRL1_SET);
-
- /* DLL_ENABLE must be set to 0 when setting RDN_DELAY or HALF_PERIOD. */
- writel(BM_GPMI_CTRL1_DLL_ENABLE, gpmi_regs + HW_GPMI_CTRL1_CLR);
-
- /* Clear out the DLL control fields. */
- reg = BM_GPMI_CTRL1_RDN_DELAY | BM_GPMI_CTRL1_HALF_PERIOD;
- writel(reg, gpmi_regs + HW_GPMI_CTRL1_CLR);
-
- /* If no sample delay is called for, return immediately. */
- if (!hw.sample_delay_factor)
- return;
-
- /* Set RDN_DELAY or HALF_PERIOD. */
- reg = ((hw.use_half_periods) ? BM_GPMI_CTRL1_HALF_PERIOD : 0)
- | BF_GPMI_CTRL1_RDN_DELAY(hw.sample_delay_factor);
-
- writel(reg, gpmi_regs + HW_GPMI_CTRL1_SET);
-
- /* At last, we enable the DLL. */
- writel(BM_GPMI_CTRL1_DLL_ENABLE, gpmi_regs + HW_GPMI_CTRL1_SET);
-
- /*
- * After we enable the GPMI DLL, we have to wait 64 clock cycles before
- * we can use the GPMI. Calculate the amount of time we need to wait,
- * in microseconds.
- */
- clock_period_in_ns = NSEC_PER_SEC / clk_get_rate(r->clock[0]);
- dll_wait_time_in_us = (clock_period_in_ns * 64) / 1000;
-
- if (!dll_wait_time_in_us)
- dll_wait_time_in_us = 1;
-
- /* Wait for the DLL to settle. */
- udelay(dll_wait_time_in_us);
-
-err_out:
- return;
-}
-
-void gpmi_end(struct gpmi_nand_data *this)
-{
- gpmi_disable_clk(this);
-}
-
-/* Clears a BCH interrupt. */
-void gpmi_clear_bch(struct gpmi_nand_data *this)
-{
- struct resources *r = &this->resources;
- writel(BM_BCH_CTRL_COMPLETE_IRQ, r->bch_regs + HW_BCH_CTRL_CLR);
-}
-
-/* Returns the Ready/Busy status of the given chip. */
-int gpmi_is_ready(struct gpmi_nand_data *this, unsigned chip)
-{
- struct resources *r = &this->resources;
- uint32_t mask = 0;
- uint32_t reg = 0;
-
- if (GPMI_IS_MX23(this)) {
- mask = MX23_BM_GPMI_DEBUG_READY0 << chip;
- reg = readl(r->gpmi_regs + HW_GPMI_DEBUG);
- } else if (GPMI_IS_MX28(this) || GPMI_IS_MX6(this)) {
- /*
- * In the imx6, all the ready/busy pins are bound
- * together. So we only need to check chip 0.
- */
- if (GPMI_IS_MX6(this))
- chip = 0;
-
- /* MX28 shares the same R/B register as MX6Q. */
- mask = MX28_BF_GPMI_STAT_READY_BUSY(1 << chip);
- reg = readl(r->gpmi_regs + HW_GPMI_STAT);
- } else
- dev_err(this->dev, "unknown arch.\n");
- return reg & mask;
-}
-
-static inline void set_dma_type(struct gpmi_nand_data *this,
- enum dma_ops_type type)
-{
- this->last_dma_type = this->dma_type;
- this->dma_type = type;
-}
-
-int gpmi_send_command(struct gpmi_nand_data *this)
-{
- struct dma_chan *channel = get_dma_chan(this);
- struct dma_async_tx_descriptor *desc;
- struct scatterlist *sgl;
- int chip = this->current_chip;
- u32 pio[3];
-
- /* [1] send out the PIO words */
- pio[0] = BF_GPMI_CTRL0_COMMAND_MODE(BV_GPMI_CTRL0_COMMAND_MODE__WRITE)
- | BM_GPMI_CTRL0_WORD_LENGTH
- | BF_GPMI_CTRL0_CS(chip, this)
- | BF_GPMI_CTRL0_LOCK_CS(LOCK_CS_ENABLE, this)
- | BF_GPMI_CTRL0_ADDRESS(BV_GPMI_CTRL0_ADDRESS__NAND_CLE)
- | BM_GPMI_CTRL0_ADDRESS_INCREMENT
- | BF_GPMI_CTRL0_XFER_COUNT(this->command_length);
- pio[1] = pio[2] = 0;
- desc = dmaengine_prep_slave_sg(channel,
- (struct scatterlist *)pio,
- ARRAY_SIZE(pio), DMA_TRANS_NONE, 0);
- if (!desc)
- return -EINVAL;
-
- /* [2] send out the COMMAND + ADDRESS string stored in @buffer */
- sgl = &this->cmd_sgl;
-
- sg_init_one(sgl, this->cmd_buffer, this->command_length);
- dma_map_sg(this->dev, sgl, 1, DMA_TO_DEVICE);
- desc = dmaengine_prep_slave_sg(channel,
- sgl, 1, DMA_MEM_TO_DEV,
- DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
- if (!desc)
- return -EINVAL;
-
- /* [3] submit the DMA */
- set_dma_type(this, DMA_FOR_COMMAND);
- return start_dma_without_bch_irq(this, desc);
-}
-
-int gpmi_send_data(struct gpmi_nand_data *this)
-{
- struct dma_async_tx_descriptor *desc;
- struct dma_chan *channel = get_dma_chan(this);
- int chip = this->current_chip;
- uint32_t command_mode;
- uint32_t address;
- u32 pio[2];
-
- /* [1] PIO */
- command_mode = BV_GPMI_CTRL0_COMMAND_MODE__WRITE;
- address = BV_GPMI_CTRL0_ADDRESS__NAND_DATA;
-
- pio[0] = BF_GPMI_CTRL0_COMMAND_MODE(command_mode)
- | BM_GPMI_CTRL0_WORD_LENGTH
- | BF_GPMI_CTRL0_CS(chip, this)
- | BF_GPMI_CTRL0_LOCK_CS(LOCK_CS_ENABLE, this)
- | BF_GPMI_CTRL0_ADDRESS(address)
- | BF_GPMI_CTRL0_XFER_COUNT(this->upper_len);
- pio[1] = 0;
- desc = dmaengine_prep_slave_sg(channel, (struct scatterlist *)pio,
- ARRAY_SIZE(pio), DMA_TRANS_NONE, 0);
- if (!desc)
- return -EINVAL;
-
- /* [2] send DMA request */
- prepare_data_dma(this, DMA_TO_DEVICE);
- desc = dmaengine_prep_slave_sg(channel, &this->data_sgl,
- 1, DMA_MEM_TO_DEV,
- DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
- if (!desc)
- return -EINVAL;
-
- /* [3] submit the DMA */
- set_dma_type(this, DMA_FOR_WRITE_DATA);
- return start_dma_without_bch_irq(this, desc);
-}
-
-int gpmi_read_data(struct gpmi_nand_data *this)
-{
- struct dma_async_tx_descriptor *desc;
- struct dma_chan *channel = get_dma_chan(this);
- int chip = this->current_chip;
- u32 pio[2];
-
- /* [1] : send PIO */
- pio[0] = BF_GPMI_CTRL0_COMMAND_MODE(BV_GPMI_CTRL0_COMMAND_MODE__READ)
- | BM_GPMI_CTRL0_WORD_LENGTH
- | BF_GPMI_CTRL0_CS(chip, this)
- | BF_GPMI_CTRL0_LOCK_CS(LOCK_CS_ENABLE, this)
- | BF_GPMI_CTRL0_ADDRESS(BV_GPMI_CTRL0_ADDRESS__NAND_DATA)
- | BF_GPMI_CTRL0_XFER_COUNT(this->upper_len);
- pio[1] = 0;
- desc = dmaengine_prep_slave_sg(channel,
- (struct scatterlist *)pio,
- ARRAY_SIZE(pio), DMA_TRANS_NONE, 0);
- if (!desc)
- return -EINVAL;
-
- /* [2] : send DMA request */
- prepare_data_dma(this, DMA_FROM_DEVICE);
- desc = dmaengine_prep_slave_sg(channel, &this->data_sgl,
- 1, DMA_DEV_TO_MEM,
- DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
- if (!desc)
- return -EINVAL;
-
- /* [3] : submit the DMA */
- set_dma_type(this, DMA_FOR_READ_DATA);
- return start_dma_without_bch_irq(this, desc);
-}
-
-int gpmi_send_page(struct gpmi_nand_data *this,
- dma_addr_t payload, dma_addr_t auxiliary)
-{
- struct bch_geometry *geo = &this->bch_geometry;
- uint32_t command_mode;
- uint32_t address;
- uint32_t ecc_command;
- uint32_t buffer_mask;
- struct dma_async_tx_descriptor *desc;
- struct dma_chan *channel = get_dma_chan(this);
- int chip = this->current_chip;
- u32 pio[6];
-
- /* A DMA descriptor that does an ECC page read. */
- command_mode = BV_GPMI_CTRL0_COMMAND_MODE__WRITE;
- address = BV_GPMI_CTRL0_ADDRESS__NAND_DATA;
- ecc_command = BV_GPMI_ECCCTRL_ECC_CMD__BCH_ENCODE;
- buffer_mask = BV_GPMI_ECCCTRL_BUFFER_MASK__BCH_PAGE |
- BV_GPMI_ECCCTRL_BUFFER_MASK__BCH_AUXONLY;
-
- pio[0] = BF_GPMI_CTRL0_COMMAND_MODE(command_mode)
- | BM_GPMI_CTRL0_WORD_LENGTH
- | BF_GPMI_CTRL0_CS(chip, this)
- | BF_GPMI_CTRL0_LOCK_CS(LOCK_CS_ENABLE, this)
- | BF_GPMI_CTRL0_ADDRESS(address)
- | BF_GPMI_CTRL0_XFER_COUNT(0);
- pio[1] = 0;
- pio[2] = BM_GPMI_ECCCTRL_ENABLE_ECC
- | BF_GPMI_ECCCTRL_ECC_CMD(ecc_command)
- | BF_GPMI_ECCCTRL_BUFFER_MASK(buffer_mask);
- pio[3] = geo->page_size;
- pio[4] = payload;
- pio[5] = auxiliary;
-
- desc = dmaengine_prep_slave_sg(channel,
- (struct scatterlist *)pio,
- ARRAY_SIZE(pio), DMA_TRANS_NONE,
- DMA_CTRL_ACK);
- if (!desc)
- return -EINVAL;
-
- set_dma_type(this, DMA_FOR_WRITE_ECC_PAGE);
- return start_dma_with_bch_irq(this, desc);
-}
-
-int gpmi_read_page(struct gpmi_nand_data *this,
- dma_addr_t payload, dma_addr_t auxiliary)
-{
- struct bch_geometry *geo = &this->bch_geometry;
- uint32_t command_mode;
- uint32_t address;
- uint32_t ecc_command;
- uint32_t buffer_mask;
- struct dma_async_tx_descriptor *desc;
- struct dma_chan *channel = get_dma_chan(this);
- int chip = this->current_chip;
- u32 pio[6];
-
- /* [1] Wait for the chip to report ready. */
- command_mode = BV_GPMI_CTRL0_COMMAND_MODE__WAIT_FOR_READY;
- address = BV_GPMI_CTRL0_ADDRESS__NAND_DATA;
-
- pio[0] = BF_GPMI_CTRL0_COMMAND_MODE(command_mode)
- | BM_GPMI_CTRL0_WORD_LENGTH
- | BF_GPMI_CTRL0_CS(chip, this)
- | BF_GPMI_CTRL0_LOCK_CS(LOCK_CS_ENABLE, this)
- | BF_GPMI_CTRL0_ADDRESS(address)
- | BF_GPMI_CTRL0_XFER_COUNT(0);
- pio[1] = 0;
- desc = dmaengine_prep_slave_sg(channel,
- (struct scatterlist *)pio, 2,
- DMA_TRANS_NONE, 0);
- if (!desc)
- return -EINVAL;
-
- /* [2] Enable the BCH block and read. */
- command_mode = BV_GPMI_CTRL0_COMMAND_MODE__READ;
- address = BV_GPMI_CTRL0_ADDRESS__NAND_DATA;
- ecc_command = BV_GPMI_ECCCTRL_ECC_CMD__BCH_DECODE;
- buffer_mask = BV_GPMI_ECCCTRL_BUFFER_MASK__BCH_PAGE
- | BV_GPMI_ECCCTRL_BUFFER_MASK__BCH_AUXONLY;
-
- pio[0] = BF_GPMI_CTRL0_COMMAND_MODE(command_mode)
- | BM_GPMI_CTRL0_WORD_LENGTH
- | BF_GPMI_CTRL0_CS(chip, this)
- | BF_GPMI_CTRL0_LOCK_CS(LOCK_CS_ENABLE, this)
- | BF_GPMI_CTRL0_ADDRESS(address)
- | BF_GPMI_CTRL0_XFER_COUNT(geo->page_size);
-
- pio[1] = 0;
- pio[2] = BM_GPMI_ECCCTRL_ENABLE_ECC
- | BF_GPMI_ECCCTRL_ECC_CMD(ecc_command)
- | BF_GPMI_ECCCTRL_BUFFER_MASK(buffer_mask);
- pio[3] = geo->page_size;
- pio[4] = payload;
- pio[5] = auxiliary;
- desc = dmaengine_prep_slave_sg(channel,
- (struct scatterlist *)pio,
- ARRAY_SIZE(pio), DMA_TRANS_NONE,
- DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
- if (!desc)
- return -EINVAL;
-
- /* [3] Disable the BCH block */
- command_mode = BV_GPMI_CTRL0_COMMAND_MODE__WAIT_FOR_READY;
- address = BV_GPMI_CTRL0_ADDRESS__NAND_DATA;
-
- pio[0] = BF_GPMI_CTRL0_COMMAND_MODE(command_mode)
- | BM_GPMI_CTRL0_WORD_LENGTH
- | BF_GPMI_CTRL0_CS(chip, this)
- | BF_GPMI_CTRL0_LOCK_CS(LOCK_CS_ENABLE, this)
- | BF_GPMI_CTRL0_ADDRESS(address)
- | BF_GPMI_CTRL0_XFER_COUNT(geo->page_size);
- pio[1] = 0;
- pio[2] = 0; /* clear GPMI_HW_GPMI_ECCCTRL, disable the BCH. */
- desc = dmaengine_prep_slave_sg(channel,
- (struct scatterlist *)pio, 3,
- DMA_TRANS_NONE,
- DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
- if (!desc)
- return -EINVAL;
-
- /* [4] submit the DMA */
- set_dma_type(this, DMA_FOR_READ_ECC_PAGE);
- return start_dma_with_bch_irq(this, desc);
-}
-
-/**
- * gpmi_copy_bits - copy bits from one memory region to another
- * @dst: destination buffer
- * @dst_bit_off: bit offset we're starting to write at
- * @src: source buffer
- * @src_bit_off: bit offset we're starting to read from
- * @nbits: number of bits to copy
- *
- * This functions copies bits from one memory region to another, and is used by
- * the GPMI driver to copy ECC sections which are not guaranteed to be byte
- * aligned.
- *
- * src and dst should not overlap.
- *
- */
-void gpmi_copy_bits(u8 *dst, size_t dst_bit_off,
- const u8 *src, size_t src_bit_off,
- size_t nbits)
-{
- size_t i;
- size_t nbytes;
- u32 src_buffer = 0;
- size_t bits_in_src_buffer = 0;
-
- if (!nbits)
- return;
-
- /*
- * Move src and dst pointers to the closest byte pointer and store bit
- * offsets within a byte.
- */
- src += src_bit_off / 8;
- src_bit_off %= 8;
-
- dst += dst_bit_off / 8;
- dst_bit_off %= 8;
-
- /*
- * Initialize the src_buffer value with bits available in the first
- * byte of data so that we end up with a byte aligned src pointer.
- */
- if (src_bit_off) {
- src_buffer = src[0] >> src_bit_off;
- if (nbits >= (8 - src_bit_off)) {
- bits_in_src_buffer += 8 - src_bit_off;
- } else {
- src_buffer &= GENMASK(nbits - 1, 0);
- bits_in_src_buffer += nbits;
- }
- nbits -= bits_in_src_buffer;
- src++;
- }
-
- /* Calculate the number of bytes that can be copied from src to dst. */
- nbytes = nbits / 8;
-
- /* Try to align dst to a byte boundary. */
- if (dst_bit_off) {
- if (bits_in_src_buffer < (8 - dst_bit_off) && nbytes) {
- src_buffer |= src[0] << bits_in_src_buffer;
- bits_in_src_buffer += 8;
- src++;
- nbytes--;
- }
-
- if (bits_in_src_buffer >= (8 - dst_bit_off)) {
- dst[0] &= GENMASK(dst_bit_off - 1, 0);
- dst[0] |= src_buffer << dst_bit_off;
- src_buffer >>= (8 - dst_bit_off);
- bits_in_src_buffer -= (8 - dst_bit_off);
- dst_bit_off = 0;
- dst++;
- if (bits_in_src_buffer > 7) {
- bits_in_src_buffer -= 8;
- dst[0] = src_buffer;
- dst++;
- src_buffer >>= 8;
- }
- }
- }
-
- if (!bits_in_src_buffer && !dst_bit_off) {
- /*
- * Both src and dst pointers are byte aligned, thus we can
- * just use the optimized memcpy function.
- */
- if (nbytes)
- memcpy(dst, src, nbytes);
- } else {
- /*
- * src buffer is not byte aligned, hence we have to copy each
- * src byte to the src_buffer variable before extracting a byte
- * to store in dst.
- */
- for (i = 0; i < nbytes; i++) {
- src_buffer |= src[i] << bits_in_src_buffer;
- dst[i] = src_buffer;
- src_buffer >>= 8;
- }
- }
- /* Update dst and src pointers */
- dst += nbytes;
- src += nbytes;
-
- /*
- * nbits is the number of remaining bits. It should not exceed 8 as
- * we've already copied as much bytes as possible.
- */
- nbits %= 8;
-
- /*
- * If there's no more bits to copy to the destination and src buffer
- * was already byte aligned, then we're done.
- */
- if (!nbits && !bits_in_src_buffer)
- return;
-
- /* Copy the remaining bits to src_buffer */
- if (nbits)
- src_buffer |= (*src & GENMASK(nbits - 1, 0)) <<
- bits_in_src_buffer;
- bits_in_src_buffer += nbits;
-
- /*
- * In case there were not enough bits to get a byte aligned dst buffer
- * prepare the src_buffer variable to match the dst organization (shift
- * src_buffer by dst_bit_off and retrieve the least significant bits
- * from dst).
- */
- if (dst_bit_off)
- src_buffer = (src_buffer << dst_bit_off) |
- (*dst & GENMASK(dst_bit_off - 1, 0));
- bits_in_src_buffer += dst_bit_off;
-
- /*
- * Keep most significant bits from dst if we end up with an unaligned
- * number of bits.
- */
- nbytes = bits_in_src_buffer / 8;
- if (bits_in_src_buffer % 8) {
- src_buffer |= (dst[nbytes] &
- GENMASK(7, bits_in_src_buffer % 8)) <<
- (nbytes * 8);
- nbytes++;
- }
-
- /* Copy the remaining bytes to dst */
- for (i = 0; i < nbytes; i++) {
- dst[i] = src_buffer;
- src_buffer >>= 8;
- }
-}
diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c
deleted file mode 100644
index 61fdd733492f..000000000000
--- a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c
+++ /dev/null
@@ -1,2182 +0,0 @@
-/*
- * Freescale GPMI NAND Flash Driver
- *
- * Copyright (C) 2010-2015 Freescale Semiconductor, Inc.
- * Copyright (C) 2008 Embedded Alley Solutions, Inc.
- *
- * 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.
- */
-#include <linux/clk.h>
-#include <linux/slab.h>
-#include <linux/sched/task_stack.h>
-#include <linux/interrupt.h>
-#include <linux/module.h>
-#include <linux/mtd/partitions.h>
-#include <linux/of.h>
-#include <linux/of_device.h>
-#include "gpmi-nand.h"
-#include "bch-regs.h"
-
-/* Resource names for the GPMI NAND driver. */
-#define GPMI_NAND_GPMI_REGS_ADDR_RES_NAME "gpmi-nand"
-#define GPMI_NAND_BCH_REGS_ADDR_RES_NAME "bch"
-#define GPMI_NAND_BCH_INTERRUPT_RES_NAME "bch"
-
-/* add our owner bbt descriptor */
-static uint8_t scan_ff_pattern[] = { 0xff };
-static struct nand_bbt_descr gpmi_bbt_descr = {
- .options = 0,
- .offs = 0,
- .len = 1,
- .pattern = scan_ff_pattern
-};
-
-/*
- * We may change the layout if we can get the ECC info from the datasheet,
- * else we will use all the (page + OOB).
- */
-static int gpmi_ooblayout_ecc(struct mtd_info *mtd, int section,
- struct mtd_oob_region *oobregion)
-{
- struct nand_chip *chip = mtd_to_nand(mtd);
- struct gpmi_nand_data *this = nand_get_controller_data(chip);
- struct bch_geometry *geo = &this->bch_geometry;
-
- if (section)
- return -ERANGE;
-
- oobregion->offset = 0;
- oobregion->length = geo->page_size - mtd->writesize;
-
- return 0;
-}
-
-static int gpmi_ooblayout_free(struct mtd_info *mtd, int section,
- struct mtd_oob_region *oobregion)
-{
- struct nand_chip *chip = mtd_to_nand(mtd);
- struct gpmi_nand_data *this = nand_get_controller_data(chip);
- struct bch_geometry *geo = &this->bch_geometry;
-
- if (section)
- return -ERANGE;
-
- /* The available oob size we have. */
- if (geo->page_size < mtd->writesize + mtd->oobsize) {
- oobregion->offset = geo->page_size - mtd->writesize;
- oobregion->length = mtd->oobsize - oobregion->offset;
- }
-
- return 0;
-}
-
-static const char * const gpmi_clks_for_mx2x[] = {
- "gpmi_io",
-};
-
-static const struct mtd_ooblayout_ops gpmi_ooblayout_ops = {
- .ecc = gpmi_ooblayout_ecc,
- .free = gpmi_ooblayout_free,
-};
-
-static const struct gpmi_devdata gpmi_devdata_imx23 = {
- .type = IS_MX23,
- .bch_max_ecc_strength = 20,
- .max_chain_delay = 16,
- .clks = gpmi_clks_for_mx2x,
- .clks_count = ARRAY_SIZE(gpmi_clks_for_mx2x),
-};
-
-static const struct gpmi_devdata gpmi_devdata_imx28 = {
- .type = IS_MX28,
- .bch_max_ecc_strength = 20,
- .max_chain_delay = 16,
- .clks = gpmi_clks_for_mx2x,
- .clks_count = ARRAY_SIZE(gpmi_clks_for_mx2x),
-};
-
-static const char * const gpmi_clks_for_mx6[] = {
- "gpmi_io", "gpmi_apb", "gpmi_bch", "gpmi_bch_apb", "per1_bch",
-};
-
-static const struct gpmi_devdata gpmi_devdata_imx6q = {
- .type = IS_MX6Q,
- .bch_max_ecc_strength = 40,
- .max_chain_delay = 12,
- .clks = gpmi_clks_for_mx6,
- .clks_count = ARRAY_SIZE(gpmi_clks_for_mx6),
-};
-
-static const struct gpmi_devdata gpmi_devdata_imx6sx = {
- .type = IS_MX6SX,
- .bch_max_ecc_strength = 62,
- .max_chain_delay = 12,
- .clks = gpmi_clks_for_mx6,
- .clks_count = ARRAY_SIZE(gpmi_clks_for_mx6),
-};
-
-static const char * const gpmi_clks_for_mx7d[] = {
- "gpmi_io", "gpmi_bch_apb",
-};
-
-static const struct gpmi_devdata gpmi_devdata_imx7d = {
- .type = IS_MX7D,
- .bch_max_ecc_strength = 62,
- .max_chain_delay = 12,
- .clks = gpmi_clks_for_mx7d,
- .clks_count = ARRAY_SIZE(gpmi_clks_for_mx7d),
-};
-
-static irqreturn_t bch_irq(int irq, void *cookie)
-{
- struct gpmi_nand_data *this = cookie;
-
- gpmi_clear_bch(this);
- complete(&this->bch_done);
- return IRQ_HANDLED;
-}
-
-/*
- * Calculate the ECC strength by hand:
- * E : The ECC strength.
- * G : the length of Galois Field.
- * N : The chunk count of per page.
- * O : the oobsize of the NAND chip.
- * M : the metasize of per page.
- *
- * The formula is :
- * E * G * N
- * ------------ <= (O - M)
- * 8
- *
- * So, we get E by:
- * (O - M) * 8
- * E <= -------------
- * G * N
- */
-static inline int get_ecc_strength(struct gpmi_nand_data *this)
-{
- struct bch_geometry *geo = &this->bch_geometry;
- struct mtd_info *mtd = nand_to_mtd(&this->nand);
- int ecc_strength;
-
- ecc_strength = ((mtd->oobsize - geo->metadata_size) * 8)
- / (geo->gf_len * geo->ecc_chunk_count);
-
- /* We need the minor even number. */
- return round_down(ecc_strength, 2);
-}
-
-static inline bool gpmi_check_ecc(struct gpmi_nand_data *this)
-{
- struct bch_geometry *geo = &this->bch_geometry;
-
- /* Do the sanity check. */
- if (GPMI_IS_MX23(this) || GPMI_IS_MX28(this)) {
- /* The mx23/mx28 only support the GF13. */
- if (geo->gf_len == 14)
- return false;
- }
- return geo->ecc_strength <= this->devdata->bch_max_ecc_strength;
-}
-
-/*
- * If we can get the ECC information from the nand chip, we do not
- * need to calculate them ourselves.
- *
- * We may have available oob space in this case.
- */
-static int set_geometry_by_ecc_info(struct gpmi_nand_data *this)
-{
- struct bch_geometry *geo = &this->bch_geometry;
- struct nand_chip *chip = &this->nand;
- struct mtd_info *mtd = nand_to_mtd(chip);
- unsigned int block_mark_bit_offset;
-
- if (!(chip->ecc_strength_ds > 0 && chip->ecc_step_ds > 0))
- return -EINVAL;
-
- switch (chip->ecc_step_ds) {
- case SZ_512:
- geo->gf_len = 13;
- break;
- case SZ_1K:
- geo->gf_len = 14;
- break;
- default:
- dev_err(this->dev,
- "unsupported nand chip. ecc bits : %d, ecc size : %d\n",
- chip->ecc_strength_ds, chip->ecc_step_ds);
- return -EINVAL;
- }
- geo->ecc_chunk_size = chip->ecc_step_ds;
- geo->ecc_strength = round_up(chip->ecc_strength_ds, 2);
- if (!gpmi_check_ecc(this))
- return -EINVAL;
-
- /* Keep the C >= O */
- if (geo->ecc_chunk_size < mtd->oobsize) {
- dev_err(this->dev,
- "unsupported nand chip. ecc size: %d, oob size : %d\n",
- chip->ecc_step_ds, mtd->oobsize);
- return -EINVAL;
- }
-
- /* The default value, see comment in the legacy_set_geometry(). */
- geo->metadata_size = 10;
-
- geo->ecc_chunk_count = mtd->writesize / geo->ecc_chunk_size;
-
- /*
- * Now, the NAND chip with 2K page(data chunk is 512byte) shows below:
- *
- * | P |
- * |<----------------------------------------------------->|
- * | |
- * | (Block Mark) |
- * | P' | | | |
- * |<-------------------------------------------->| D | | O' |
- * | |<---->| |<--->|
- * V V V V V
- * +---+----------+-+----------+-+----------+-+----------+-+-----+
- * | M | data |E| data |E| data |E| data |E| |
- * +---+----------+-+----------+-+----------+-+----------+-+-----+
- * ^ ^
- * | O |
- * |<------------>|
- * | |
- *
- * P : the page size for BCH module.
- * E : The ECC strength.
- * G : the length of Galois Field.
- * N : The chunk count of per page.
- * M : the metasize of per page.
- * C : the ecc chunk size, aka the "data" above.
- * P': the nand chip's page size.
- * O : the nand chip's oob size.
- * O': the free oob.
- *
- * The formula for P is :
- *
- * E * G * N
- * P = ------------ + P' + M
- * 8
- *
- * The position of block mark moves forward in the ECC-based view
- * of page, and the delta is:
- *
- * E * G * (N - 1)
- * D = (---------------- + M)
- * 8
- *
- * Please see the comment in legacy_set_geometry().
- * With the condition C >= O , we still can get same result.
- * So the bit position of the physical block mark within the ECC-based
- * view of the page is :
- * (P' - D) * 8
- */
- geo->page_size = mtd->writesize + geo->metadata_size +
- (geo->gf_len * geo->ecc_strength * geo->ecc_chunk_count) / 8;
-
- geo->payload_size = mtd->writesize;
-
- geo->auxiliary_status_offset = ALIGN(geo->metadata_size, 4);
- geo->auxiliary_size = ALIGN(geo->metadata_size, 4)
- + ALIGN(geo->ecc_chunk_count, 4);
-
- if (!this->swap_block_mark)
- return 0;
-
- /* For bit swap. */
- block_mark_bit_offset = mtd->writesize * 8 -
- (geo->ecc_strength * geo->gf_len * (geo->ecc_chunk_count - 1)
- + geo->metadata_size * 8);
-
- geo->block_mark_byte_offset = block_mark_bit_offset / 8;
- geo->block_mark_bit_offset = block_mark_bit_offset % 8;
- return 0;
-}
-
-static int legacy_set_geometry(struct gpmi_nand_data *this)
-{
- struct bch_geometry *geo = &this->bch_geometry;
- struct mtd_info *mtd = nand_to_mtd(&this->nand);
- unsigned int metadata_size;
- unsigned int status_size;
- unsigned int block_mark_bit_offset;
-
- /*
- * The size of the metadata can be changed, though we set it to 10
- * bytes now. But it can't be too large, because we have to save
- * enough space for BCH.
- */
- geo->metadata_size = 10;
-
- /* The default for the length of Galois Field. */
- geo->gf_len = 13;
-
- /* The default for chunk size. */
- geo->ecc_chunk_size = 512;
- while (geo->ecc_chunk_size < mtd->oobsize) {
- geo->ecc_chunk_size *= 2; /* keep C >= O */
- geo->gf_len = 14;
- }
-
- geo->ecc_chunk_count = mtd->writesize / geo->ecc_chunk_size;
-
- /* We use the same ECC strength for all chunks. */
- geo->ecc_strength = get_ecc_strength(this);
- if (!gpmi_check_ecc(this)) {
- dev_err(this->dev,
- "ecc strength: %d cannot be supported by the controller (%d)\n"
- "try to use minimum ecc strength that NAND chip required\n",
- geo->ecc_strength,
- this->devdata->bch_max_ecc_strength);
- return -EINVAL;
- }
-
- geo->page_size = mtd->writesize + geo->metadata_size +
- (geo->gf_len * geo->ecc_strength * geo->ecc_chunk_count) / 8;
- geo->payload_size = mtd->writesize;
-
- /*
- * The auxiliary buffer contains the metadata and the ECC status. The
- * metadata is padded to the nearest 32-bit boundary. The ECC status
- * contains one byte for every ECC chunk, and is also padded to the
- * nearest 32-bit boundary.
- */
- metadata_size = ALIGN(geo->metadata_size, 4);
- status_size = ALIGN(geo->ecc_chunk_count, 4);
-
- geo->auxiliary_size = metadata_size + status_size;
- geo->auxiliary_status_offset = metadata_size;
-
- if (!this->swap_block_mark)
- return 0;
-
- /*
- * We need to compute the byte and bit offsets of
- * the physical block mark within the ECC-based view of the page.
- *
- * NAND chip with 2K page shows below:
- * (Block Mark)
- * | |
- * | D |
- * |<---->|
- * V V
- * +---+----------+-+----------+-+----------+-+----------+-+
- * | M | data |E| data |E| data |E| data |E|
- * +---+----------+-+----------+-+----------+-+----------+-+
- *
- * The position of block mark moves forward in the ECC-based view
- * of page, and the delta is:
- *
- * E * G * (N - 1)
- * D = (---------------- + M)
- * 8
- *
- * With the formula to compute the ECC strength, and the condition
- * : C >= O (C is the ecc chunk size)
- *
- * It's easy to deduce to the following result:
- *
- * E * G (O - M) C - M C - M
- * ----------- <= ------- <= -------- < ---------
- * 8 N N (N - 1)
- *
- * So, we get:
- *
- * E * G * (N - 1)
- * D = (---------------- + M) < C
- * 8
- *
- * The above inequality means the position of block mark
- * within the ECC-based view of the page is still in the data chunk,
- * and it's NOT in the ECC bits of the chunk.
- *
- * Use the following to compute the bit position of the
- * physical block mark within the ECC-based view of the page:
- * (page_size - D) * 8
- *
- * --Huang Shijie
- */
- block_mark_bit_offset = mtd->writesize * 8 -
- (geo->ecc_strength * geo->gf_len * (geo->ecc_chunk_count - 1)
- + geo->metadata_size * 8);
-
- geo->block_mark_byte_offset = block_mark_bit_offset / 8;
- geo->block_mark_bit_offset = block_mark_bit_offset % 8;
- return 0;
-}
-
-int common_nfc_set_geometry(struct gpmi_nand_data *this)
-{
- if ((of_property_read_bool(this->dev->of_node, "fsl,use-minimum-ecc"))
- || legacy_set_geometry(this))
- return set_geometry_by_ecc_info(this);
-
- return 0;
-}
-
-struct dma_chan *get_dma_chan(struct gpmi_nand_data *this)
-{
- /* We use the DMA channel 0 to access all the nand chips. */
- return this->dma_chans[0];
-}
-
-/* Can we use the upper's buffer directly for DMA? */
-void prepare_data_dma(struct gpmi_nand_data *this, enum dma_data_direction dr)
-{
- struct scatterlist *sgl = &this->data_sgl;
- int ret;
-
- /* first try to map the upper buffer directly */
- if (virt_addr_valid(this->upper_buf) &&
- !object_is_on_stack(this->upper_buf)) {
- sg_init_one(sgl, this->upper_buf, this->upper_len);
- ret = dma_map_sg(this->dev, sgl, 1, dr);
- if (ret == 0)
- goto map_fail;
-
- this->direct_dma_map_ok = true;
- return;
- }
-
-map_fail:
- /* We have to use our own DMA buffer. */
- sg_init_one(sgl, this->data_buffer_dma, this->upper_len);
-
- if (dr == DMA_TO_DEVICE)
- memcpy(this->data_buffer_dma, this->upper_buf, this->upper_len);
-
- dma_map_sg(this->dev, sgl, 1, dr);
-
- this->direct_dma_map_ok = false;
-}
-
-/* This will be called after the DMA operation is finished. */
-static void dma_irq_callback(void *param)
-{
- struct gpmi_nand_data *this = param;
- struct completion *dma_c = &this->dma_done;
-
- switch (this->dma_type) {
- case DMA_FOR_COMMAND:
- dma_unmap_sg(this->dev, &this->cmd_sgl, 1, DMA_TO_DEVICE);
- break;
-
- case DMA_FOR_READ_DATA:
- dma_unmap_sg(this->dev, &this->data_sgl, 1, DMA_FROM_DEVICE);
- if (this->direct_dma_map_ok == false)
- memcpy(this->upper_buf, this->data_buffer_dma,
- this->upper_len);
- break;
-
- case DMA_FOR_WRITE_DATA:
- dma_unmap_sg(this->dev, &this->data_sgl, 1, DMA_TO_DEVICE);
- break;
-
- case DMA_FOR_READ_ECC_PAGE:
- case DMA_FOR_WRITE_ECC_PAGE:
- /* We have to wait the BCH interrupt to finish. */
- break;
-
- default:
- dev_err(this->dev, "in wrong DMA operation.\n");
- }
-
- complete(dma_c);
-}
-
-int start_dma_without_bch_irq(struct gpmi_nand_data *this,
- struct dma_async_tx_descriptor *desc)
-{
- struct completion *dma_c = &this->dma_done;
- unsigned long timeout;
-
- init_completion(dma_c);
-
- desc->callback = dma_irq_callback;
- desc->callback_param = this;
- dmaengine_submit(desc);
- dma_async_issue_pending(get_dma_chan(this));
-
- /* Wait for the interrupt from the DMA block. */
- timeout = wait_for_completion_timeout(dma_c, msecs_to_jiffies(1000));
- if (!timeout) {
- dev_err(this->dev, "DMA timeout, last DMA :%d\n",
- this->last_dma_type);
- gpmi_dump_info(this);
- return -ETIMEDOUT;
- }
- return 0;
-}
-
-/*
- * This function is used in BCH reading or BCH writing pages.
- * It will wait for the BCH interrupt as long as ONE second.
- * Actually, we must wait for two interrupts :
- * [1] firstly the DMA interrupt and
- * [2] secondly the BCH interrupt.
- */
-int start_dma_with_bch_irq(struct gpmi_nand_data *this,
- struct dma_async_tx_descriptor *desc)
-{
- struct completion *bch_c = &this->bch_done;
- unsigned long timeout;
-
- /* Prepare to receive an interrupt from the BCH block. */
- init_completion(bch_c);
-
- /* start the DMA */
- start_dma_without_bch_irq(this, desc);
-
- /* Wait for the interrupt from the BCH block. */
- timeout = wait_for_completion_timeout(bch_c, msecs_to_jiffies(1000));
- if (!timeout) {
- dev_err(this->dev, "BCH timeout, last DMA :%d\n",
- this->last_dma_type);
- gpmi_dump_info(this);
- return -ETIMEDOUT;
- }
- return 0;
-}
-
-static int acquire_register_block(struct gpmi_nand_data *this,
- const char *res_name)
-{
- struct platform_device *pdev = this->pdev;
- struct resources *res = &this->resources;
- struct resource *r;
- void __iomem *p;
-
- r = platform_get_resource_byname(pdev, IORESOURCE_MEM, res_name);
- p = devm_ioremap_resource(&pdev->dev, r);
- if (IS_ERR(p))
- return PTR_ERR(p);
-
- if (!strcmp(res_name, GPMI_NAND_GPMI_REGS_ADDR_RES_NAME))
- res->gpmi_regs = p;
- else if (!strcmp(res_name, GPMI_NAND_BCH_REGS_ADDR_RES_NAME))
- res->bch_regs = p;
- else
- dev_err(this->dev, "unknown resource name : %s\n", res_name);
-
- return 0;
-}
-
-static int acquire_bch_irq(struct gpmi_nand_data *this, irq_handler_t irq_h)
-{
- struct platform_device *pdev = this->pdev;
- const char *res_name = GPMI_NAND_BCH_INTERRUPT_RES_NAME;
- struct resource *r;
- int err;
-
- r = platform_get_resource_byname(pdev, IORESOURCE_IRQ, res_name);
- if (!r) {
- dev_err(this->dev, "Can't get resource for %s\n", res_name);
- return -ENODEV;
- }
-
- err = devm_request_irq(this->dev, r->start, irq_h, 0, res_name, this);
- if (err)
- dev_err(this->dev, "error requesting BCH IRQ\n");
-
- return err;
-}
-
-static void release_dma_channels(struct gpmi_nand_data *this)
-{
- unsigned int i;
- for (i = 0; i < DMA_CHANS; i++)
- if (this->dma_chans[i]) {
- dma_release_channel(this->dma_chans[i]);
- this->dma_chans[i] = NULL;
- }
-}
-
-static int acquire_dma_channels(struct gpmi_nand_data *this)
-{
- struct platform_device *pdev = this->pdev;
- struct dma_chan *dma_chan;
-
- /* request dma channel */
- dma_chan = dma_request_slave_channel(&pdev->dev, "rx-tx");
- if (!dma_chan) {
- dev_err(this->dev, "Failed to request DMA channel.\n");
- goto acquire_err;
- }
-
- this->dma_chans[0] = dma_chan;
- return 0;
-
-acquire_err:
- release_dma_channels(this);
- return -EINVAL;
-}
-
-static int gpmi_get_clks(struct gpmi_nand_data *this)
-{
- struct resources *r = &this->resources;
- struct clk *clk;
- int err, i;
-
- for (i = 0; i < this->devdata->clks_count; i++) {
- clk = devm_clk_get(this->dev, this->devdata->clks[i]);
- if (IS_ERR(clk)) {
- err = PTR_ERR(clk);
- goto err_clock;
- }
-
- r->clock[i] = clk;
- }
-
- if (GPMI_IS_MX6(this))
- /*
- * Set the default value for the gpmi clock.
- *
- * If you want to use the ONFI nand which is in the
- * Synchronous Mode, you should change the clock as you need.
- */
- clk_set_rate(r->clock[0], 22000000);
-
- return 0;
-
-err_clock:
- dev_dbg(this->dev, "failed in finding the clocks.\n");
- return err;
-}
-
-static int acquire_resources(struct gpmi_nand_data *this)
-{
- int ret;
-
- ret = acquire_register_block(this, GPMI_NAND_GPMI_REGS_ADDR_RES_NAME);
- if (ret)
- goto exit_regs;
-
- ret = acquire_register_block(this, GPMI_NAND_BCH_REGS_ADDR_RES_NAME);
- if (ret)
- goto exit_regs;
-
- ret = acquire_bch_irq(this, bch_irq);
- if (ret)
- goto exit_regs;
-
- ret = acquire_dma_channels(this);
- if (ret)
- goto exit_regs;
-
- ret = gpmi_get_clks(this);
- if (ret)
- goto exit_clock;
- return 0;
-
-exit_clock:
- release_dma_channels(this);
-exit_regs:
- return ret;
-}
-
-static void release_resources(struct gpmi_nand_data *this)
-{
- release_dma_channels(this);
-}
-
-static int init_hardware(struct gpmi_nand_data *this)
-{
- int ret;
-
- /*
- * This structure contains the "safe" GPMI timing that should succeed
- * with any NAND Flash device
- * (although, with less-than-optimal performance).
- */
- struct nand_timing safe_timing = {
- .data_setup_in_ns = 80,
- .data_hold_in_ns = 60,
- .address_setup_in_ns = 25,
- .gpmi_sample_delay_in_ns = 6,
- .tREA_in_ns = -1,
- .tRLOH_in_ns = -1,
- .tRHOH_in_ns = -1,
- };
-
- /* Initialize the hardwares. */
- ret = gpmi_init(this);
- if (ret)
- return ret;
-
- this->timing = safe_timing;
- return 0;
-}
-
-static int read_page_prepare(struct gpmi_nand_data *this,
- void *destination, unsigned length,
- void *alt_virt, dma_addr_t alt_phys, unsigned alt_size,
- void **use_virt, dma_addr_t *use_phys)
-{
- struct device *dev = this->dev;
-
- if (virt_addr_valid(destination)) {
- dma_addr_t dest_phys;
-
- dest_phys = dma_map_single(dev, destination,
- length, DMA_FROM_DEVICE);
- if (dma_mapping_error(dev, dest_phys)) {
- if (alt_size < length) {
- dev_err(dev, "Alternate buffer is too small\n");
- return -ENOMEM;
- }
- goto map_failed;
- }
- *use_virt = destination;
- *use_phys = dest_phys;
- this->direct_dma_map_ok = true;
- return 0;
- }
-
-map_failed:
- *use_virt = alt_virt;
- *use_phys = alt_phys;
- this->direct_dma_map_ok = false;
- return 0;
-}
-
-static inline void read_page_end(struct gpmi_nand_data *this,
- void *destination, unsigned length,
- void *alt_virt, dma_addr_t alt_phys, unsigned alt_size,
- void *used_virt, dma_addr_t used_phys)
-{
- if (this->direct_dma_map_ok)
- dma_unmap_single(this->dev, used_phys, length, DMA_FROM_DEVICE);
-}
-
-static inline void read_page_swap_end(struct gpmi_nand_data *this,
- void *destination, unsigned length,
- void *alt_virt, dma_addr_t alt_phys, unsigned alt_size,
- void *used_virt, dma_addr_t used_phys)
-{
- if (!this->direct_dma_map_ok)
- memcpy(destination, alt_virt, length);
-}
-
-static int send_page_prepare(struct gpmi_nand_data *this,
- const void *source, unsigned length,
- void *alt_virt, dma_addr_t alt_phys, unsigned alt_size,
- const void **use_virt, dma_addr_t *use_phys)
-{
- struct device *dev = this->dev;
-
- if (virt_addr_valid(source)) {
- dma_addr_t source_phys;
-
- source_phys = dma_map_single(dev, (void *)source, length,
- DMA_TO_DEVICE);
- if (dma_mapping_error(dev, source_phys)) {
- if (alt_size < length) {
- dev_err(dev, "Alternate buffer is too small\n");
- return -ENOMEM;
- }
- goto map_failed;
- }
- *use_virt = source;
- *use_phys = source_phys;
- return 0;
- }
-map_failed:
- /*
- * Copy the content of the source buffer into the alternate
- * buffer and set up the return values accordingly.
- */
- memcpy(alt_virt, source, length);
-
- *use_virt = alt_virt;
- *use_phys = alt_phys;
- return 0;
-}
-
-static void send_page_end(struct gpmi_nand_data *this,
- const void *source, unsigned length,
- void *alt_virt, dma_addr_t alt_phys, unsigned alt_size,
- const void *used_virt, dma_addr_t used_phys)
-{
- struct device *dev = this->dev;
- if (used_virt == source)
- dma_unmap_single(dev, used_phys, length, DMA_TO_DEVICE);
-}
-
-static void gpmi_free_dma_buffer(struct gpmi_nand_data *this)
-{
- struct device *dev = this->dev;
-
- if (this->page_buffer_virt && virt_addr_valid(this->page_buffer_virt))
- dma_free_coherent(dev, this->page_buffer_size,
- this->page_buffer_virt,
- this->page_buffer_phys);
- kfree(this->cmd_buffer);
- kfree(this->data_buffer_dma);
- kfree(this->raw_buffer);
-
- this->cmd_buffer = NULL;
- this->data_buffer_dma = NULL;
- this->raw_buffer = NULL;
- this->page_buffer_virt = NULL;
- this->page_buffer_size = 0;
-}
-
-/* Allocate the DMA buffers */
-static int gpmi_alloc_dma_buffer(struct gpmi_nand_data *this)
-{
- struct bch_geometry *geo = &this->bch_geometry;
- struct device *dev = this->dev;
- struct mtd_info *mtd = nand_to_mtd(&this->nand);
-
- /* [1] Allocate a command buffer. PAGE_SIZE is enough. */
- this->cmd_buffer = kzalloc(PAGE_SIZE, GFP_DMA | GFP_KERNEL);
- if (this->cmd_buffer == NULL)
- goto error_alloc;
-
- /*
- * [2] Allocate a read/write data buffer.
- * The gpmi_alloc_dma_buffer can be called twice.
- * We allocate a PAGE_SIZE length buffer if gpmi_alloc_dma_buffer
- * is called before the nand_scan_ident; and we allocate a buffer
- * of the real NAND page size when the gpmi_alloc_dma_buffer is
- * called after the nand_scan_ident.
- */
- this->data_buffer_dma = kzalloc(mtd->writesize ?: PAGE_SIZE,
- GFP_DMA | GFP_KERNEL);
- if (this->data_buffer_dma == NULL)
- goto error_alloc;
-
- /*
- * [3] Allocate the page buffer.
- *
- * Both the payload buffer and the auxiliary buffer must appear on
- * 32-bit boundaries. We presume the size of the payload buffer is a
- * power of two and is much larger than four, which guarantees the
- * auxiliary buffer will appear on a 32-bit boundary.
- */
- this->page_buffer_size = geo->payload_size + geo->auxiliary_size;
- this->page_buffer_virt = dma_alloc_coherent(dev, this->page_buffer_size,
- &this->page_buffer_phys, GFP_DMA);
- if (!this->page_buffer_virt)
- goto error_alloc;
-
- this->raw_buffer = kzalloc(mtd->writesize + mtd->oobsize, GFP_KERNEL);
- if (!this->raw_buffer)
- goto error_alloc;
-
- /* Slice up the page buffer. */
- this->payload_virt = this->page_buffer_virt;
- this->payload_phys = this->page_buffer_phys;
- this->auxiliary_virt = this->payload_virt + geo->payload_size;
- this->auxiliary_phys = this->payload_phys + geo->payload_size;
- return 0;
-
-error_alloc:
- gpmi_free_dma_buffer(this);
- return -ENOMEM;
-}
-
-static void gpmi_cmd_ctrl(struct mtd_info *mtd, int data, unsigned int ctrl)
-{
- struct nand_chip *chip = mtd_to_nand(mtd);
- struct gpmi_nand_data *this = nand_get_controller_data(chip);
- int ret;
-
- /*
- * Every operation begins with a command byte and a series of zero or
- * more address bytes. These are distinguished by either the Address
- * Latch Enable (ALE) or Command Latch Enable (CLE) signals being
- * asserted. When MTD is ready to execute the command, it will deassert
- * both latch enables.
- *
- * Rather than run a separate DMA operation for every single byte, we
- * queue them up and run a single DMA operation for the entire series
- * of command and data bytes. NAND_CMD_NONE means the END of the queue.
- */
- if ((ctrl & (NAND_ALE | NAND_CLE))) {
- if (data != NAND_CMD_NONE)
- this->cmd_buffer[this->command_length++] = data;
- return;
- }
-
- if (!this->command_length)
- return;
-
- ret = gpmi_send_command(this);
- if (ret)
- dev_err(this->dev, "Chip: %u, Error %d\n",
- this->current_chip, ret);
-
- this->command_length = 0;
-}
-
-static int gpmi_dev_ready(struct mtd_info *mtd)
-{
- struct nand_chip *chip = mtd_to_nand(mtd);
- struct gpmi_nand_data *this = nand_get_controller_data(chip);
-
- return gpmi_is_ready(this, this->current_chip);
-}
-
-static void gpmi_select_chip(struct mtd_info *mtd, int chipnr)
-{
- struct nand_chip *chip = mtd_to_nand(mtd);
- struct gpmi_nand_data *this = nand_get_controller_data(chip);
-
- if ((this->current_chip < 0) && (chipnr >= 0))
- gpmi_begin(this);
- else if ((this->current_chip >= 0) && (chipnr < 0))
- gpmi_end(this);
-
- this->current_chip = chipnr;
-}
-
-static void gpmi_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
-{
- struct nand_chip *chip = mtd_to_nand(mtd);
- struct gpmi_nand_data *this = nand_get_controller_data(chip);
-
- dev_dbg(this->dev, "len is %d\n", len);
- this->upper_buf = buf;
- this->upper_len = len;
-
- gpmi_read_data(this);
-}
-
-static void gpmi_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
-{
- struct nand_chip *chip = mtd_to_nand(mtd);
- struct gpmi_nand_data *this = nand_get_controller_data(chip);
-
- dev_dbg(this->dev, "len is %d\n", len);
- this->upper_buf = (uint8_t *)buf;
- this->upper_len = len;
-
- gpmi_send_data(this);
-}
-
-static uint8_t gpmi_read_byte(struct mtd_info *mtd)
-{
- struct nand_chip *chip = mtd_to_nand(mtd);
- struct gpmi_nand_data *this = nand_get_controller_data(chip);
- uint8_t *buf = this->data_buffer_dma;
-
- gpmi_read_buf(mtd, buf, 1);
- return buf[0];
-}
-
-/*
- * Handles block mark swapping.
- * It can be called in swapping the block mark, or swapping it back,
- * because the the operations are the same.
- */
-static void block_mark_swapping(struct gpmi_nand_data *this,
- void *payload, void *auxiliary)
-{
- struct bch_geometry *nfc_geo = &this->bch_geometry;
- unsigned char *p;
- unsigned char *a;
- unsigned int bit;
- unsigned char mask;
- unsigned char from_data;
- unsigned char from_oob;
-
- if (!this->swap_block_mark)
- return;
-
- /*
- * If control arrives here, we're swapping. Make some convenience
- * variables.
- */
- bit = nfc_geo->block_mark_bit_offset;
- p = payload + nfc_geo->block_mark_byte_offset;
- a = auxiliary;
-
- /*
- * Get the byte from the data area that overlays the block mark. Since
- * the ECC engine applies its own view to the bits in the page, the
- * physical block mark won't (in general) appear on a byte boundary in
- * the data.
- */
- from_data = (p[0] >> bit) | (p[1] << (8 - bit));
-
- /* Get the byte from the OOB. */
- from_oob = a[0];
-
- /* Swap them. */
- a[0] = from_data;
-
- mask = (0x1 << bit) - 1;
- p[0] = (p[0] & mask) | (from_oob << bit);
-
- mask = ~0 << bit;
- p[1] = (p[1] & mask) | (from_oob >> (8 - bit));
-}
-
-static int gpmi_ecc_read_page_data(struct nand_chip *chip,
- uint8_t *buf, int oob_required,
- int page)
-{
- struct gpmi_nand_data *this = nand_get_controller_data(chip);
- struct bch_geometry *nfc_geo = &this->bch_geometry;
- struct mtd_info *mtd = nand_to_mtd(chip);
- void *payload_virt;
- dma_addr_t payload_phys;
- void *auxiliary_virt;
- dma_addr_t auxiliary_phys;
- unsigned int i;
- unsigned char *status;
- unsigned int max_bitflips = 0;
- int ret;
-
- dev_dbg(this->dev, "page number is : %d\n", page);
- ret = read_page_prepare(this, buf, nfc_geo->payload_size,
- this->payload_virt, this->payload_phys,
- nfc_geo->payload_size,
- &payload_virt, &payload_phys);
- if (ret) {
- dev_err(this->dev, "Inadequate DMA buffer\n");
- ret = -ENOMEM;
- return ret;
- }
- auxiliary_virt = this->auxiliary_virt;
- auxiliary_phys = this->auxiliary_phys;
-
- /* go! */
- ret = gpmi_read_page(this, payload_phys, auxiliary_phys);
- read_page_end(this, buf, nfc_geo->payload_size,
- this->payload_virt, this->payload_phys,
- nfc_geo->payload_size,
- payload_virt, payload_phys);
- if (ret) {
- dev_err(this->dev, "Error in ECC-based read: %d\n", ret);
- return ret;
- }
-
- /* Loop over status bytes, accumulating ECC status. */
- status = auxiliary_virt + nfc_geo->auxiliary_status_offset;
-
- read_page_swap_end(this, buf, nfc_geo->payload_size,
- this->payload_virt, this->payload_phys,
- nfc_geo->payload_size,
- payload_virt, payload_phys);
-
- for (i = 0; i < nfc_geo->ecc_chunk_count; i++, status++) {
- if ((*status == STATUS_GOOD) || (*status == STATUS_ERASED))
- continue;
-
- if (*status == STATUS_UNCORRECTABLE) {
- int eccbits = nfc_geo->ecc_strength * nfc_geo->gf_len;
- u8 *eccbuf = this->raw_buffer;
- int offset, bitoffset;
- int eccbytes;
- int flips;
-
- /* Read ECC bytes into our internal raw_buffer */
- offset = nfc_geo->metadata_size * 8;
- offset += ((8 * nfc_geo->ecc_chunk_size) + eccbits) * (i + 1);
- offset -= eccbits;
- bitoffset = offset % 8;
- eccbytes = DIV_ROUND_UP(offset + eccbits, 8);
- offset /= 8;
- eccbytes -= offset;
- nand_change_read_column_op(chip, offset, eccbuf,
- eccbytes, false);
-
- /*
- * ECC data are not byte aligned and we may have
- * in-band data in the first and last byte of
- * eccbuf. Set non-eccbits to one so that
- * nand_check_erased_ecc_chunk() does not count them
- * as bitflips.
- */
- if (bitoffset)
- eccbuf[0] |= GENMASK(bitoffset - 1, 0);
-
- bitoffset = (bitoffset + eccbits) % 8;
- if (bitoffset)
- eccbuf[eccbytes - 1] |= GENMASK(7, bitoffset);
-
- /*
- * The ECC hardware has an uncorrectable ECC status
- * code in case we have bitflips in an erased page. As
- * nothing was written into this subpage the ECC is
- * obviously wrong and we can not trust it. We assume
- * at this point that we are reading an erased page and
- * try to correct the bitflips in buffer up to
- * ecc_strength bitflips. If this is a page with random
- * data, we exceed this number of bitflips and have a
- * ECC failure. Otherwise we use the corrected buffer.
- */
- if (i == 0) {
- /* The first block includes metadata */
- flips = nand_check_erased_ecc_chunk(
- buf + i * nfc_geo->ecc_chunk_size,
- nfc_geo->ecc_chunk_size,
- eccbuf, eccbytes,
- auxiliary_virt,
- nfc_geo->metadata_size,
- nfc_geo->ecc_strength);
- } else {
- flips = nand_check_erased_ecc_chunk(
- buf + i * nfc_geo->ecc_chunk_size,
- nfc_geo->ecc_chunk_size,
- eccbuf, eccbytes,
- NULL, 0,
- nfc_geo->ecc_strength);
- }
-
- if (flips > 0) {
- max_bitflips = max_t(unsigned int, max_bitflips,
- flips);
- mtd->ecc_stats.corrected += flips;
- continue;
- }
-
- mtd->ecc_stats.failed++;
- continue;
- }
-
- mtd->ecc_stats.corrected += *status;
- max_bitflips = max_t(unsigned int, max_bitflips, *status);
- }
-
- /* handle the block mark swapping */
- block_mark_swapping(this, buf, auxiliary_virt);
-
- if (oob_required) {
- /*
- * It's time to deliver the OOB bytes. See gpmi_ecc_read_oob()
- * for details about our policy for delivering the OOB.
- *
- * We fill the caller's buffer with set bits, and then copy the
- * block mark to th caller's buffer. Note that, if block mark
- * swapping was necessary, it has already been done, so we can
- * rely on the first byte of the auxiliary buffer to contain
- * the block mark.
- */
- memset(chip->oob_poi, ~0, mtd->oobsize);
- chip->oob_poi[0] = ((uint8_t *) auxiliary_virt)[0];
- }
-
- return max_bitflips;
-}
-
-static int gpmi_ecc_read_page(struct mtd_info *mtd, struct nand_chip *chip,
- uint8_t *buf, int oob_required, int page)
-{
- nand_read_page_op(chip, page, 0, NULL, 0);
-
- return gpmi_ecc_read_page_data(chip, buf, oob_required, page);
-}
-
-/* Fake a virtual small page for the subpage read */
-static int gpmi_ecc_read_subpage(struct mtd_info *mtd, struct nand_chip *chip,
- uint32_t offs, uint32_t len, uint8_t *buf, int page)
-{
- struct gpmi_nand_data *this = nand_get_controller_data(chip);
- void __iomem *bch_regs = this->resources.bch_regs;
- struct bch_geometry old_geo = this->bch_geometry;
- struct bch_geometry *geo = &this->bch_geometry;
- int size = chip->ecc.size; /* ECC chunk size */
- int meta, n, page_size;
- u32 r1_old, r2_old, r1_new, r2_new;
- unsigned int max_bitflips;
- int first, last, marker_pos;
- int ecc_parity_size;
- int col = 0;
- int old_swap_block_mark = this->swap_block_mark;
-
- /* The size of ECC parity */
- ecc_parity_size = geo->gf_len * geo->ecc_strength / 8;
-
- /* Align it with the chunk size */
- first = offs / size;
- last = (offs + len - 1) / size;
-
- if (this->swap_block_mark) {
- /*
- * Find the chunk which contains the Block Marker.
- * If this chunk is in the range of [first, last],
- * we have to read out the whole page.
- * Why? since we had swapped the data at the position of Block
- * Marker to the metadata which is bound with the chunk 0.
- */
- marker_pos = geo->block_mark_byte_offset / size;
- if (last >= marker_pos && first <= marker_pos) {
- dev_dbg(this->dev,
- "page:%d, first:%d, last:%d, marker at:%d\n",
- page, first, last, marker_pos);
- return gpmi_ecc_read_page(mtd, chip, buf, 0, page);
- }
- }
-
- meta = geo->metadata_size;
- if (first) {
- col = meta + (size + ecc_parity_size) * first;
- meta = 0;
- buf = buf + first * size;
- }
-
- nand_read_page_op(chip, page, col, NULL, 0);
-
- /* Save the old environment */
- r1_old = r1_new = readl(bch_regs + HW_BCH_FLASH0LAYOUT0);
- r2_old = r2_new = readl(bch_regs + HW_BCH_FLASH0LAYOUT1);
-
- /* change the BCH registers and bch_geometry{} */
- n = last - first + 1;
- page_size = meta + (size + ecc_parity_size) * n;
-
- r1_new &= ~(BM_BCH_FLASH0LAYOUT0_NBLOCKS |
- BM_BCH_FLASH0LAYOUT0_META_SIZE);
- r1_new |= BF_BCH_FLASH0LAYOUT0_NBLOCKS(n - 1)
- | BF_BCH_FLASH0LAYOUT0_META_SIZE(meta);
- writel(r1_new, bch_regs + HW_BCH_FLASH0LAYOUT0);
-
- r2_new &= ~BM_BCH_FLASH0LAYOUT1_PAGE_SIZE;
- r2_new |= BF_BCH_FLASH0LAYOUT1_PAGE_SIZE(page_size);
- writel(r2_new, bch_regs + HW_BCH_FLASH0LAYOUT1);
-
- geo->ecc_chunk_count = n;
- geo->payload_size = n * size;
- geo->page_size = page_size;
- geo->auxiliary_status_offset = ALIGN(meta, 4);
-
- dev_dbg(this->dev, "page:%d(%d:%d)%d, chunk:(%d:%d), BCH PG size:%d\n",
- page, offs, len, col, first, n, page_size);
-
- /* Read the subpage now */
- this->swap_block_mark = false;
- max_bitflips = gpmi_ecc_read_page_data(chip, buf, 0, page);
-
- /* Restore */
- writel(r1_old, bch_regs + HW_BCH_FLASH0LAYOUT0);
- writel(r2_old, bch_regs + HW_BCH_FLASH0LAYOUT1);
- this->bch_geometry = old_geo;
- this->swap_block_mark = old_swap_block_mark;
-
- return max_bitflips;
-}
-
-static int gpmi_ecc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
- const uint8_t *buf, int oob_required, int page)
-{
- struct gpmi_nand_data *this = nand_get_controller_data(chip);
- struct bch_geometry *nfc_geo = &this->bch_geometry;
- const void *payload_virt;
- dma_addr_t payload_phys;
- const void *auxiliary_virt;
- dma_addr_t auxiliary_phys;
- int ret;
-
- dev_dbg(this->dev, "ecc write page.\n");
-
- nand_prog_page_begin_op(chip, page, 0, NULL, 0);
-
- if (this->swap_block_mark) {
- /*
- * If control arrives here, we're doing block mark swapping.
- * Since we can't modify the caller's buffers, we must copy them
- * into our own.
- */
- memcpy(this->payload_virt, buf, mtd->writesize);
- payload_virt = this->payload_virt;
- payload_phys = this->payload_phys;
-
- memcpy(this->auxiliary_virt, chip->oob_poi,
- nfc_geo->auxiliary_size);
- auxiliary_virt = this->auxiliary_virt;
- auxiliary_phys = this->auxiliary_phys;
-
- /* Handle block mark swapping. */
- block_mark_swapping(this,
- (void *)payload_virt, (void *)auxiliary_virt);
- } else {
- /*
- * If control arrives here, we're not doing block mark swapping,
- * so we can to try and use the caller's buffers.
- */
- ret = send_page_prepare(this,
- buf, mtd->writesize,
- this->payload_virt, this->payload_phys,
- nfc_geo->payload_size,
- &payload_virt, &payload_phys);
- if (ret) {
- dev_err(this->dev, "Inadequate payload DMA buffer\n");
- return 0;
- }
-
- ret = send_page_prepare(this,
- chip->oob_poi, mtd->oobsize,
- this->auxiliary_virt, this->auxiliary_phys,
- nfc_geo->auxiliary_size,
- &auxiliary_virt, &auxiliary_phys);
- if (ret) {
- dev_err(this->dev, "Inadequate auxiliary DMA buffer\n");
- goto exit_auxiliary;
- }
- }
-
- /* Ask the NFC. */
- ret = gpmi_send_page(this, payload_phys, auxiliary_phys);
- if (ret)
- dev_err(this->dev, "Error in ECC-based write: %d\n", ret);
-
- if (!this->swap_block_mark) {
- send_page_end(this, chip->oob_poi, mtd->oobsize,
- this->auxiliary_virt, this->auxiliary_phys,
- nfc_geo->auxiliary_size,
- auxiliary_virt, auxiliary_phys);
-exit_auxiliary:
- send_page_end(this, buf, mtd->writesize,
- this->payload_virt, this->payload_phys,
- nfc_geo->payload_size,
- payload_virt, payload_phys);
- }
-
- if (ret)
- return ret;
-
- return nand_prog_page_end_op(chip);
-}
-
-/*
- * There are several places in this driver where we have to handle the OOB and
- * block marks. This is the function where things are the most complicated, so
- * this is where we try to explain it all. All the other places refer back to
- * here.
- *
- * These are the rules, in order of decreasing importance:
- *
- * 1) Nothing the caller does can be allowed to imperil the block mark.
- *
- * 2) In read operations, the first byte of the OOB we return must reflect the
- * true state of the block mark, no matter where that block mark appears in
- * the physical page.
- *
- * 3) ECC-based read operations return an OOB full of set bits (since we never
- * allow ECC-based writes to the OOB, it doesn't matter what ECC-based reads
- * return).
- *
- * 4) "Raw" read operations return a direct view of the physical bytes in the
- * page, using the conventional definition of which bytes are data and which
- * are OOB. This gives the caller a way to see the actual, physical bytes
- * in the page, without the distortions applied by our ECC engine.
- *
- *
- * What we do for this specific read operation depends on two questions:
- *
- * 1) Are we doing a "raw" read, or an ECC-based read?
- *
- * 2) Are we using block mark swapping or transcription?
- *
- * There are four cases, illustrated by the following Karnaugh map:
- *
- * | Raw | ECC-based |
- * -------------+-------------------------+-------------------------+
- * | Read the conventional | |
- * | OOB at the end of the | |
- * Swapping | page and return it. It | |
- * | contains exactly what | |
- * | we want. | Read the block mark and |
- * -------------+-------------------------+ return it in a buffer |
- * | Read the conventional | full of set bits. |
- * | OOB at the end of the | |
- * | page and also the block | |
- * Transcribing | mark in the metadata. | |
- * | Copy the block mark | |
- * | into the first byte of | |
- * | the OOB. | |
- * -------------+-------------------------+-------------------------+
- *
- * Note that we break rule #4 in the Transcribing/Raw case because we're not
- * giving an accurate view of the actual, physical bytes in the page (we're
- * overwriting the block mark). That's OK because it's more important to follow
- * rule #2.
- *
- * It turns out that knowing whether we want an "ECC-based" or "raw" read is not
- * easy. When reading a page, for example, the NAND Flash MTD code calls our
- * ecc.read_page or ecc.read_page_raw function. Thus, the fact that MTD wants an
- * ECC-based or raw view of the page is implicit in which function it calls
- * (there is a similar pair of ECC-based/raw functions for writing).
- */
-static int gpmi_ecc_read_oob(struct mtd_info *mtd, struct nand_chip *chip,
- int page)
-{
- struct gpmi_nand_data *this = nand_get_controller_data(chip);
-
- dev_dbg(this->dev, "page number is %d\n", page);
- /* clear the OOB buffer */
- memset(chip->oob_poi, ~0, mtd->oobsize);
-
- /* Read out the conventional OOB. */
- nand_read_page_op(chip, page, mtd->writesize, NULL, 0);
- chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
-
- /*
- * Now, we want to make sure the block mark is correct. In the
- * non-transcribing case (!GPMI_IS_MX23()), we already have it.
- * Otherwise, we need to explicitly read it.
- */
- if (GPMI_IS_MX23(this)) {
- /* Read the block mark into the first byte of the OOB buffer. */
- nand_read_page_op(chip, page, 0, NULL, 0);
- chip->oob_poi[0] = chip->read_byte(mtd);
- }
-
- return 0;
-}
-
-static int
-gpmi_ecc_write_oob(struct mtd_info *mtd, struct nand_chip *chip, int page)
-{
- struct mtd_oob_region of = { };
-
- /* Do we have available oob area? */
- mtd_ooblayout_free(mtd, 0, &of);
- if (!of.length)
- return -EPERM;
-
- if (!nand_is_slc(chip))
- return -EPERM;
-
- return nand_prog_page_op(chip, page, mtd->writesize + of.offset,
- chip->oob_poi + of.offset, of.length);
-}
-
-/*
- * This function reads a NAND page without involving the ECC engine (no HW
- * ECC correction).
- * The tricky part in the GPMI/BCH controller is that it stores ECC bits
- * inline (interleaved with payload DATA), and do not align data chunk on
- * byte boundaries.
- * We thus need to take care moving the payload data and ECC bits stored in the
- * page into the provided buffers, which is why we're using gpmi_copy_bits.
- *
- * See set_geometry_by_ecc_info inline comments to have a full description
- * of the layout used by the GPMI controller.
- */
-static int gpmi_ecc_read_page_raw(struct mtd_info *mtd,
- struct nand_chip *chip, uint8_t *buf,
- int oob_required, int page)
-{
- struct gpmi_nand_data *this = nand_get_controller_data(chip);
- struct bch_geometry *nfc_geo = &this->bch_geometry;
- int eccsize = nfc_geo->ecc_chunk_size;
- int eccbits = nfc_geo->ecc_strength * nfc_geo->gf_len;
- u8 *tmp_buf = this->raw_buffer;
- size_t src_bit_off;
- size_t oob_bit_off;
- size_t oob_byte_off;
- uint8_t *oob = chip->oob_poi;
- int step;
-
- nand_read_page_op(chip, page, 0, tmp_buf,
- mtd->writesize + mtd->oobsize);
-
- /*
- * If required, swap the bad block marker and the data stored in the
- * metadata section, so that we don't wrongly consider a block as bad.
- *
- * See the layout description for a detailed explanation on why this
- * is needed.
- */
- if (this->swap_block_mark)
- swap(tmp_buf[0], tmp_buf[mtd->writesize]);
-
- /*
- * Copy the metadata section into the oob buffer (this section is
- * guaranteed to be aligned on a byte boundary).
- */
- if (oob_required)
- memcpy(oob, tmp_buf, nfc_geo->metadata_size);
-
- oob_bit_off = nfc_geo->metadata_size * 8;
- src_bit_off = oob_bit_off;
-
- /* Extract interleaved payload data and ECC bits */
- for (step = 0; step < nfc_geo->ecc_chunk_count; step++) {
- if (buf)
- gpmi_copy_bits(buf, step * eccsize * 8,
- tmp_buf, src_bit_off,
- eccsize * 8);
- src_bit_off += eccsize * 8;
-
- /* Align last ECC block to align a byte boundary */
- if (step == nfc_geo->ecc_chunk_count - 1 &&
- (oob_bit_off + eccbits) % 8)
- eccbits += 8 - ((oob_bit_off + eccbits) % 8);
-
- if (oob_required)
- gpmi_copy_bits(oob, oob_bit_off,
- tmp_buf, src_bit_off,
- eccbits);
-
- src_bit_off += eccbits;
- oob_bit_off += eccbits;
- }
-
- if (oob_required) {
- oob_byte_off = oob_bit_off / 8;
-
- if (oob_byte_off < mtd->oobsize)
- memcpy(oob + oob_byte_off,
- tmp_buf + mtd->writesize + oob_byte_off,
- mtd->oobsize - oob_byte_off);
- }
-
- return 0;
-}
-
-/*
- * This function writes a NAND page without involving the ECC engine (no HW
- * ECC generation).
- * The tricky part in the GPMI/BCH controller is that it stores ECC bits
- * inline (interleaved with payload DATA), and do not align data chunk on
- * byte boundaries.
- * We thus need to take care moving the OOB area at the right place in the
- * final page, which is why we're using gpmi_copy_bits.
- *
- * See set_geometry_by_ecc_info inline comments to have a full description
- * of the layout used by the GPMI controller.
- */
-static int gpmi_ecc_write_page_raw(struct mtd_info *mtd,
- struct nand_chip *chip,
- const uint8_t *buf,
- int oob_required, int page)
-{
- struct gpmi_nand_data *this = nand_get_controller_data(chip);
- struct bch_geometry *nfc_geo = &this->bch_geometry;
- int eccsize = nfc_geo->ecc_chunk_size;
- int eccbits = nfc_geo->ecc_strength * nfc_geo->gf_len;
- u8 *tmp_buf = this->raw_buffer;
- uint8_t *oob = chip->oob_poi;
- size_t dst_bit_off;
- size_t oob_bit_off;
- size_t oob_byte_off;
- int step;
-
- /*
- * Initialize all bits to 1 in case we don't have a buffer for the
- * payload or oob data in order to leave unspecified bits of data
- * to their initial state.
- */
- if (!buf || !oob_required)
- memset(tmp_buf, 0xff, mtd->writesize + mtd->oobsize);
-
- /*
- * First copy the metadata section (stored in oob buffer) at the
- * beginning of the page, as imposed by the GPMI layout.
- */
- memcpy(tmp_buf, oob, nfc_geo->metadata_size);
- oob_bit_off = nfc_geo->metadata_size * 8;
- dst_bit_off = oob_bit_off;
-
- /* Interleave payload data and ECC bits */
- for (step = 0; step < nfc_geo->ecc_chunk_count; step++) {
- if (buf)
- gpmi_copy_bits(tmp_buf, dst_bit_off,
- buf, step * eccsize * 8, eccsize * 8);
- dst_bit_off += eccsize * 8;
-
- /* Align last ECC block to align a byte boundary */
- if (step == nfc_geo->ecc_chunk_count - 1 &&
- (oob_bit_off + eccbits) % 8)
- eccbits += 8 - ((oob_bit_off + eccbits) % 8);
-
- if (oob_required)
- gpmi_copy_bits(tmp_buf, dst_bit_off,
- oob, oob_bit_off, eccbits);
-
- dst_bit_off += eccbits;
- oob_bit_off += eccbits;
- }
-
- oob_byte_off = oob_bit_off / 8;
-
- if (oob_required && oob_byte_off < mtd->oobsize)
- memcpy(tmp_buf + mtd->writesize + oob_byte_off,
- oob + oob_byte_off, mtd->oobsize - oob_byte_off);
-
- /*
- * If required, swap the bad block marker and the first byte of the
- * metadata section, so that we don't modify the bad block marker.
- *
- * See the layout description for a detailed explanation on why this
- * is needed.
- */
- if (this->swap_block_mark)
- swap(tmp_buf[0], tmp_buf[mtd->writesize]);
-
- return nand_prog_page_op(chip, page, 0, tmp_buf,
- mtd->writesize + mtd->oobsize);
-}
-
-static int gpmi_ecc_read_oob_raw(struct mtd_info *mtd, struct nand_chip *chip,
- int page)
-{
- return gpmi_ecc_read_page_raw(mtd, chip, NULL, 1, page);
-}
-
-static int gpmi_ecc_write_oob_raw(struct mtd_info *mtd, struct nand_chip *chip,
- int page)
-{
- return gpmi_ecc_write_page_raw(mtd, chip, NULL, 1, page);
-}
-
-static int gpmi_block_markbad(struct mtd_info *mtd, loff_t ofs)
-{
- struct nand_chip *chip = mtd_to_nand(mtd);
- struct gpmi_nand_data *this = nand_get_controller_data(chip);
- int ret = 0;
- uint8_t *block_mark;
- int column, page, chipnr;
-
- chipnr = (int)(ofs >> chip->chip_shift);
- chip->select_chip(mtd, chipnr);
-
- column = !GPMI_IS_MX23(this) ? mtd->writesize : 0;
-
- /* Write the block mark. */
- block_mark = this->data_buffer_dma;
- block_mark[0] = 0; /* bad block marker */
-
- /* Shift to get page */
- page = (int)(ofs >> chip->page_shift);
-
- ret = nand_prog_page_op(chip, page, column, block_mark, 1);
-
- chip->select_chip(mtd, -1);
-
- return ret;
-}
-
-static int nand_boot_set_geometry(struct gpmi_nand_data *this)
-{
- struct boot_rom_geometry *geometry = &this->rom_geometry;
-
- /*
- * Set the boot block stride size.
- *
- * In principle, we should be reading this from the OTP bits, since
- * that's where the ROM is going to get it. In fact, we don't have any
- * way to read the OTP bits, so we go with the default and hope for the
- * best.
- */
- geometry->stride_size_in_pages = 64;
-
- /*
- * Set the search area stride exponent.
- *
- * In principle, we should be reading this from the OTP bits, since
- * that's where the ROM is going to get it. In fact, we don't have any
- * way to read the OTP bits, so we go with the default and hope for the
- * best.
- */
- geometry->search_area_stride_exponent = 2;
- return 0;
-}
-
-static const char *fingerprint = "STMP";
-static int mx23_check_transcription_stamp(struct gpmi_nand_data *this)
-{
- struct boot_rom_geometry *rom_geo = &this->rom_geometry;
- struct device *dev = this->dev;
- struct nand_chip *chip = &this->nand;
- struct mtd_info *mtd = nand_to_mtd(chip);
- unsigned int search_area_size_in_strides;
- unsigned int stride;
- unsigned int page;
- uint8_t *buffer = chip->data_buf;
- int saved_chip_number;
- int found_an_ncb_fingerprint = false;
-
- /* Compute the number of strides in a search area. */
- search_area_size_in_strides = 1 << rom_geo->search_area_stride_exponent;
-
- saved_chip_number = this->current_chip;
- chip->select_chip(mtd, 0);
-
- /*
- * Loop through the first search area, looking for the NCB fingerprint.
- */
- dev_dbg(dev, "Scanning for an NCB fingerprint...\n");
-
- for (stride = 0; stride < search_area_size_in_strides; stride++) {
- /* Compute the page addresses. */
- page = stride * rom_geo->stride_size_in_pages;
-
- dev_dbg(dev, "Looking for a fingerprint in page 0x%x\n", page);
-
- /*
- * Read the NCB fingerprint. The fingerprint is four bytes long
- * and starts in the 12th byte of the page.
- */
- nand_read_page_op(chip, page, 12, NULL, 0);
- chip->read_buf(mtd, buffer, strlen(fingerprint));
-
- /* Look for the fingerprint. */
- if (!memcmp(buffer, fingerprint, strlen(fingerprint))) {
- found_an_ncb_fingerprint = true;
- break;
- }
-
- }
-
- chip->select_chip(mtd, saved_chip_number);
-
- if (found_an_ncb_fingerprint)
- dev_dbg(dev, "\tFound a fingerprint\n");
- else
- dev_dbg(dev, "\tNo fingerprint found\n");
- return found_an_ncb_fingerprint;
-}
-
-/* Writes a transcription stamp. */
-static int mx23_write_transcription_stamp(struct gpmi_nand_data *this)
-{
- struct device *dev = this->dev;
- struct boot_rom_geometry *rom_geo = &this->rom_geometry;
- struct nand_chip *chip = &this->nand;
- struct mtd_info *mtd = nand_to_mtd(chip);
- unsigned int block_size_in_pages;
- unsigned int search_area_size_in_strides;
- unsigned int search_area_size_in_pages;
- unsigned int search_area_size_in_blocks;
- unsigned int block;
- unsigned int stride;
- unsigned int page;
- uint8_t *buffer = chip->data_buf;
- int saved_chip_number;
- int status;
-
- /* Compute the search area geometry. */
- block_size_in_pages = mtd->erasesize / mtd->writesize;
- search_area_size_in_strides = 1 << rom_geo->search_area_stride_exponent;
- search_area_size_in_pages = search_area_size_in_strides *
- rom_geo->stride_size_in_pages;
- search_area_size_in_blocks =
- (search_area_size_in_pages + (block_size_in_pages - 1)) /
- block_size_in_pages;
-
- dev_dbg(dev, "Search Area Geometry :\n");
- dev_dbg(dev, "\tin Blocks : %u\n", search_area_size_in_blocks);
- dev_dbg(dev, "\tin Strides: %u\n", search_area_size_in_strides);
- dev_dbg(dev, "\tin Pages : %u\n", search_area_size_in_pages);
-
- /* Select chip 0. */
- saved_chip_number = this->current_chip;
- chip->select_chip(mtd, 0);
-
- /* Loop over blocks in the first search area, erasing them. */
- dev_dbg(dev, "Erasing the search area...\n");
-
- for (block = 0; block < search_area_size_in_blocks; block++) {
- /* Erase this block. */
- dev_dbg(dev, "\tErasing block 0x%x\n", block);
- status = nand_erase_op(chip, block);
- if (status)
- dev_err(dev, "[%s] Erase failed.\n", __func__);
- }
-
- /* Write the NCB fingerprint into the page buffer. */
- memset(buffer, ~0, mtd->writesize);
- memcpy(buffer + 12, fingerprint, strlen(fingerprint));
-
- /* Loop through the first search area, writing NCB fingerprints. */
- dev_dbg(dev, "Writing NCB fingerprints...\n");
- for (stride = 0; stride < search_area_size_in_strides; stride++) {
- /* Compute the page addresses. */
- page = stride * rom_geo->stride_size_in_pages;
-
- /* Write the first page of the current stride. */
- dev_dbg(dev, "Writing an NCB fingerprint in page 0x%x\n", page);
-
- status = chip->ecc.write_page_raw(mtd, chip, buffer, 0, page);
- if (status)
- dev_err(dev, "[%s] Write failed.\n", __func__);
- }
-
- /* Deselect chip 0. */
- chip->select_chip(mtd, saved_chip_number);
- return 0;
-}
-
-static int mx23_boot_init(struct gpmi_nand_data *this)
-{
- struct device *dev = this->dev;
- struct nand_chip *chip = &this->nand;
- struct mtd_info *mtd = nand_to_mtd(chip);
- unsigned int block_count;
- unsigned int block;
- int chipnr;
- int page;
- loff_t byte;
- uint8_t block_mark;
- int ret = 0;
-
- /*
- * If control arrives here, we can't use block mark swapping, which
- * means we're forced to use transcription. First, scan for the
- * transcription stamp. If we find it, then we don't have to do
- * anything -- the block marks are already transcribed.
- */
- if (mx23_check_transcription_stamp(this))
- return 0;
-
- /*
- * If control arrives here, we couldn't find a transcription stamp, so
- * so we presume the block marks are in the conventional location.
- */
- dev_dbg(dev, "Transcribing bad block marks...\n");
-
- /* Compute the number of blocks in the entire medium. */
- block_count = chip->chipsize >> chip->phys_erase_shift;
-
- /*
- * Loop over all the blocks in the medium, transcribing block marks as
- * we go.
- */
- for (block = 0; block < block_count; block++) {
- /*
- * Compute the chip, page and byte addresses for this block's
- * conventional mark.
- */
- chipnr = block >> (chip->chip_shift - chip->phys_erase_shift);
- page = block << (chip->phys_erase_shift - chip->page_shift);
- byte = block << chip->phys_erase_shift;
-
- /* Send the command to read the conventional block mark. */
- chip->select_chip(mtd, chipnr);
- nand_read_page_op(chip, page, mtd->writesize, NULL, 0);
- block_mark = chip->read_byte(mtd);
- chip->select_chip(mtd, -1);
-
- /*
- * Check if the block is marked bad. If so, we need to mark it
- * again, but this time the result will be a mark in the
- * location where we transcribe block marks.
- */
- if (block_mark != 0xff) {
- dev_dbg(dev, "Transcribing mark in block %u\n", block);
- ret = chip->block_markbad(mtd, byte);
- if (ret)
- dev_err(dev,
- "Failed to mark block bad with ret %d\n",
- ret);
- }
- }
-
- /* Write the stamp that indicates we've transcribed the block marks. */
- mx23_write_transcription_stamp(this);
- return 0;
-}
-
-static int nand_boot_init(struct gpmi_nand_data *this)
-{
- nand_boot_set_geometry(this);
-
- /* This is ROM arch-specific initilization before the BBT scanning. */
- if (GPMI_IS_MX23(this))
- return mx23_boot_init(this);
- return 0;
-}
-
-static int gpmi_set_geometry(struct gpmi_nand_data *this)
-{
- int ret;
-
- /* Free the temporary DMA memory for reading ID. */
- gpmi_free_dma_buffer(this);
-
- /* Set up the NFC geometry which is used by BCH. */
- ret = bch_set_geometry(this);
- if (ret) {
- dev_err(this->dev, "Error setting BCH geometry : %d\n", ret);
- return ret;
- }
-
- /* Alloc the new DMA buffers according to the pagesize and oobsize */
- return gpmi_alloc_dma_buffer(this);
-}
-
-static int gpmi_init_last(struct gpmi_nand_data *this)
-{
- struct nand_chip *chip = &this->nand;
- struct mtd_info *mtd = nand_to_mtd(chip);
- struct nand_ecc_ctrl *ecc = &chip->ecc;
- struct bch_geometry *bch_geo = &this->bch_geometry;
- int ret;
-
- /* Set up the medium geometry */
- ret = gpmi_set_geometry(this);
- if (ret)
- return ret;
-
- /* Init the nand_ecc_ctrl{} */
- ecc->read_page = gpmi_ecc_read_page;
- ecc->write_page = gpmi_ecc_write_page;
- ecc->read_oob = gpmi_ecc_read_oob;
- ecc->write_oob = gpmi_ecc_write_oob;
- ecc->read_page_raw = gpmi_ecc_read_page_raw;
- ecc->write_page_raw = gpmi_ecc_write_page_raw;
- ecc->read_oob_raw = gpmi_ecc_read_oob_raw;
- ecc->write_oob_raw = gpmi_ecc_write_oob_raw;
- ecc->mode = NAND_ECC_HW;
- ecc->size = bch_geo->ecc_chunk_size;
- ecc->strength = bch_geo->ecc_strength;
- mtd_set_ooblayout(mtd, &gpmi_ooblayout_ops);
-
- /*
- * We only enable the subpage read when:
- * (1) the chip is imx6, and
- * (2) the size of the ECC parity is byte aligned.
- */
- if (GPMI_IS_MX6(this) &&
- ((bch_geo->gf_len * bch_geo->ecc_strength) % 8) == 0) {
- ecc->read_subpage = gpmi_ecc_read_subpage;
- chip->options |= NAND_SUBPAGE_READ;
- }
-
- /*
- * Can we enable the extra features? such as EDO or Sync mode.
- *
- * We do not check the return value now. That's means if we fail in
- * enable the extra features, we still can run in the normal way.
- */
- gpmi_extra_init(this);
-
- return 0;
-}
-
-static int gpmi_nand_init(struct gpmi_nand_data *this)
-{
- struct nand_chip *chip = &this->nand;
- struct mtd_info *mtd = nand_to_mtd(chip);
- int ret;
-
- /* init current chip */
- this->current_chip = -1;
-
- /* init the MTD data structures */
- mtd->name = "gpmi-nand";
- mtd->dev.parent = this->dev;
-
- /* init the nand_chip{}, we don't support a 16-bit NAND Flash bus. */
- nand_set_controller_data(chip, this);
- nand_set_flash_node(chip, this->pdev->dev.of_node);
- chip->select_chip = gpmi_select_chip;
- chip->cmd_ctrl = gpmi_cmd_ctrl;
- chip->dev_ready = gpmi_dev_ready;
- chip->read_byte = gpmi_read_byte;
- chip->read_buf = gpmi_read_buf;
- chip->write_buf = gpmi_write_buf;
- chip->badblock_pattern = &gpmi_bbt_descr;
- chip->block_markbad = gpmi_block_markbad;
- chip->options |= NAND_NO_SUBPAGE_WRITE;
-
- /* Set up swap_block_mark, must be set before the gpmi_set_geometry() */
- this->swap_block_mark = !GPMI_IS_MX23(this);
-
- /*
- * Allocate a temporary DMA buffer for reading ID in the
- * nand_scan_ident().
- */
- this->bch_geometry.payload_size = 1024;
- this->bch_geometry.auxiliary_size = 128;
- ret = gpmi_alloc_dma_buffer(this);
- if (ret)
- goto err_out;
-
- ret = nand_scan_ident(mtd, GPMI_IS_MX6(this) ? 2 : 1, NULL);
- if (ret)
- goto err_out;
-
- if (chip->bbt_options & NAND_BBT_USE_FLASH) {
- chip->bbt_options |= NAND_BBT_NO_OOB;
-
- if (of_property_read_bool(this->dev->of_node,
- "fsl,no-blockmark-swap"))
- this->swap_block_mark = false;
- }
- dev_dbg(this->dev, "Blockmark swapping %sabled\n",
- this->swap_block_mark ? "en" : "dis");
-
- ret = gpmi_init_last(this);
- if (ret)
- goto err_out;
-
- chip->options |= NAND_SKIP_BBTSCAN;
- ret = nand_scan_tail(mtd);
- if (ret)
- goto err_out;
-
- ret = nand_boot_init(this);
- if (ret)
- goto err_nand_cleanup;
- ret = chip->scan_bbt(mtd);
- if (ret)
- goto err_nand_cleanup;
-
- ret = mtd_device_register(mtd, NULL, 0);
- if (ret)
- goto err_nand_cleanup;
- return 0;
-
-err_nand_cleanup:
- nand_cleanup(chip);
-err_out:
- gpmi_free_dma_buffer(this);
- return ret;
-}
-
-static const struct of_device_id gpmi_nand_id_table[] = {
- {
- .compatible = "fsl,imx23-gpmi-nand",
- .data = &gpmi_devdata_imx23,
- }, {
- .compatible = "fsl,imx28-gpmi-nand",
- .data = &gpmi_devdata_imx28,
- }, {
- .compatible = "fsl,imx6q-gpmi-nand",
- .data = &gpmi_devdata_imx6q,
- }, {
- .compatible = "fsl,imx6sx-gpmi-nand",
- .data = &gpmi_devdata_imx6sx,
- }, {
- .compatible = "fsl,imx7d-gpmi-nand",
- .data = &gpmi_devdata_imx7d,
- }, {}
-};
-MODULE_DEVICE_TABLE(of, gpmi_nand_id_table);
-
-static int gpmi_nand_probe(struct platform_device *pdev)
-{
- struct gpmi_nand_data *this;
- const struct of_device_id *of_id;
- int ret;
-
- this = devm_kzalloc(&pdev->dev, sizeof(*this), GFP_KERNEL);
- if (!this)
- return -ENOMEM;
-
- of_id = of_match_device(gpmi_nand_id_table, &pdev->dev);
- if (of_id) {
- this->devdata = of_id->data;
- } else {
- dev_err(&pdev->dev, "Failed to find the right device id.\n");
- return -ENODEV;
- }
-
- platform_set_drvdata(pdev, this);
- this->pdev = pdev;
- this->dev = &pdev->dev;
-
- ret = acquire_resources(this);
- if (ret)
- goto exit_acquire_resources;
-
- ret = init_hardware(this);
- if (ret)
- goto exit_nfc_init;
-
- ret = gpmi_nand_init(this);
- if (ret)
- goto exit_nfc_init;
-
- dev_info(this->dev, "driver registered.\n");
-
- return 0;
-
-exit_nfc_init:
- release_resources(this);
-exit_acquire_resources:
-
- return ret;
-}
-
-static int gpmi_nand_remove(struct platform_device *pdev)
-{
- struct gpmi_nand_data *this = platform_get_drvdata(pdev);
-
- nand_release(nand_to_mtd(&this->nand));
- gpmi_free_dma_buffer(this);
- release_resources(this);
- return 0;
-}
-
-#ifdef CONFIG_PM_SLEEP
-static int gpmi_pm_suspend(struct device *dev)
-{
- struct gpmi_nand_data *this = dev_get_drvdata(dev);
-
- release_dma_channels(this);
- return 0;
-}
-
-static int gpmi_pm_resume(struct device *dev)
-{
- struct gpmi_nand_data *this = dev_get_drvdata(dev);
- int ret;
-
- ret = acquire_dma_channels(this);
- if (ret < 0)
- return ret;
-
- /* re-init the GPMI registers */
- this->flags &= ~GPMI_TIMING_INIT_OK;
- ret = gpmi_init(this);
- if (ret) {
- dev_err(this->dev, "Error setting GPMI : %d\n", ret);
- return ret;
- }
-
- /* re-init the BCH registers */
- ret = bch_set_geometry(this);
- if (ret) {
- dev_err(this->dev, "Error setting BCH : %d\n", ret);
- return ret;
- }
-
- /* re-init others */
- gpmi_extra_init(this);
-
- return 0;
-}
-#endif /* CONFIG_PM_SLEEP */
-
-static const struct dev_pm_ops gpmi_pm_ops = {
- SET_SYSTEM_SLEEP_PM_OPS(gpmi_pm_suspend, gpmi_pm_resume)
-};
-
-static struct platform_driver gpmi_nand_driver = {
- .driver = {
- .name = "gpmi-nand",
- .pm = &gpmi_pm_ops,
- .of_match_table = gpmi_nand_id_table,
- },
- .probe = gpmi_nand_probe,
- .remove = gpmi_nand_remove,
-};
-module_platform_driver(gpmi_nand_driver);
-
-MODULE_AUTHOR("Freescale Semiconductor, Inc.");
-MODULE_DESCRIPTION("i.MX GPMI NAND Flash Controller Driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-nand.h b/drivers/mtd/nand/gpmi-nand/gpmi-nand.h
deleted file mode 100644
index 06c1f993912c..000000000000
--- a/drivers/mtd/nand/gpmi-nand/gpmi-nand.h
+++ /dev/null
@@ -1,315 +0,0 @@
-/*
- * Freescale GPMI NAND Flash Driver
- *
- * Copyright (C) 2010-2011 Freescale Semiconductor, Inc.
- * Copyright (C) 2008 Embedded Alley Solutions, Inc.
- *
- * 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.
- */
-#ifndef __DRIVERS_MTD_NAND_GPMI_NAND_H
-#define __DRIVERS_MTD_NAND_GPMI_NAND_H
-
-#include <linux/mtd/rawnand.h>
-#include <linux/platform_device.h>
-#include <linux/dma-mapping.h>
-#include <linux/dmaengine.h>
-
-#define GPMI_CLK_MAX 5 /* MX6Q needs five clocks */
-struct resources {
- void __iomem *gpmi_regs;
- void __iomem *bch_regs;
- unsigned int dma_low_channel;
- unsigned int dma_high_channel;
- struct clk *clock[GPMI_CLK_MAX];
-};
-
-/**
- * struct bch_geometry - BCH geometry description.
- * @gf_len: The length of Galois Field. (e.g., 13 or 14)
- * @ecc_strength: A number that describes the strength of the ECC
- * algorithm.
- * @page_size: The size, in bytes, of a physical page, including
- * both data and OOB.
- * @metadata_size: The size, in bytes, of the metadata.
- * @ecc_chunk_size: The size, in bytes, of a single ECC chunk. Note
- * the first chunk in the page includes both data and
- * metadata, so it's a bit larger than this value.
- * @ecc_chunk_count: The number of ECC chunks in the page,
- * @payload_size: The size, in bytes, of the payload buffer.
- * @auxiliary_size: The size, in bytes, of the auxiliary buffer.
- * @auxiliary_status_offset: The offset into the auxiliary buffer at which
- * the ECC status appears.
- * @block_mark_byte_offset: The byte offset in the ECC-based page view at
- * which the underlying physical block mark appears.
- * @block_mark_bit_offset: The bit offset into the ECC-based page view at
- * which the underlying physical block mark appears.
- */
-struct bch_geometry {
- unsigned int gf_len;
- unsigned int ecc_strength;
- unsigned int page_size;
- unsigned int metadata_size;
- unsigned int ecc_chunk_size;
- unsigned int ecc_chunk_count;
- unsigned int payload_size;
- unsigned int auxiliary_size;
- unsigned int auxiliary_status_offset;
- unsigned int block_mark_byte_offset;
- unsigned int block_mark_bit_offset;
-};
-
-/**
- * struct boot_rom_geometry - Boot ROM geometry description.
- * @stride_size_in_pages: The size of a boot block stride, in pages.
- * @search_area_stride_exponent: The logarithm to base 2 of the size of a
- * search area in boot block strides.
- */
-struct boot_rom_geometry {
- unsigned int stride_size_in_pages;
- unsigned int search_area_stride_exponent;
-};
-
-/* DMA operations types */
-enum dma_ops_type {
- DMA_FOR_COMMAND = 1,
- DMA_FOR_READ_DATA,
- DMA_FOR_WRITE_DATA,
- DMA_FOR_READ_ECC_PAGE,
- DMA_FOR_WRITE_ECC_PAGE
-};
-
-/**
- * struct nand_timing - Fundamental timing attributes for NAND.
- * @data_setup_in_ns: The data setup time, in nanoseconds. Usually the
- * maximum of tDS and tWP. A negative value
- * indicates this characteristic isn't known.
- * @data_hold_in_ns: The data hold time, in nanoseconds. Usually the
- * maximum of tDH, tWH and tREH. A negative value
- * indicates this characteristic isn't known.
- * @address_setup_in_ns: The address setup time, in nanoseconds. Usually
- * the maximum of tCLS, tCS and tALS. A negative
- * value indicates this characteristic isn't known.
- * @gpmi_sample_delay_in_ns: A GPMI-specific timing parameter. A negative value
- * indicates this characteristic isn't known.
- * @tREA_in_ns: tREA, in nanoseconds, from the data sheet. A
- * negative value indicates this characteristic isn't
- * known.
- * @tRLOH_in_ns: tRLOH, in nanoseconds, from the data sheet. A
- * negative value indicates this characteristic isn't
- * known.
- * @tRHOH_in_ns: tRHOH, in nanoseconds, from the data sheet. A
- * negative value indicates this characteristic isn't
- * known.
- */
-struct nand_timing {
- int8_t data_setup_in_ns;
- int8_t data_hold_in_ns;
- int8_t address_setup_in_ns;
- int8_t gpmi_sample_delay_in_ns;
- int8_t tREA_in_ns;
- int8_t tRLOH_in_ns;
- int8_t tRHOH_in_ns;
-};
-
-enum gpmi_type {
- IS_MX23,
- IS_MX28,
- IS_MX6Q,
- IS_MX6SX,
- IS_MX7D,
-};
-
-struct gpmi_devdata {
- enum gpmi_type type;
- int bch_max_ecc_strength;
- int max_chain_delay; /* See the async EDO mode */
- const char * const *clks;
- const int clks_count;
-};
-
-struct gpmi_nand_data {
- /* flags */
-#define GPMI_ASYNC_EDO_ENABLED (1 << 0)
-#define GPMI_TIMING_INIT_OK (1 << 1)
- int flags;
- const struct gpmi_devdata *devdata;
-
- /* System Interface */
- struct device *dev;
- struct platform_device *pdev;
-
- /* Resources */
- struct resources resources;
-
- /* Flash Hardware */
- struct nand_timing timing;
- int timing_mode;
-
- /* BCH */
- struct bch_geometry bch_geometry;
- struct completion bch_done;
-
- /* NAND Boot issue */
- bool swap_block_mark;
- struct boot_rom_geometry rom_geometry;
-
- /* MTD / NAND */
- struct nand_chip nand;
-
- /* General-use Variables */
- int current_chip;
- unsigned int command_length;
-
- /* passed from upper layer */
- uint8_t *upper_buf;
- int upper_len;
-
- /* for DMA operations */
- bool direct_dma_map_ok;
-
- struct scatterlist cmd_sgl;
- char *cmd_buffer;
-
- struct scatterlist data_sgl;
- char *data_buffer_dma;
-
- void *page_buffer_virt;
- dma_addr_t page_buffer_phys;
- unsigned int page_buffer_size;
-
- void *payload_virt;
- dma_addr_t payload_phys;
-
- void *auxiliary_virt;
- dma_addr_t auxiliary_phys;
-
- void *raw_buffer;
-
- /* DMA channels */
-#define DMA_CHANS 8
- struct dma_chan *dma_chans[DMA_CHANS];
- enum dma_ops_type last_dma_type;
- enum dma_ops_type dma_type;
- struct completion dma_done;
-
- /* private */
- void *private;
-};
-
-/**
- * struct gpmi_nfc_hardware_timing - GPMI hardware timing parameters.
- * @data_setup_in_cycles: The data setup time, in cycles.
- * @data_hold_in_cycles: The data hold time, in cycles.
- * @address_setup_in_cycles: The address setup time, in cycles.
- * @device_busy_timeout: The timeout waiting for NAND Ready/Busy,
- * this value is the number of cycles multiplied
- * by 4096.
- * @use_half_periods: Indicates the clock is running slowly, so the
- * NFC DLL should use half-periods.
- * @sample_delay_factor: The sample delay factor.
- * @wrn_dly_sel: The delay on the GPMI write strobe.
- */
-struct gpmi_nfc_hardware_timing {
- /* for HW_GPMI_TIMING0 */
- uint8_t data_setup_in_cycles;
- uint8_t data_hold_in_cycles;
- uint8_t address_setup_in_cycles;
-
- /* for HW_GPMI_TIMING1 */
- uint16_t device_busy_timeout;
-#define GPMI_DEFAULT_BUSY_TIMEOUT 0x500 /* default busy timeout value.*/
-
- /* for HW_GPMI_CTRL1 */
- bool use_half_periods;
- uint8_t sample_delay_factor;
- uint8_t wrn_dly_sel;
-};
-
-/**
- * struct timing_threshold - Timing threshold
- * @max_data_setup_cycles: The maximum number of data setup cycles that
- * can be expressed in the hardware.
- * @internal_data_setup_in_ns: The time, in ns, that the NFC hardware requires
- * for data read internal setup. In the Reference
- * Manual, see the chapter "High-Speed NAND
- * Timing" for more details.
- * @max_sample_delay_factor: The maximum sample delay factor that can be
- * expressed in the hardware.
- * @max_dll_clock_period_in_ns: The maximum period of the GPMI clock that the
- * sample delay DLL hardware can possibly work
- * with (the DLL is unusable with longer periods).
- * If the full-cycle period is greater than HALF
- * this value, the DLL must be configured to use
- * half-periods.
- * @max_dll_delay_in_ns: The maximum amount of delay, in ns, that the
- * DLL can implement.
- * @clock_frequency_in_hz: The clock frequency, in Hz, during the current
- * I/O transaction. If no I/O transaction is in
- * progress, this is the clock frequency during
- * the most recent I/O transaction.
- */
-struct timing_threshold {
- const unsigned int max_chip_count;
- const unsigned int max_data_setup_cycles;
- const unsigned int internal_data_setup_in_ns;
- const unsigned int max_sample_delay_factor;
- const unsigned int max_dll_clock_period_in_ns;
- const unsigned int max_dll_delay_in_ns;
- unsigned long clock_frequency_in_hz;
-
-};
-
-/* Common Services */
-int common_nfc_set_geometry(struct gpmi_nand_data *);
-struct dma_chan *get_dma_chan(struct gpmi_nand_data *);
-void prepare_data_dma(struct gpmi_nand_data *,
- enum dma_data_direction dr);
-int start_dma_without_bch_irq(struct gpmi_nand_data *,
- struct dma_async_tx_descriptor *);
-int start_dma_with_bch_irq(struct gpmi_nand_data *,
- struct dma_async_tx_descriptor *);
-
-/* GPMI-NAND helper function library */
-int gpmi_init(struct gpmi_nand_data *);
-int gpmi_extra_init(struct gpmi_nand_data *);
-void gpmi_clear_bch(struct gpmi_nand_data *);
-void gpmi_dump_info(struct gpmi_nand_data *);
-int bch_set_geometry(struct gpmi_nand_data *);
-int gpmi_is_ready(struct gpmi_nand_data *, unsigned chip);
-int gpmi_send_command(struct gpmi_nand_data *);
-void gpmi_begin(struct gpmi_nand_data *);
-void gpmi_end(struct gpmi_nand_data *);
-int gpmi_read_data(struct gpmi_nand_data *);
-int gpmi_send_data(struct gpmi_nand_data *);
-int gpmi_send_page(struct gpmi_nand_data *,
- dma_addr_t payload, dma_addr_t auxiliary);
-int gpmi_read_page(struct gpmi_nand_data *,
- dma_addr_t payload, dma_addr_t auxiliary);
-
-void gpmi_copy_bits(u8 *dst, size_t dst_bit_off,
- const u8 *src, size_t src_bit_off,
- size_t nbits);
-
-/* BCH : Status Block Completion Codes */
-#define STATUS_GOOD 0x00
-#define STATUS_ERASED 0xff
-#define STATUS_UNCORRECTABLE 0xfe
-
-/* Use the devdata to distinguish different Archs. */
-#define GPMI_IS_MX23(x) ((x)->devdata->type == IS_MX23)
-#define GPMI_IS_MX28(x) ((x)->devdata->type == IS_MX28)
-#define GPMI_IS_MX6Q(x) ((x)->devdata->type == IS_MX6Q)
-#define GPMI_IS_MX6SX(x) ((x)->devdata->type == IS_MX6SX)
-#define GPMI_IS_MX7D(x) ((x)->devdata->type == IS_MX7D)
-
-#define GPMI_IS_MX6(x) (GPMI_IS_MX6Q(x) || GPMI_IS_MX6SX(x) || \
- GPMI_IS_MX7D(x))
-#endif
diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-regs.h b/drivers/mtd/nand/gpmi-nand/gpmi-regs.h
deleted file mode 100644
index 82114cdc8330..000000000000
--- a/drivers/mtd/nand/gpmi-nand/gpmi-regs.h
+++ /dev/null
@@ -1,187 +0,0 @@
-/*
- * Freescale GPMI NAND Flash Driver
- *
- * Copyright 2008-2011 Freescale Semiconductor, Inc.
- * Copyright 2008 Embedded Alley Solutions, Inc.
- *
- * 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.
- */
-#ifndef __GPMI_NAND_GPMI_REGS_H
-#define __GPMI_NAND_GPMI_REGS_H
-
-#define HW_GPMI_CTRL0 0x00000000
-#define HW_GPMI_CTRL0_SET 0x00000004
-#define HW_GPMI_CTRL0_CLR 0x00000008
-#define HW_GPMI_CTRL0_TOG 0x0000000c
-
-#define BP_GPMI_CTRL0_COMMAND_MODE 24
-#define BM_GPMI_CTRL0_COMMAND_MODE (3 << BP_GPMI_CTRL0_COMMAND_MODE)
-#define BF_GPMI_CTRL0_COMMAND_MODE(v) \
- (((v) << BP_GPMI_CTRL0_COMMAND_MODE) & BM_GPMI_CTRL0_COMMAND_MODE)
-#define BV_GPMI_CTRL0_COMMAND_MODE__WRITE 0x0
-#define BV_GPMI_CTRL0_COMMAND_MODE__READ 0x1
-#define BV_GPMI_CTRL0_COMMAND_MODE__READ_AND_COMPARE 0x2
-#define BV_GPMI_CTRL0_COMMAND_MODE__WAIT_FOR_READY 0x3
-
-#define BM_GPMI_CTRL0_WORD_LENGTH (1 << 23)
-#define BV_GPMI_CTRL0_WORD_LENGTH__16_BIT 0x0
-#define BV_GPMI_CTRL0_WORD_LENGTH__8_BIT 0x1
-
-/*
- * Difference in LOCK_CS between imx23 and imx28 :
- * This bit may impact the _POWER_ consumption. So some chips
- * do not set it.
- */
-#define MX23_BP_GPMI_CTRL0_LOCK_CS 22
-#define MX28_BP_GPMI_CTRL0_LOCK_CS 27
-#define LOCK_CS_ENABLE 0x1
-#define BF_GPMI_CTRL0_LOCK_CS(v, x) 0x0
-
-/* Difference in CS between imx23 and imx28 */
-#define BP_GPMI_CTRL0_CS 20
-#define MX23_BM_GPMI_CTRL0_CS (3 << BP_GPMI_CTRL0_CS)
-#define MX28_BM_GPMI_CTRL0_CS (7 << BP_GPMI_CTRL0_CS)
-#define BF_GPMI_CTRL0_CS(v, x) (((v) << BP_GPMI_CTRL0_CS) & \
- (GPMI_IS_MX23((x)) \
- ? MX23_BM_GPMI_CTRL0_CS \
- : MX28_BM_GPMI_CTRL0_CS))
-
-#define BP_GPMI_CTRL0_ADDRESS 17
-#define BM_GPMI_CTRL0_ADDRESS (3 << BP_GPMI_CTRL0_ADDRESS)
-#define BF_GPMI_CTRL0_ADDRESS(v) \
- (((v) << BP_GPMI_CTRL0_ADDRESS) & BM_GPMI_CTRL0_ADDRESS)
-#define BV_GPMI_CTRL0_ADDRESS__NAND_DATA 0x0
-#define BV_GPMI_CTRL0_ADDRESS__NAND_CLE 0x1
-#define BV_GPMI_CTRL0_ADDRESS__NAND_ALE 0x2
-
-#define BM_GPMI_CTRL0_ADDRESS_INCREMENT (1 << 16)
-#define BV_GPMI_CTRL0_ADDRESS_INCREMENT__DISABLED 0x0
-#define BV_GPMI_CTRL0_ADDRESS_INCREMENT__ENABLED 0x1
-
-#define BP_GPMI_CTRL0_XFER_COUNT 0
-#define BM_GPMI_CTRL0_XFER_COUNT (0xffff << BP_GPMI_CTRL0_XFER_COUNT)
-#define BF_GPMI_CTRL0_XFER_COUNT(v) \
- (((v) << BP_GPMI_CTRL0_XFER_COUNT) & BM_GPMI_CTRL0_XFER_COUNT)
-
-#define HW_GPMI_COMPARE 0x00000010
-
-#define HW_GPMI_ECCCTRL 0x00000020
-#define HW_GPMI_ECCCTRL_SET 0x00000024
-#define HW_GPMI_ECCCTRL_CLR 0x00000028
-#define HW_GPMI_ECCCTRL_TOG 0x0000002c
-
-#define BP_GPMI_ECCCTRL_ECC_CMD 13
-#define BM_GPMI_ECCCTRL_ECC_CMD (3 << BP_GPMI_ECCCTRL_ECC_CMD)
-#define BF_GPMI_ECCCTRL_ECC_CMD(v) \
- (((v) << BP_GPMI_ECCCTRL_ECC_CMD) & BM_GPMI_ECCCTRL_ECC_CMD)
-#define BV_GPMI_ECCCTRL_ECC_CMD__BCH_DECODE 0x0
-#define BV_GPMI_ECCCTRL_ECC_CMD__BCH_ENCODE 0x1
-
-#define BM_GPMI_ECCCTRL_ENABLE_ECC (1 << 12)
-#define BV_GPMI_ECCCTRL_ENABLE_ECC__ENABLE 0x1
-#define BV_GPMI_ECCCTRL_ENABLE_ECC__DISABLE 0x0
-
-#define BP_GPMI_ECCCTRL_BUFFER_MASK 0
-#define BM_GPMI_ECCCTRL_BUFFER_MASK (0x1ff << BP_GPMI_ECCCTRL_BUFFER_MASK)
-#define BF_GPMI_ECCCTRL_BUFFER_MASK(v) \
- (((v) << BP_GPMI_ECCCTRL_BUFFER_MASK) & BM_GPMI_ECCCTRL_BUFFER_MASK)
-#define BV_GPMI_ECCCTRL_BUFFER_MASK__BCH_AUXONLY 0x100
-#define BV_GPMI_ECCCTRL_BUFFER_MASK__BCH_PAGE 0x1FF
-
-#define HW_GPMI_ECCCOUNT 0x00000030
-#define HW_GPMI_PAYLOAD 0x00000040
-#define HW_GPMI_AUXILIARY 0x00000050
-#define HW_GPMI_CTRL1 0x00000060
-#define HW_GPMI_CTRL1_SET 0x00000064
-#define HW_GPMI_CTRL1_CLR 0x00000068
-#define HW_GPMI_CTRL1_TOG 0x0000006c
-
-#define BP_GPMI_CTRL1_DECOUPLE_CS 24
-#define BM_GPMI_CTRL1_DECOUPLE_CS (1 << BP_GPMI_CTRL1_DECOUPLE_CS)
-
-#define BP_GPMI_CTRL1_WRN_DLY_SEL 22
-#define BM_GPMI_CTRL1_WRN_DLY_SEL (0x3 << BP_GPMI_CTRL1_WRN_DLY_SEL)
-#define BF_GPMI_CTRL1_WRN_DLY_SEL(v) \
- (((v) << BP_GPMI_CTRL1_WRN_DLY_SEL) & BM_GPMI_CTRL1_WRN_DLY_SEL)
-#define BV_GPMI_CTRL1_WRN_DLY_SEL_4_TO_8NS 0x0
-#define BV_GPMI_CTRL1_WRN_DLY_SEL_6_TO_10NS 0x1
-#define BV_GPMI_CTRL1_WRN_DLY_SEL_7_TO_12NS 0x2
-#define BV_GPMI_CTRL1_WRN_DLY_SEL_NO_DELAY 0x3
-
-#define BM_GPMI_CTRL1_BCH_MODE (1 << 18)
-
-#define BP_GPMI_CTRL1_DLL_ENABLE 17
-#define BM_GPMI_CTRL1_DLL_ENABLE (1 << BP_GPMI_CTRL1_DLL_ENABLE)
-
-#define BP_GPMI_CTRL1_HALF_PERIOD 16
-#define BM_GPMI_CTRL1_HALF_PERIOD (1 << BP_GPMI_CTRL1_HALF_PERIOD)
-
-#define BP_GPMI_CTRL1_RDN_DELAY 12
-#define BM_GPMI_CTRL1_RDN_DELAY (0xf << BP_GPMI_CTRL1_RDN_DELAY)
-#define BF_GPMI_CTRL1_RDN_DELAY(v) \
- (((v) << BP_GPMI_CTRL1_RDN_DELAY) & BM_GPMI_CTRL1_RDN_DELAY)
-
-#define BM_GPMI_CTRL1_DEV_RESET (1 << 3)
-#define BV_GPMI_CTRL1_DEV_RESET__ENABLED 0x0
-#define BV_GPMI_CTRL1_DEV_RESET__DISABLED 0x1
-
-#define BM_GPMI_CTRL1_ATA_IRQRDY_POLARITY (1 << 2)
-#define BV_GPMI_CTRL1_ATA_IRQRDY_POLARITY__ACTIVELOW 0x0
-#define BV_GPMI_CTRL1_ATA_IRQRDY_POLARITY__ACTIVEHIGH 0x1
-
-#define BM_GPMI_CTRL1_CAMERA_MODE (1 << 1)
-#define BV_GPMI_CTRL1_GPMI_MODE__NAND 0x0
-#define BV_GPMI_CTRL1_GPMI_MODE__ATA 0x1
-
-#define BM_GPMI_CTRL1_GPMI_MODE (1 << 0)
-
-#define HW_GPMI_TIMING0 0x00000070
-
-#define BP_GPMI_TIMING0_ADDRESS_SETUP 16
-#define BM_GPMI_TIMING0_ADDRESS_SETUP (0xff << BP_GPMI_TIMING0_ADDRESS_SETUP)
-#define BF_GPMI_TIMING0_ADDRESS_SETUP(v) \
- (((v) << BP_GPMI_TIMING0_ADDRESS_SETUP) & BM_GPMI_TIMING0_ADDRESS_SETUP)
-
-#define BP_GPMI_TIMING0_DATA_HOLD 8
-#define BM_GPMI_TIMING0_DATA_HOLD (0xff << BP_GPMI_TIMING0_DATA_HOLD)
-#define BF_GPMI_TIMING0_DATA_HOLD(v) \
- (((v) << BP_GPMI_TIMING0_DATA_HOLD) & BM_GPMI_TIMING0_DATA_HOLD)
-
-#define BP_GPMI_TIMING0_DATA_SETUP 0
-#define BM_GPMI_TIMING0_DATA_SETUP (0xff << BP_GPMI_TIMING0_DATA_SETUP)
-#define BF_GPMI_TIMING0_DATA_SETUP(v) \
- (((v) << BP_GPMI_TIMING0_DATA_SETUP) & BM_GPMI_TIMING0_DATA_SETUP)
-
-#define HW_GPMI_TIMING1 0x00000080
-#define BP_GPMI_TIMING1_BUSY_TIMEOUT 16
-#define BM_GPMI_TIMING1_BUSY_TIMEOUT (0xffff << BP_GPMI_TIMING1_BUSY_TIMEOUT)
-#define BF_GPMI_TIMING1_BUSY_TIMEOUT(v) \
- (((v) << BP_GPMI_TIMING1_BUSY_TIMEOUT) & BM_GPMI_TIMING1_BUSY_TIMEOUT)
-
-#define HW_GPMI_TIMING2 0x00000090
-#define HW_GPMI_DATA 0x000000a0
-
-/* MX28 uses this to detect READY. */
-#define HW_GPMI_STAT 0x000000b0
-#define MX28_BP_GPMI_STAT_READY_BUSY 24
-#define MX28_BM_GPMI_STAT_READY_BUSY (0xff << MX28_BP_GPMI_STAT_READY_BUSY)
-#define MX28_BF_GPMI_STAT_READY_BUSY(v) \
- (((v) << MX28_BP_GPMI_STAT_READY_BUSY) & MX28_BM_GPMI_STAT_READY_BUSY)
-
-/* MX23 uses this to detect READY. */
-#define HW_GPMI_DEBUG 0x000000c0
-#define MX23_BP_GPMI_DEBUG_READY0 28
-#define MX23_BM_GPMI_DEBUG_READY0 (1 << MX23_BP_GPMI_DEBUG_READY0)
-#endif