summaryrefslogtreecommitdiff
path: root/drivers/mtd/nand/raw
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd/nand/raw')
-rw-r--r--drivers/mtd/nand/raw/Kconfig31
-rw-r--r--drivers/mtd/nand/raw/Makefile4
-rw-r--r--drivers/mtd/nand/raw/cortina_nand.c11
-rw-r--r--drivers/mtd/nand/raw/denali.c10
-rw-r--r--drivers/mtd/nand/raw/lpc32xx_nand_slc.c587
-rw-r--r--drivers/mtd/nand/raw/mxic_nand.c602
-rw-r--r--drivers/mtd/nand/raw/mxs_nand.c6
-rw-r--r--drivers/mtd/nand/raw/octeontx_bch.c422
-rw-r--r--drivers/mtd/nand/raw/octeontx_bch.h131
-rw-r--r--drivers/mtd/nand/raw/octeontx_bch_regs.h167
-rw-r--r--drivers/mtd/nand/raw/octeontx_nand.c2254
-rw-r--r--drivers/mtd/nand/raw/pxa3xx_nand.c1
-rw-r--r--drivers/mtd/nand/raw/stm32_fmc2_nand.c6
-rw-r--r--drivers/mtd/nand/raw/sunxi_nand.c17
14 files changed, 33 insertions, 4216 deletions
diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig
index adb271dfb8f..9c8a32bb0a8 100644
--- a/drivers/mtd/nand/raw/Kconfig
+++ b/drivers/mtd/nand/raw/Kconfig
@@ -261,11 +261,6 @@ config NAND_LPC32XX_MLC
help
Enable the LPC32XX MLC NAND controller.
-config NAND_LPC32XX_SLC
- bool "Support LPC32XX_SLC controller"
- help
- Enable the LPC32XX SLC NAND controller.
-
config NAND_OMAP_GPMC
bool "Support OMAP GPMC NAND controller"
depends on ARCH_OMAP2PLUS || ARCH_KEYSTONE || ARCH_K3
@@ -556,12 +551,6 @@ config NAND_MXS_USE_MINIMUM_ECC
endif
-config NAND_MXIC
- bool "Macronix raw NAND controller"
- select SYS_NAND_SELF_INIT
- help
- This selects the Macronix raw NAND controller driver.
-
config NAND_ZYNQ
bool "Support for Zynq Nand controller"
select SPL_SYS_NAND_SELF_INIT
@@ -579,22 +568,6 @@ config NAND_ZYNQ_USE_BOOTLOADER1_TIMINGS
This flag prevent U-Boot reconfigure NAND flash controller and reuse
the NAND timing from 1st stage bootloader.
-config NAND_OCTEONTX
- bool "Support for OcteonTX NAND controller"
- select SYS_NAND_SELF_INIT
- imply CMD_NAND
- help
- This enables Nand flash controller hardware found on the OcteonTX
- processors.
-
-config NAND_OCTEONTX_HW_ECC
- bool "Support Hardware ECC for OcteonTX NAND controller"
- depends on NAND_OCTEONTX
- default y
- help
- This enables Hardware BCH engine found on the OcteonTX processors to
- support ECC for NAND flash controller.
-
config NAND_STM32_FMC2
bool "Support for NAND controller on STM32MP SoCs"
depends on ARCH_STM32MP
@@ -684,7 +657,7 @@ config SYS_NAND_ONFI_DETECTION
config SYS_NAND_PAGE_SIZE
hex "NAND chip page size"
- depends on ARCH_SUNXI || NAND_OMAP_GPMC || NAND_LPC32XX_SLC || \
+ depends on ARCH_SUNXI || NAND_OMAP_GPMC || \
SPL_NAND_SIMPLE || (NAND_MXC && SPL_NAND_SUPPORT) || \
MVEBU_SPL_BOOT_DEVICE_NAND || \
(NAND_ATMEL && SPL_NAND_SUPPORT) || \
@@ -696,7 +669,7 @@ config SYS_NAND_PAGE_SIZE
config SYS_NAND_OOBSIZE
hex "NAND chip OOB size"
- depends on ARCH_SUNXI || NAND_OMAP_GPMC || NAND_LPC32XX_SLC || \
+ depends on ARCH_SUNXI || NAND_OMAP_GPMC || \
SPL_NAND_SIMPLE || (NAND_MXC && SPL_NAND_SUPPORT) || \
(NAND_ATMEL && SPL_NAND_SUPPORT) || SPL_GENERATE_ATMEL_PMECC_HEADER
depends on !NAND_MXS && !NAND_DENALI_DT && !NAND_LPC32XX_MLC
diff --git a/drivers/mtd/nand/raw/Makefile b/drivers/mtd/nand/raw/Makefile
index 34cba77046a..76546a6287b 100644
--- a/drivers/mtd/nand/raw/Makefile
+++ b/drivers/mtd/nand/raw/Makefile
@@ -61,21 +61,17 @@ obj-$(CONFIG_NAND_FSL_IFC) += fsl_ifc_nand.o
obj-$(CONFIG_NAND_KIRKWOOD) += kirkwood_nand.o
obj-$(CONFIG_NAND_KMETER1) += kmeter1_nand.o
obj-$(CONFIG_NAND_LPC32XX_MLC) += lpc32xx_nand_mlc.o
-obj-$(CONFIG_NAND_LPC32XX_SLC) += lpc32xx_nand_slc.o
obj-$(CONFIG_NAND_VF610_NFC) += vf610_nfc.o
obj-$(CONFIG_NAND_MESON) += meson_nand.o
obj-$(CONFIG_NAND_MXC) += mxc_nand.o
obj-$(CONFIG_NAND_MXS) += mxs_nand.o
obj-$(CONFIG_NAND_MXS_DT) += mxs_nand_dt.o
-obj-$(CONFIG_NAND_OCTEONTX) += octeontx_nand.o
-obj-$(CONFIG_NAND_OCTEONTX_HW_ECC) += octeontx_bch.o
obj-$(CONFIG_NAND_PXA3XX) += pxa3xx_nand.o
obj-$(CONFIG_TEGRA_NAND) += tegra_nand.o
obj-$(CONFIG_NAND_OMAP_GPMC) += omap_gpmc.o
obj-$(CONFIG_NAND_OMAP_ELM) += omap_elm.o
obj-$(CONFIG_NAND_SANDBOX) += sand_nand.o
obj-$(CONFIG_NAND_SUNXI) += sunxi_nand.o
-obj-$(CONFIG_NAND_MXIC) += mxic_nand.o
obj-$(CONFIG_NAND_ZYNQ) += zynq_nand.o
obj-$(CONFIG_NAND_STM32_FMC2) += stm32_fmc2_nand.o
obj-$(CONFIG_CORTINA_NAND) += cortina_nand.o
diff --git a/drivers/mtd/nand/raw/cortina_nand.c b/drivers/mtd/nand/raw/cortina_nand.c
index 06918a46e93..a27a6994f56 100644
--- a/drivers/mtd/nand/raw/cortina_nand.c
+++ b/drivers/mtd/nand/raw/cortina_nand.c
@@ -186,14 +186,13 @@ int init_nand_dma(struct nand_chip *nand)
info->tx_desc = malloc_cache_aligned((sizeof(struct tx_descriptor_t) *
CA_DMA_DESC_NUM));
- info->rx_desc = malloc_cache_aligned((sizeof(struct rx_descriptor_t) *
- CA_DMA_DESC_NUM));
-
- if (!info->rx_desc && info->tx_desc) {
+ if (!info->tx_desc) {
printf("Fail to alloc DMA descript!\n");
- kfree(info->tx_desc);
return -ENOMEM;
- } else if (info->rx_desc && !info->tx_desc) {
+ }
+ info->rx_desc = malloc_cache_aligned((sizeof(struct rx_descriptor_t) *
+ CA_DMA_DESC_NUM));
+ if (!info->rx_desc) {
printf("Fail to alloc DMA descript!\n");
kfree(info->tx_desc);
return -ENOMEM;
diff --git a/drivers/mtd/nand/raw/denali.c b/drivers/mtd/nand/raw/denali.c
index b2401116689..39cb641e0b3 100644
--- a/drivers/mtd/nand/raw/denali.c
+++ b/drivers/mtd/nand/raw/denali.c
@@ -173,13 +173,9 @@ static uint32_t denali_wait_for_irq(struct denali_nand_info *denali,
time_left--;
}
- if (!time_left) {
- dev_err(denali->dev, "timeout while waiting for irq 0x%x\n",
- irq_mask);
- return 0;
- }
-
- return denali->irq_status;
+ dev_err(denali->dev, "timeout while waiting for irq 0x%x\n",
+ irq_mask);
+ return 0;
}
static uint32_t denali_check_irq(struct denali_nand_info *denali)
diff --git a/drivers/mtd/nand/raw/lpc32xx_nand_slc.c b/drivers/mtd/nand/raw/lpc32xx_nand_slc.c
deleted file mode 100644
index 109c31fb4d1..00000000000
--- a/drivers/mtd/nand/raw/lpc32xx_nand_slc.c
+++ /dev/null
@@ -1,587 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * LPC32xx SLC NAND flash controller driver
- *
- * (C) Copyright 2015-2018 Vladimir Zapolskiy <vz@mleia.com>
- * Copyright (c) 2015 Tyco Fire Protection Products.
- *
- * Hardware ECC support original source code
- * Copyright (C) 2008 by NXP Semiconductors
- * Author: Kevin Wells
- */
-
-#include <config.h>
-#include <log.h>
-#include <nand.h>
-#include <linux/bug.h>
-#include <linux/mtd/nand_ecc.h>
-#include <linux/mtd/rawnand.h>
-#include <linux/errno.h>
-#include <asm/io.h>
-#include <asm/arch/config.h>
-#include <asm/arch/clk.h>
-#include <asm/arch/sys_proto.h>
-#include <asm/arch/dma.h>
-#include <asm/arch/cpu.h>
-#include <linux/printk.h>
-
-struct lpc32xx_nand_slc_regs {
- u32 data;
- u32 addr;
- u32 cmd;
- u32 stop;
- u32 ctrl;
- u32 cfg;
- u32 stat;
- u32 int_stat;
- u32 ien;
- u32 isr;
- u32 icr;
- u32 tac;
- u32 tc;
- u32 ecc;
- u32 dma_data;
-};
-
-/* CFG register */
-#define CFG_CE_LOW (1 << 5)
-#define CFG_DMA_ECC (1 << 4) /* Enable DMA ECC bit */
-#define CFG_ECC_EN (1 << 3) /* ECC enable bit */
-#define CFG_DMA_BURST (1 << 2) /* DMA burst bit */
-#define CFG_DMA_DIR (1 << 1) /* DMA write(0)/read(1) bit */
-
-/* CTRL register */
-#define CTRL_SW_RESET (1 << 2)
-#define CTRL_ECC_CLEAR (1 << 1) /* Reset ECC bit */
-#define CTRL_DMA_START (1 << 0) /* Start DMA channel bit */
-
-/* STAT register */
-#define STAT_DMA_FIFO (1 << 2) /* DMA FIFO has data bit */
-#define STAT_NAND_READY (1 << 0)
-
-/* INT_STAT register */
-#define INT_STAT_TC (1 << 1)
-#define INT_STAT_RDY (1 << 0)
-
-/* TAC register bits, be aware of overflows */
-#define TAC_W_RDY(n) (max_t(uint32_t, (n), 0xF) << 28)
-#define TAC_W_WIDTH(n) (max_t(uint32_t, (n), 0xF) << 24)
-#define TAC_W_HOLD(n) (max_t(uint32_t, (n), 0xF) << 20)
-#define TAC_W_SETUP(n) (max_t(uint32_t, (n), 0xF) << 16)
-#define TAC_R_RDY(n) (max_t(uint32_t, (n), 0xF) << 12)
-#define TAC_R_WIDTH(n) (max_t(uint32_t, (n), 0xF) << 8)
-#define TAC_R_HOLD(n) (max_t(uint32_t, (n), 0xF) << 4)
-#define TAC_R_SETUP(n) (max_t(uint32_t, (n), 0xF) << 0)
-
-/* NAND ECC Layout for small page NAND devices
- * Note: For large page devices, the default layouts are used. */
-static struct nand_ecclayout lpc32xx_nand_oob_16 = {
- .eccbytes = 6,
- .eccpos = { 10, 11, 12, 13, 14, 15, },
- .oobfree = {
- { .offset = 0, .length = 4, },
- { .offset = 6, .length = 4, },
- }
-};
-
-#if defined(CONFIG_DMA_LPC32XX) && !defined(CONFIG_XPL_BUILD)
-#define ECCSTEPS (CONFIG_SYS_NAND_PAGE_SIZE / CFG_SYS_NAND_ECCSIZE)
-
-/*
- * DMA Descriptors
- * For Large Block: 17 descriptors = ((16 Data and ECC Read) + 1 Spare Area)
- * For Small Block: 5 descriptors = ((4 Data and ECC Read) + 1 Spare Area)
- */
-static struct lpc32xx_dmac_ll dmalist[ECCSTEPS * 2 + 1];
-static u32 ecc_buffer[8]; /* MAX ECC size */
-static unsigned int dmachan = (unsigned int)-1; /* Invalid channel */
-
-/*
- * Helper macro for the DMA client (i.e. NAND SLC):
- * - to write the next DMA linked list item address
- * (see arch/include/asm/arch-lpc32xx/dma.h).
- * - to assign the DMA data register to DMA source or destination address.
- * - to assign the ECC register to DMA source or destination address.
- */
-#define lpc32xx_dmac_next_lli(x) ((u32)x)
-#define lpc32xx_dmac_set_dma_data() ((u32)&lpc32xx_nand_slc_regs->dma_data)
-#define lpc32xx_dmac_set_ecc() ((u32)&lpc32xx_nand_slc_regs->ecc)
-#endif
-
-static struct lpc32xx_nand_slc_regs __iomem *lpc32xx_nand_slc_regs
- = (struct lpc32xx_nand_slc_regs __iomem *)SLC_NAND_BASE;
-
-static void lpc32xx_nand_init(void)
-{
- uint32_t hclk = get_hclk_clk_rate();
-
- /* Reset SLC NAND controller */
- writel(CTRL_SW_RESET, &lpc32xx_nand_slc_regs->ctrl);
-
- /* 8-bit bus, no DMA, no ECC, ordinary CE signal */
- writel(0, &lpc32xx_nand_slc_regs->cfg);
-
- /* Interrupts disabled and cleared */
- writel(0, &lpc32xx_nand_slc_regs->ien);
- writel(INT_STAT_TC | INT_STAT_RDY,
- &lpc32xx_nand_slc_regs->icr);
-
- /* Configure NAND flash timings */
- writel(TAC_W_RDY(CFG_LPC32XX_NAND_SLC_WDR_CLKS) |
- TAC_W_WIDTH(hclk / CFG_LPC32XX_NAND_SLC_WWIDTH) |
- TAC_W_HOLD(hclk / CFG_LPC32XX_NAND_SLC_WHOLD) |
- TAC_W_SETUP(hclk / CFG_LPC32XX_NAND_SLC_WSETUP) |
- TAC_R_RDY(CFG_LPC32XX_NAND_SLC_RDR_CLKS) |
- TAC_R_WIDTH(hclk / CFG_LPC32XX_NAND_SLC_RWIDTH) |
- TAC_R_HOLD(hclk / CFG_LPC32XX_NAND_SLC_RHOLD) |
- TAC_R_SETUP(hclk / CFG_LPC32XX_NAND_SLC_RSETUP),
- &lpc32xx_nand_slc_regs->tac);
-}
-
-static void lpc32xx_nand_cmd_ctrl(struct mtd_info *mtd,
- int cmd, unsigned int ctrl)
-{
- debug("ctrl: 0x%08x, cmd: 0x%08x\n", ctrl, cmd);
-
- if (ctrl & NAND_NCE)
- setbits_le32(&lpc32xx_nand_slc_regs->cfg, CFG_CE_LOW);
- else
- clrbits_le32(&lpc32xx_nand_slc_regs->cfg, CFG_CE_LOW);
-
- if (cmd == NAND_CMD_NONE)
- return;
-
- if (ctrl & NAND_CLE)
- writel(cmd & 0xFF, &lpc32xx_nand_slc_regs->cmd);
- else if (ctrl & NAND_ALE)
- writel(cmd & 0xFF, &lpc32xx_nand_slc_regs->addr);
-}
-
-static int lpc32xx_nand_dev_ready(struct mtd_info *mtd)
-{
- return readl(&lpc32xx_nand_slc_regs->stat) & STAT_NAND_READY;
-}
-
-#if defined(CONFIG_DMA_LPC32XX) && !defined(CONFIG_XPL_BUILD)
-/*
- * Prepares DMA descriptors for NAND RD/WR operations
- * If the size is < 256 Bytes then it is assumed to be
- * an OOB transfer
- */
-static void lpc32xx_nand_dma_configure(struct nand_chip *chip,
- const u8 *buffer, int size,
- int read)
-{
- u32 i, dmasrc, ctrl, ecc_ctrl, oob_ctrl, dmadst;
- struct lpc32xx_dmac_ll *dmalist_cur;
- struct lpc32xx_dmac_ll *dmalist_cur_ecc;
-
- /*
- * CTRL descriptor entry for reading ECC
- * Copy Multiple times to sync DMA with Flash Controller
- */
- ecc_ctrl = 0x5 |
- DMAC_CHAN_SRC_BURST_1 |
- DMAC_CHAN_DEST_BURST_1 |
- DMAC_CHAN_SRC_WIDTH_32 |
- DMAC_CHAN_DEST_WIDTH_32 |
- DMAC_CHAN_DEST_AHB1;
-
- /* CTRL descriptor entry for reading/writing Data */
- ctrl = (CFG_SYS_NAND_ECCSIZE / 4) |
- DMAC_CHAN_SRC_BURST_4 |
- DMAC_CHAN_DEST_BURST_4 |
- DMAC_CHAN_SRC_WIDTH_32 |
- DMAC_CHAN_DEST_WIDTH_32 |
- DMAC_CHAN_DEST_AHB1;
-
- /* CTRL descriptor entry for reading/writing Spare Area */
- oob_ctrl = (CONFIG_SYS_NAND_OOBSIZE / 4) |
- DMAC_CHAN_SRC_BURST_4 |
- DMAC_CHAN_DEST_BURST_4 |
- DMAC_CHAN_SRC_WIDTH_32 |
- DMAC_CHAN_DEST_WIDTH_32 |
- DMAC_CHAN_DEST_AHB1;
-
- if (read) {
- dmasrc = lpc32xx_dmac_set_dma_data();
- dmadst = (u32)buffer;
- ctrl |= DMAC_CHAN_DEST_AUTOINC;
- } else {
- dmadst = lpc32xx_dmac_set_dma_data();
- dmasrc = (u32)buffer;
- ctrl |= DMAC_CHAN_SRC_AUTOINC;
- }
-
- /*
- * Write Operation Sequence for Small Block NAND
- * ----------------------------------------------------------
- * 1. X'fer 256 bytes of data from Memory to Flash.
- * 2. Copy generated ECC data from Register to Spare Area
- * 3. X'fer next 256 bytes of data from Memory to Flash.
- * 4. Copy generated ECC data from Register to Spare Area.
- * 5. X'fer 16 byets of Spare area from Memory to Flash.
- * Read Operation Sequence for Small Block NAND
- * ----------------------------------------------------------
- * 1. X'fer 256 bytes of data from Flash to Memory.
- * 2. Copy generated ECC data from Register to ECC calc Buffer.
- * 3. X'fer next 256 bytes of data from Flash to Memory.
- * 4. Copy generated ECC data from Register to ECC calc Buffer.
- * 5. X'fer 16 bytes of Spare area from Flash to Memory.
- * Write Operation Sequence for Large Block NAND
- * ----------------------------------------------------------
- * 1. Steps(1-4) of Write Operations repeate for four times
- * which generates 16 DMA descriptors to X'fer 2048 bytes of
- * data & 32 bytes of ECC data.
- * 2. X'fer 64 bytes of Spare area from Memory to Flash.
- * Read Operation Sequence for Large Block NAND
- * ----------------------------------------------------------
- * 1. Steps(1-4) of Read Operations repeate for four times
- * which generates 16 DMA descriptors to X'fer 2048 bytes of
- * data & 32 bytes of ECC data.
- * 2. X'fer 64 bytes of Spare area from Flash to Memory.
- */
-
- for (i = 0; i < size/CFG_SYS_NAND_ECCSIZE; i++) {
- dmalist_cur = &dmalist[i * 2];
- dmalist_cur_ecc = &dmalist[(i * 2) + 1];
-
- dmalist_cur->dma_src = (read ? (dmasrc) : (dmasrc + (i*256)));
- dmalist_cur->dma_dest = (read ? (dmadst + (i*256)) : dmadst);
- dmalist_cur->next_lli = lpc32xx_dmac_next_lli(dmalist_cur_ecc);
- dmalist_cur->next_ctrl = ctrl;
-
- dmalist_cur_ecc->dma_src = lpc32xx_dmac_set_ecc();
- dmalist_cur_ecc->dma_dest = (u32)&ecc_buffer[i];
- dmalist_cur_ecc->next_lli =
- lpc32xx_dmac_next_lli(&dmalist[(i * 2) + 2]);
- dmalist_cur_ecc->next_ctrl = ecc_ctrl;
- }
-
- if (i) { /* Data only transfer */
- dmalist_cur_ecc = &dmalist[(i * 2) - 1];
- dmalist_cur_ecc->next_lli = 0;
- dmalist_cur_ecc->next_ctrl |= DMAC_CHAN_INT_TC_EN;
- return;
- }
-
- /* OOB only transfer */
- if (read) {
- dmasrc = lpc32xx_dmac_set_dma_data();
- dmadst = (u32)buffer;
- oob_ctrl |= DMAC_CHAN_DEST_AUTOINC;
- } else {
- dmadst = lpc32xx_dmac_set_dma_data();
- dmasrc = (u32)buffer;
- oob_ctrl |= DMAC_CHAN_SRC_AUTOINC;
- }
-
- /* Read/ Write Spare Area Data To/From Flash */
- dmalist_cur = &dmalist[i * 2];
- dmalist_cur->dma_src = dmasrc;
- dmalist_cur->dma_dest = dmadst;
- dmalist_cur->next_lli = 0;
- dmalist_cur->next_ctrl = (oob_ctrl | DMAC_CHAN_INT_TC_EN);
-}
-
-static void lpc32xx_nand_xfer(struct mtd_info *mtd, const u8 *buf,
- int len, int read)
-{
- struct nand_chip *chip = mtd_to_nand(mtd);
- u32 config;
- int ret;
-
- /* DMA Channel Configuration */
- config = (read ? DMAC_CHAN_FLOW_D_P2M : DMAC_CHAN_FLOW_D_M2P) |
- (read ? DMAC_DEST_PERIP(0) : DMAC_DEST_PERIP(DMA_PERID_NAND1)) |
- (read ? DMAC_SRC_PERIP(DMA_PERID_NAND1) : DMAC_SRC_PERIP(0)) |
- DMAC_CHAN_ENABLE;
-
- /* Prepare DMA descriptors */
- lpc32xx_nand_dma_configure(chip, buf, len, read);
-
- /* Setup SLC controller and start transfer */
- if (read)
- setbits_le32(&lpc32xx_nand_slc_regs->cfg, CFG_DMA_DIR);
- else /* NAND_ECC_WRITE */
- clrbits_le32(&lpc32xx_nand_slc_regs->cfg, CFG_DMA_DIR);
- setbits_le32(&lpc32xx_nand_slc_regs->cfg, CFG_DMA_BURST);
-
- /* Write length for new transfers */
- if (!((readl(&lpc32xx_nand_slc_regs->stat) & STAT_DMA_FIFO) |
- readl(&lpc32xx_nand_slc_regs->tc))) {
- int tmp = (len != mtd->oobsize) ? mtd->oobsize : 0;
- writel(len + tmp, &lpc32xx_nand_slc_regs->tc);
- }
-
- setbits_le32(&lpc32xx_nand_slc_regs->ctrl, CTRL_DMA_START);
-
- /* Start DMA transfers */
- ret = lpc32xx_dma_start_xfer(dmachan, dmalist, config);
- if (unlikely(ret < 0))
- BUG();
-
- /* Wait for NAND to be ready */
- while (!lpc32xx_nand_dev_ready(mtd))
- ;
-
- /* Wait till DMA transfer is DONE */
- if (lpc32xx_dma_wait_status(dmachan))
- pr_err("NAND DMA transfer error!\r\n");
-
- /* Stop DMA & HW ECC */
- clrbits_le32(&lpc32xx_nand_slc_regs->ctrl, CTRL_DMA_START);
- clrbits_le32(&lpc32xx_nand_slc_regs->cfg,
- CFG_DMA_DIR | CFG_DMA_BURST | CFG_ECC_EN | CFG_DMA_ECC);
-}
-
-static u32 slc_ecc_copy_to_buffer(u8 *spare, const u32 *ecc, int count)
-{
- int i;
- for (i = 0; i < (count * CFG_SYS_NAND_ECCBYTES);
- i += CFG_SYS_NAND_ECCBYTES) {
- u32 ce = ecc[i / CFG_SYS_NAND_ECCBYTES];
- ce = ~(ce << 2) & 0xFFFFFF;
- spare[i+2] = (u8)(ce & 0xFF); ce >>= 8;
- spare[i+1] = (u8)(ce & 0xFF); ce >>= 8;
- spare[i] = (u8)(ce & 0xFF);
- }
- return 0;
-}
-
-static int lpc32xx_ecc_calculate(struct mtd_info *mtd, const uint8_t *dat,
- uint8_t *ecc_code)
-{
- return slc_ecc_copy_to_buffer(ecc_code, ecc_buffer, ECCSTEPS);
-}
-
-/*
- * Enables and prepares SLC NAND controller
- * for doing data transfers with H/W ECC enabled.
- */
-static void lpc32xx_hwecc_enable(struct mtd_info *mtd, int mode)
-{
- /* Clear ECC */
- writel(CTRL_ECC_CLEAR, &lpc32xx_nand_slc_regs->ctrl);
-
- /* Setup SLC controller for H/W ECC operations */
- setbits_le32(&lpc32xx_nand_slc_regs->cfg, CFG_ECC_EN | CFG_DMA_ECC);
-}
-
-/*
- * lpc32xx_correct_data - [NAND Interface] Detect and correct bit error(s)
- * mtd: MTD block structure
- * dat: raw data read from the chip
- * read_ecc: ECC from the chip
- * calc_ecc: the ECC calculated from raw data
- *
- * Detect and correct a 1 bit error for 256 byte block
- */
-int lpc32xx_correct_data(struct mtd_info *mtd, u_char *dat,
- u_char *read_ecc, u_char *calc_ecc)
-{
- unsigned int i;
- int ret1, ret2 = 0;
- u_char *r = read_ecc;
- u_char *c = calc_ecc;
- u16 data_offset = 0;
-
- for (i = 0 ; i < ECCSTEPS ; i++) {
- r += CFG_SYS_NAND_ECCBYTES;
- c += CFG_SYS_NAND_ECCBYTES;
- data_offset += CFG_SYS_NAND_ECCSIZE;
-
- ret1 = nand_correct_data(mtd, dat + data_offset, r, c);
- if (ret1 < 0)
- return -EBADMSG;
- else
- ret2 += ret1;
- }
-
- return ret2;
-}
-
-static void lpc32xx_dma_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
-{
- lpc32xx_nand_xfer(mtd, buf, len, 1);
-}
-
-static void lpc32xx_dma_write_buf(struct mtd_info *mtd, const uint8_t *buf,
- int len)
-{
- lpc32xx_nand_xfer(mtd, buf, len, 0);
-}
-
-/* Reuse the logic from "nand_read_page_hwecc()" */
-static int lpc32xx_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
- uint8_t *buf, int oob_required, int page)
-{
- int i;
- int stat;
- uint8_t *p = buf;
- uint8_t *ecc_calc = chip->buffers->ecccalc;
- uint8_t *ecc_code = chip->buffers->ecccode;
- uint32_t *eccpos = chip->ecc.layout->eccpos;
- unsigned int max_bitflips = 0;
-
- /*
- * As per the "LPC32x0 and LPC32x0/01 User manual" table 173 notes
- * and section 9.7, the NAND SLC & DMA allowed single DMA transaction
- * of a page size using DMA controller scatter/gather mode through
- * linked list; the ECC read is done without any software intervention.
- */
-
- lpc32xx_hwecc_enable(mtd, NAND_ECC_READ);
- lpc32xx_dma_read_buf(mtd, p, chip->ecc.size * chip->ecc.steps);
- lpc32xx_ecc_calculate(mtd, p, &ecc_calc[0]);
- lpc32xx_dma_read_buf(mtd, chip->oob_poi, mtd->oobsize);
-
- for (i = 0; i < chip->ecc.total; i++)
- ecc_code[i] = chip->oob_poi[eccpos[i]];
-
- stat = chip->ecc.correct(mtd, p, &ecc_code[0], &ecc_calc[0]);
- if (stat < 0)
- mtd->ecc_stats.failed++;
- else {
- mtd->ecc_stats.corrected += stat;
- max_bitflips = max_t(unsigned int, max_bitflips, stat);
- }
-
- return max_bitflips;
-}
-
-/* Reuse the logic from "nand_write_page_hwecc()" */
-static int lpc32xx_write_page_hwecc(struct mtd_info *mtd,
- struct nand_chip *chip,
- const uint8_t *buf, int oob_required,
- int page)
-{
- int i;
- uint8_t *ecc_calc = chip->buffers->ecccalc;
- const uint8_t *p = buf;
- uint32_t *eccpos = chip->ecc.layout->eccpos;
-
- /*
- * As per the "LPC32x0 and LPC32x0/01 User manual" table 173 notes
- * and section 9.7, the NAND SLC & DMA allowed single DMA transaction
- * of a page size using DMA controller scatter/gather mode through
- * linked list; the ECC read is done without any software intervention.
- */
-
- lpc32xx_hwecc_enable(mtd, NAND_ECC_WRITE);
- lpc32xx_dma_write_buf(mtd, p, chip->ecc.size * chip->ecc.steps);
- lpc32xx_ecc_calculate(mtd, p, &ecc_calc[0]);
-
- for (i = 0; i < chip->ecc.total; i++)
- chip->oob_poi[eccpos[i]] = ecc_calc[i];
-
- lpc32xx_dma_write_buf(mtd, chip->oob_poi, mtd->oobsize);
-
- return 0;
-}
-#else
-static void lpc32xx_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
-{
- while (len-- > 0)
- *buf++ = readl(&lpc32xx_nand_slc_regs->data);
-}
-
-static void lpc32xx_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
-{
- while (len-- > 0)
- writel(*buf++, &lpc32xx_nand_slc_regs->data);
-}
-#endif
-
-static uint8_t lpc32xx_read_byte(struct mtd_info *mtd)
-{
- return readl(&lpc32xx_nand_slc_regs->data);
-}
-
-static void lpc32xx_write_byte(struct mtd_info *mtd, uint8_t byte)
-{
- writel(byte, &lpc32xx_nand_slc_regs->data);
-}
-
-/*
- * LPC32xx has only one SLC NAND controller, don't utilize
- * CONFIG_SYS_NAND_SELF_INIT to be able to reuse this function
- * both in SPL NAND and U-Boot images.
- */
-int board_nand_init(struct nand_chip *lpc32xx_chip)
-{
-#if defined(CONFIG_DMA_LPC32XX) && !defined(CONFIG_XPL_BUILD)
- int ret;
-
- /* Acquire a channel for our use */
- ret = lpc32xx_dma_get_channel();
- if (unlikely(ret < 0)) {
- pr_info("Unable to get free DMA channel for NAND transfers\n");
- return -1;
- }
- dmachan = (unsigned int)ret;
-#endif
-
- lpc32xx_chip->cmd_ctrl = lpc32xx_nand_cmd_ctrl;
- lpc32xx_chip->dev_ready = lpc32xx_nand_dev_ready;
-
- /*
- * The implementation of these functions is quite common, but
- * they MUST be defined, because access to data register
- * is strictly 32-bit aligned.
- */
- lpc32xx_chip->read_byte = lpc32xx_read_byte;
- lpc32xx_chip->write_byte = lpc32xx_write_byte;
-
-#if defined(CONFIG_DMA_LPC32XX) && !defined(CONFIG_XPL_BUILD)
- /* Hardware ECC calculation is supported when DMA driver is selected */
- lpc32xx_chip->ecc.mode = NAND_ECC_HW;
-
- lpc32xx_chip->read_buf = lpc32xx_dma_read_buf;
- lpc32xx_chip->write_buf = lpc32xx_dma_write_buf;
-
- lpc32xx_chip->ecc.calculate = lpc32xx_ecc_calculate;
- lpc32xx_chip->ecc.correct = lpc32xx_correct_data;
- lpc32xx_chip->ecc.hwctl = lpc32xx_hwecc_enable;
- lpc32xx_chip->chip_delay = 2000;
-
- lpc32xx_chip->ecc.read_page = lpc32xx_read_page_hwecc;
- lpc32xx_chip->ecc.write_page = lpc32xx_write_page_hwecc;
- lpc32xx_chip->options |= NAND_NO_SUBPAGE_WRITE;
-#else
- /*
- * Hardware ECC calculation is not supported by the driver,
- * because it requires DMA support, see LPC32x0 User Manual,
- * note after SLC_ECC register description (UM10326, p.198)
- */
- lpc32xx_chip->ecc.mode = NAND_ECC_SOFT;
-
- /*
- * The implementation of these functions is quite common, but
- * they MUST be defined, because access to data register
- * is strictly 32-bit aligned.
- */
- lpc32xx_chip->read_buf = lpc32xx_read_buf;
- lpc32xx_chip->write_buf = lpc32xx_write_buf;
-#endif
-
- /*
- * These values are predefined
- * for both small and large page NAND flash devices.
- */
- lpc32xx_chip->ecc.size = CFG_SYS_NAND_ECCSIZE;
- lpc32xx_chip->ecc.bytes = CFG_SYS_NAND_ECCBYTES;
- lpc32xx_chip->ecc.strength = 1;
-
- if (CONFIG_SYS_NAND_PAGE_SIZE != NAND_LARGE_BLOCK_PAGE_SIZE)
- lpc32xx_chip->ecc.layout = &lpc32xx_nand_oob_16;
-
-#if defined(CONFIG_SYS_NAND_USE_FLASH_BBT)
- lpc32xx_chip->bbt_options |= NAND_BBT_USE_FLASH;
-#endif
-
- /* Initialize NAND interface */
- lpc32xx_nand_init();
-
- return 0;
-}
diff --git a/drivers/mtd/nand/raw/mxic_nand.c b/drivers/mtd/nand/raw/mxic_nand.c
deleted file mode 100644
index 0e54b5f6938..00000000000
--- a/drivers/mtd/nand/raw/mxic_nand.c
+++ /dev/null
@@ -1,602 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Copyright (C) 2021 Macronix International Co., Ltd.
- *
- * Author:
- * Zhengxun Li <zhengxunli@mxic.com.tw>
- */
-
-#include <clk.h>
-#include <dm.h>
-#include <malloc.h>
-#include <nand.h>
-#include <asm/io.h>
-#include <asm/arch/hardware.h>
-#include <dm/device_compat.h>
-#include <linux/bug.h>
-#include <linux/errno.h>
-#include <linux/iopoll.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/rawnand.h>
-#include <linux/mtd/partitions.h>
-#include <linux/mtd/nand_ecc.h>
-#include <linux/delay.h>
-
-#define HC_CFG 0x0
-#define HC_CFG_IF_CFG(x) ((x) << 27)
-#define HC_CFG_DUAL_SLAVE BIT(31)
-#define HC_CFG_INDIVIDUAL BIT(30)
-#define HC_CFG_NIO(x) (((x) / 4) << 27)
-#define HC_CFG_TYPE(s, t) ((t) << (23 + ((s) * 2)))
-#define HC_CFG_TYPE_SPI_NOR 0
-#define HC_CFG_TYPE_SPI_NAND 1
-#define HC_CFG_TYPE_SPI_RAM 2
-#define HC_CFG_TYPE_RAW_NAND 3
-#define HC_CFG_SLV_ACT(x) ((x) << 21)
-#define HC_CFG_CLK_PH_EN BIT(20)
-#define HC_CFG_CLK_POL_INV BIT(19)
-#define HC_CFG_BIG_ENDIAN BIT(18)
-#define HC_CFG_DATA_PASS BIT(17)
-#define HC_CFG_IDLE_SIO_LVL(x) ((x) << 16)
-#define HC_CFG_MAN_START_EN BIT(3)
-#define HC_CFG_MAN_START BIT(2)
-#define HC_CFG_MAN_CS_EN BIT(1)
-#define HC_CFG_MAN_CS_ASSERT BIT(0)
-
-#define INT_STS 0x4
-#define INT_STS_EN 0x8
-#define INT_SIG_EN 0xc
-#define INT_STS_ALL GENMASK(31, 0)
-#define INT_RDY_PIN BIT(26)
-#define INT_RDY_SR BIT(25)
-#define INT_LNR_SUSP BIT(24)
-#define INT_ECC_ERR BIT(17)
-#define INT_CRC_ERR BIT(16)
-#define INT_LWR_DIS BIT(12)
-#define INT_LRD_DIS BIT(11)
-#define INT_SDMA_INT BIT(10)
-#define INT_DMA_FINISH BIT(9)
-#define INT_RX_NOT_FULL BIT(3)
-#define INT_RX_NOT_EMPTY BIT(2)
-#define INT_TX_NOT_FULL BIT(1)
-#define INT_TX_EMPTY BIT(0)
-
-#define HC_EN 0x10
-#define HC_EN_BIT BIT(0)
-
-#define TXD(x) (0x14 + ((x) * 4))
-#define RXD 0x24
-
-#define SS_CTRL(s) (0x30 + ((s) * 4))
-#define LRD_CFG 0x44
-#define LWR_CFG 0x80
-#define RWW_CFG 0x70
-#define OP_READ BIT(23)
-#define OP_DUMMY_CYC(x) ((x) << 17)
-#define OP_ADDR_BYTES(x) ((x) << 14)
-#define OP_CMD_BYTES(x) (((x) - 1) << 13)
-#define OP_OCTA_CRC_EN BIT(12)
-#define OP_DQS_EN BIT(11)
-#define OP_ENHC_EN BIT(10)
-#define OP_PREAMBLE_EN BIT(9)
-#define OP_DATA_DDR BIT(8)
-#define OP_DATA_BUSW(x) ((x) << 6)
-#define OP_ADDR_DDR BIT(5)
-#define OP_ADDR_BUSW(x) ((x) << 3)
-#define OP_CMD_DDR BIT(2)
-#define OP_CMD_BUSW(x) (x)
-#define OP_BUSW_1 0
-#define OP_BUSW_2 1
-#define OP_BUSW_4 2
-#define OP_BUSW_8 3
-
-#define OCTA_CRC 0x38
-#define OCTA_CRC_IN_EN(s) BIT(3 + ((s) * 16))
-#define OCTA_CRC_CHUNK(s, x) ((fls((x) / 32)) << (1 + ((s) * 16)))
-#define OCTA_CRC_OUT_EN(s) BIT(0 + ((s) * 16))
-
-#define ONFI_DIN_CNT(s) (0x3c + (s))
-
-#define LRD_CTRL 0x48
-#define RWW_CTRL 0x74
-#define LWR_CTRL 0x84
-#define LMODE_EN BIT(31)
-#define LMODE_SLV_ACT(x) ((x) << 21)
-#define LMODE_CMD1(x) ((x) << 8)
-#define LMODE_CMD0(x) (x)
-
-#define LRD_ADDR 0x4c
-#define LWR_ADDR 0x88
-#define LRD_RANGE 0x50
-#define LWR_RANGE 0x8c
-
-#define AXI_SLV_ADDR 0x54
-
-#define DMAC_RD_CFG 0x58
-#define DMAC_WR_CFG 0x94
-#define DMAC_CFG_PERIPH_EN BIT(31)
-#define DMAC_CFG_ALLFLUSH_EN BIT(30)
-#define DMAC_CFG_LASTFLUSH_EN BIT(29)
-#define DMAC_CFG_QE(x) (((x) + 1) << 16)
-#define DMAC_CFG_BURST_LEN(x) (((x) + 1) << 12)
-#define DMAC_CFG_BURST_SZ(x) ((x) << 8)
-#define DMAC_CFG_DIR_READ BIT(1)
-#define DMAC_CFG_START BIT(0)
-
-#define DMAC_RD_CNT 0x5c
-#define DMAC_WR_CNT 0x98
-
-#define SDMA_ADDR 0x60
-
-#define DMAM_CFG 0x64
-#define DMAM_CFG_START BIT(31)
-#define DMAM_CFG_CONT BIT(30)
-#define DMAM_CFG_SDMA_GAP(x) (fls((x) / 8192) << 2)
-#define DMAM_CFG_DIR_READ BIT(1)
-#define DMAM_CFG_EN BIT(0)
-
-#define DMAM_CNT 0x68
-
-#define LNR_TIMER_TH 0x6c
-
-#define RDM_CFG0 0x78
-#define RDM_CFG0_POLY(x) (x)
-
-#define RDM_CFG1 0x7c
-#define RDM_CFG1_RDM_EN BIT(31)
-#define RDM_CFG1_SEED(x) (x)
-
-#define LWR_SUSP_CTRL 0x90
-#define LWR_SUSP_CTRL_EN BIT(31)
-
-#define DMAS_CTRL 0x9c
-#define DMAS_CTRL_EN BIT(31)
-#define DMAS_CTRL_DIR_READ BIT(30)
-
-#define DATA_STROB 0xa0
-#define DATA_STROB_EDO_EN BIT(2)
-#define DATA_STROB_INV_POL BIT(1)
-#define DATA_STROB_DELAY_2CYC BIT(0)
-
-#define IDLY_CODE(x) (0xa4 + ((x) * 4))
-#define IDLY_CODE_VAL(x, v) ((v) << (((x) % 4) * 8))
-
-#define GPIO 0xc4
-#define GPIO_PT(x) BIT(3 + ((x) * 16))
-#define GPIO_RESET(x) BIT(2 + ((x) * 16))
-#define GPIO_HOLDB(x) BIT(1 + ((x) * 16))
-#define GPIO_WPB(x) BIT((x) * 16)
-
-#define HC_VER 0xd0
-
-#define HW_TEST(x) (0xe0 + ((x) * 4))
-
-#define MXIC_NFC_MAX_CLK_HZ 50000000
-#define IRQ_TIMEOUT 1000
-
-struct mxic_nand_ctrl {
- struct clk *send_clk;
- struct clk *send_dly_clk;
- void __iomem *regs;
- struct nand_chip nand_chip;
-};
-
-/*
- * struct mxic_nfc_command_format - Defines NAND flash command format
- * @start_cmd: First cycle command (Start command)
- * @end_cmd: Second cycle command (Last command)
- * @addr_len: Number of address cycles required to send the address
- * @read: Direction of command
- */
-
-struct mxic_nfc_command_format {
- int start_cmd;
- int end_cmd;
- u8 addr_len;
- bool read;
-};
-
-/* The NAND flash operations command format */
-static const struct mxic_nfc_command_format mxic_nand_commands[] = {
- {NAND_CMD_READ0, NAND_CMD_READSTART, 5, 1 },
- {NAND_CMD_RNDOUT, NAND_CMD_RNDOUTSTART, 2, 1 },
- {NAND_CMD_READID, NAND_CMD_NONE, 1, 1 },
- {NAND_CMD_STATUS, NAND_CMD_NONE, 0, 1 },
- {NAND_CMD_SEQIN, NAND_CMD_NONE, 5, 0 },
- {NAND_CMD_PAGEPROG, NAND_CMD_NONE, 0, 0 },
- {NAND_CMD_CACHEDPROG, NAND_CMD_NONE, 0, 0 },
- {NAND_CMD_RNDIN, NAND_CMD_NONE, 2, 0 },
- {NAND_CMD_ERASE1, NAND_CMD_NONE, 3, 0 },
- {NAND_CMD_ERASE2, NAND_CMD_NONE, 0, 0 },
- {NAND_CMD_RESET, NAND_CMD_NONE, 0, 0 },
- {NAND_CMD_PARAM, NAND_CMD_NONE, 1, 1 },
- {NAND_CMD_GET_FEATURES, NAND_CMD_NONE, 1, 1 },
- {NAND_CMD_SET_FEATURES, NAND_CMD_NONE, 1, 0 },
- {NAND_CMD_NONE, NAND_CMD_NONE, 0, 0 },
-};
-
-static int mxic_nfc_clk_enable(struct mxic_nand_ctrl *nfc)
-{
- int ret;
-
- ret = clk_prepare_enable(nfc->send_clk);
- if (ret)
- return ret;
-
- ret = clk_prepare_enable(nfc->send_dly_clk);
- if (ret)
- goto err_send_dly_clk;
-
- return ret;
-
-err_send_dly_clk:
- clk_disable_unprepare(nfc->send_clk);
-
- return ret;
-}
-
-static void mxic_nfc_clk_disable(struct mxic_nand_ctrl *nfc)
-{
- clk_disable_unprepare(nfc->send_clk);
- clk_disable_unprepare(nfc->send_dly_clk);
-}
-
-static void mxic_nfc_set_input_delay(struct mxic_nand_ctrl *nfc, u8 idly_code)
-{
- writel(IDLY_CODE_VAL(0, idly_code) |
- IDLY_CODE_VAL(1, idly_code) |
- IDLY_CODE_VAL(2, idly_code) |
- IDLY_CODE_VAL(3, idly_code),
- nfc->regs + IDLY_CODE(0));
- writel(IDLY_CODE_VAL(4, idly_code) |
- IDLY_CODE_VAL(5, idly_code) |
- IDLY_CODE_VAL(6, idly_code) |
- IDLY_CODE_VAL(7, idly_code),
- nfc->regs + IDLY_CODE(1));
-}
-
-static int mxic_nfc_clk_setup(struct mxic_nand_ctrl *nfc, unsigned long freq)
-{
- int ret;
-
- ret = clk_set_rate(nfc->send_clk, freq);
- if (ret)
- return ret;
-
- ret = clk_set_rate(nfc->send_dly_clk, freq);
- if (ret)
- return ret;
-
- /*
- * A constant delay range from 0x0 ~ 0x1F for input delay,
- * the unit is 78 ps, the max input delay is 2.418 ns.
- */
- mxic_nfc_set_input_delay(nfc, 0xf);
-
- return 0;
-}
-
-static int mxic_nfc_set_freq(struct mxic_nand_ctrl *nfc, unsigned long freq)
-{
- int ret;
-
- if (freq > MXIC_NFC_MAX_CLK_HZ)
- freq = MXIC_NFC_MAX_CLK_HZ;
-
- mxic_nfc_clk_disable(nfc);
- ret = mxic_nfc_clk_setup(nfc, freq);
- if (ret)
- return ret;
-
- ret = mxic_nfc_clk_enable(nfc);
- if (ret)
- return ret;
-
- return 0;
-}
-
-static void mxic_nfc_hw_init(struct mxic_nand_ctrl *nfc)
-{
- writel(HC_CFG_NIO(8) | HC_CFG_TYPE(1, HC_CFG_TYPE_RAW_NAND) |
- HC_CFG_SLV_ACT(0) | HC_CFG_MAN_CS_EN |
- HC_CFG_IDLE_SIO_LVL(1), nfc->regs + HC_CFG);
- writel(INT_STS_ALL, nfc->regs + INT_STS_EN);
- writel(INT_RDY_PIN, nfc->regs + INT_SIG_EN);
- writel(0x0, nfc->regs + ONFI_DIN_CNT(0));
- writel(0, nfc->regs + LRD_CFG);
- writel(0, nfc->regs + LRD_CTRL);
- writel(0x0, nfc->regs + HC_EN);
-}
-
-static void mxic_nfc_cs_enable(struct mxic_nand_ctrl *nfc)
-{
- writel(readl(nfc->regs + HC_CFG) | HC_CFG_MAN_CS_EN,
- nfc->regs + HC_CFG);
- writel(HC_CFG_MAN_CS_ASSERT | readl(nfc->regs + HC_CFG),
- nfc->regs + HC_CFG);
-}
-
-static void mxic_nfc_cs_disable(struct mxic_nand_ctrl *nfc)
-{
- writel(~HC_CFG_MAN_CS_ASSERT & readl(nfc->regs + HC_CFG),
- nfc->regs + HC_CFG);
-}
-
-static int mxic_nfc_data_xfer(struct mxic_nand_ctrl *nfc, const void *txbuf,
- void *rxbuf, unsigned int len)
-{
- unsigned int pos = 0;
-
- while (pos < len) {
- unsigned int nbytes = len - pos;
- u32 data = 0xffffffff;
- u32 sts;
- int ret;
-
- if (nbytes > 4)
- nbytes = 4;
-
- if (txbuf)
- memcpy(&data, txbuf + pos, nbytes);
-
- ret = readl_poll_timeout(nfc->regs + INT_STS, sts,
- sts & INT_TX_EMPTY, 1000000);
- if (ret)
- return ret;
-
- writel(data, nfc->regs + TXD(nbytes % 4));
-
- ret = readl_poll_timeout(nfc->regs + INT_STS, sts,
- sts & INT_TX_EMPTY, 1000000);
- if (ret)
- return ret;
-
- ret = readl_poll_timeout(nfc->regs + INT_STS, sts,
- sts & INT_RX_NOT_EMPTY, 1000000);
- if (ret)
- return ret;
-
- data = readl(nfc->regs + RXD);
- if (rxbuf) {
- data >>= (8 * (4 - nbytes));
- memcpy(rxbuf + pos, &data, nbytes);
- }
-
- WARN_ON(readl(nfc->regs + INT_STS) & INT_RX_NOT_EMPTY);
-
- pos += nbytes;
- }
-
- return 0;
-}
-
-static uint8_t mxic_nfc_read_byte(struct mtd_info *mtd)
-{
- struct nand_chip *chip = mtd_to_nand(mtd);
- struct mxic_nand_ctrl *nfc = nand_get_controller_data(chip);
- u8 data;
-
- writel(0x0, nfc->regs + ONFI_DIN_CNT(0));
- writel(OP_DATA_BUSW(OP_BUSW_8) | OP_DUMMY_CYC(0x3F) |
- OP_READ, nfc->regs + SS_CTRL(0));
-
- mxic_nfc_data_xfer(nfc, NULL, &data, 1);
-
- return data;
-}
-
-static void mxic_nfc_read_buf(struct mtd_info *mtd, uint8_t *rxbuf, int rlen)
-{
- struct nand_chip *chip = mtd_to_nand(mtd);
- struct mxic_nand_ctrl *nfc = nand_get_controller_data(chip);
-
- writel(0x0, nfc->regs + ONFI_DIN_CNT(0));
- writel(OP_DATA_BUSW(OP_BUSW_8) | OP_DUMMY_CYC(0x3F) |
- OP_READ, nfc->regs + SS_CTRL(0));
-
- mxic_nfc_data_xfer(nfc, NULL, rxbuf, rlen);
-}
-
-static void mxic_nfc_write_buf(struct mtd_info *mtd, const uint8_t *txbuf,
- int wlen)
-{
- struct nand_chip *chip = mtd_to_nand(mtd);
- struct mxic_nand_ctrl *nfc = nand_get_controller_data(chip);
-
- writel(wlen, nfc->regs + ONFI_DIN_CNT(0));
- writel(OP_DATA_BUSW(OP_BUSW_8) | OP_DUMMY_CYC(0x3F),
- nfc->regs + SS_CTRL(0));
-
- mxic_nfc_data_xfer(nfc, txbuf, NULL, wlen);
-}
-
-static void mxic_nfc_cmd_function(struct mtd_info *mtd, unsigned int command,
- int column, int page_addr)
-{
- struct nand_chip *chip = mtd_to_nand(mtd);
- struct mxic_nand_ctrl *nfc = nand_get_controller_data(chip);
- const struct mxic_nfc_command_format *cmd = NULL;
- u32 sts;
- u8 index, addr[5];
-
- /* Emulate NAND_CMD_READOOB */
- if (command == NAND_CMD_READOOB) {
- column += mtd->writesize;
- command = NAND_CMD_READ0;
- }
-
- /* Get the command format */
- for (index = 0; index < ARRAY_SIZE(mxic_nand_commands); index++)
- if (command == mxic_nand_commands[index].start_cmd)
- break;
-
- cmd = &mxic_nand_commands[index];
-
- if (!(command == NAND_CMD_PAGEPROG ||
- command == NAND_CMD_CACHEDPROG ||
- command == NAND_CMD_ERASE2))
- mxic_nfc_cs_disable(nfc);
-
- mxic_nfc_cs_enable(nfc);
-
- if (column != -1) {
- addr[0] = column;
- addr[1] = column >> 8;
-
- if (page_addr != -1) {
- addr[2] = page_addr;
- addr[3] = page_addr >> 8;
- addr[4] = page_addr >> 16;
- }
- } else if (page_addr != -1) {
- addr[0] = page_addr;
- addr[1] = page_addr >> 8;
- addr[2] = page_addr >> 16;
- }
-
- writel(0, nfc->regs + HC_EN);
- writel(HC_EN_BIT, nfc->regs + HC_EN);
- writel(OP_CMD_BUSW(OP_BUSW_8) | OP_DUMMY_CYC(0x3F) | OP_CMD_BYTES(0),
- nfc->regs + SS_CTRL(0));
-
- mxic_nfc_data_xfer(nfc, &cmd->start_cmd, NULL, 1);
-
- if (cmd->addr_len) {
- writel(OP_ADDR_BUSW(OP_BUSW_8) | OP_DUMMY_CYC(0x3F) |
- OP_ADDR_BYTES(cmd->addr_len), nfc->regs + SS_CTRL(0));
-
- mxic_nfc_data_xfer(nfc, &addr, NULL, cmd->addr_len);
- }
-
- if (cmd->end_cmd != NAND_CMD_NONE) {
- writel(0, nfc->regs + HC_EN);
- writel(HC_EN_BIT, nfc->regs + HC_EN);
- writel(OP_CMD_BUSW(OP_BUSW_8) | OP_DUMMY_CYC(0x3F) |
- OP_CMD_BYTES(0), nfc->regs + SS_CTRL(0));
-
- mxic_nfc_data_xfer(nfc, &cmd->end_cmd, NULL, 1);
- }
-
- readl_poll_timeout(nfc->regs + INT_STS, sts, sts & INT_RDY_PIN,
- 1000000);
-
- if (command == NAND_CMD_PAGEPROG ||
- command == NAND_CMD_CACHEDPROG ||
- command == NAND_CMD_ERASE2 ||
- command == NAND_CMD_RESET) {
- mxic_nfc_cs_disable(nfc);
- }
-}
-
-static int mxic_nfc_setup_data_interface(struct mtd_info *mtd, int chipnr,
- const struct nand_data_interface *conf)
-{
- struct nand_chip *chip = mtd_to_nand(mtd);
- struct mxic_nand_ctrl *nfc = nand_get_controller_data(chip);
- const struct nand_sdr_timings *sdr;
- unsigned long freq;
- int ret;
-
- sdr = nand_get_sdr_timings(conf);
- if (IS_ERR(sdr))
- return PTR_ERR(sdr);
-
- if (chipnr == NAND_DATA_IFACE_CHECK_ONLY)
- return 0;
-
- freq = 1000000000 / (sdr->tRC_min / 1000);
-
- ret = mxic_nfc_set_freq(nfc, freq);
- if (ret)
- WARN_ON("Set freq failed\n");
-
- if (sdr->tRC_min < 30000)
- writel(DATA_STROB_EDO_EN, nfc->regs + DATA_STROB);
-
- return 0;
-}
-
-/* Dummy implementation: we don't support multiple chips */
-static void mxic_nfc_select_chip(struct mtd_info *mtd, int chipnr)
-{
- switch (chipnr) {
- case -1:
- case 0:
- break;
-
- default:
- BUG();
- }
-}
-
-static int mxic_nfc_probe(struct udevice *dev)
-{
- struct mxic_nand_ctrl *nfc = dev_get_priv(dev);
- struct nand_chip *nand_chip = &nfc->nand_chip;
- struct mtd_info *mtd;
- ofnode child;
- int err;
-
- nfc->regs = dev_read_addr_ptr(dev);
-
- nfc->send_clk = devm_clk_get(dev, "send");
- if (IS_ERR(nfc->send_clk))
- return PTR_ERR(nfc->send_clk);
-
- nfc->send_dly_clk = devm_clk_get(dev, "send_dly");
- if (IS_ERR(nfc->send_dly_clk))
- return PTR_ERR(nfc->send_dly_clk);
-
- mtd = nand_to_mtd(nand_chip);
-
- ofnode_for_each_subnode(child, dev_ofnode(dev))
- nand_set_flash_node(nand_chip, child);
-
- nand_set_controller_data(nand_chip, nfc);
-
- nand_chip->select_chip = mxic_nfc_select_chip;
- nand_chip->setup_data_interface = mxic_nfc_setup_data_interface;
- nand_chip->cmdfunc = mxic_nfc_cmd_function;
- nand_chip->read_byte = mxic_nfc_read_byte;
- nand_chip->read_buf = mxic_nfc_read_buf;
- nand_chip->write_buf = mxic_nfc_write_buf;
-
- mxic_nfc_hw_init(nfc);
-
- err = nand_scan(mtd, 1);
- if (err)
- return err;
-
- err = nand_register(0, mtd);
- if (err) {
- dev_err(dev, "Failed to register MTD: %d\n", err);
- return err;
- }
-
- return 0;
-}
-
-static const struct udevice_id mxic_nfc_of_ids[] = {
- { .compatible = "mxic,multi-itfc-v009-nand-controller" },
- { /* Sentinel */ }
-};
-
-U_BOOT_DRIVER(mxic_nfc) = {
- .name = "mxic_nfc",
- .id = UCLASS_MTD,
- .of_match = mxic_nfc_of_ids,
- .probe = mxic_nfc_probe,
- .priv_auto = sizeof(struct mxic_nand_ctrl),
-};
-
-void board_nand_init(void)
-{
- struct udevice *dev;
- int ret;
-
- ret = uclass_get_device_by_driver(UCLASS_MTD,
- DM_DRIVER_GET(mxic_nfc), &dev);
- if (ret && ret != -ENODEV)
- pr_err("Failed to initialize %s. (error %d)\n", dev->name,
- ret);
-}
diff --git a/drivers/mtd/nand/raw/mxs_nand.c b/drivers/mtd/nand/raw/mxs_nand.c
index ba67466069b..fecf1f5ba91 100644
--- a/drivers/mtd/nand/raw/mxs_nand.c
+++ b/drivers/mtd/nand/raw/mxs_nand.c
@@ -1640,10 +1640,12 @@ int mxs_nand_init_ctrl(struct mxs_nand_info *nand_info)
nand->setup_data_interface = mxs_nand_setup_interface;
/* first scan to find the device and get the page size */
- if (nand_scan_ident(mtd, CONFIG_SYS_MAX_NAND_DEVICE, NULL))
+ err = nand_scan_ident(mtd, CONFIG_SYS_MAX_NAND_DEVICE, NULL);
+ if (err)
goto err_free_buffers;
- if (mxs_nand_setup_ecc(mtd))
+ err = mxs_nand_setup_ecc(mtd);
+ if (err)
goto err_free_buffers;
nand->ecc.read_page = mxs_nand_ecc_read_page;
diff --git a/drivers/mtd/nand/raw/octeontx_bch.c b/drivers/mtd/nand/raw/octeontx_bch.c
deleted file mode 100644
index 056a6857822..00000000000
--- a/drivers/mtd/nand/raw/octeontx_bch.c
+++ /dev/null
@@ -1,422 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Copyright (C) 2018 Marvell International Ltd.
- */
-
-#include <dm.h>
-#include <dm/of_access.h>
-#include <malloc.h>
-#include <memalign.h>
-#include <nand.h>
-#include <pci.h>
-#include <pci_ids.h>
-#include <time.h>
-#include <linux/bitfield.h>
-#include <linux/ctype.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/ioport.h>
-#include <linux/libfdt.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/nand_bch.h>
-#include <linux/mtd/nand_ecc.h>
-#include <asm/io.h>
-#include <asm/types.h>
-#include <asm/dma-mapping.h>
-#include <asm/arch/clock.h>
-#include "octeontx_bch.h"
-
-static LIST_HEAD(octeontx_bch_devices);
-static unsigned int num_vfs = BCH_NR_VF;
-static void *bch_pf;
-static void *bch_vf;
-static void *token;
-static bool bch_pf_initialized;
-static bool bch_vf_initialized;
-
-static int pci_enable_sriov(struct udevice *dev, int nr_virtfn)
-{
- int ret;
-
- ret = pci_sriov_init(dev, nr_virtfn);
- if (ret)
- printf("%s(%s): pci_sriov_init returned %d\n", __func__,
- dev->name, ret);
- return ret;
-}
-
-void *octeontx_bch_getv(void)
-{
- if (!bch_vf)
- return NULL;
- if (bch_vf_initialized && bch_pf_initialized)
- return bch_vf;
- else
- return NULL;
-}
-
-void octeontx_bch_putv(void *token)
-{
- bch_vf_initialized = !!token;
- bch_vf = token;
-}
-
-void *octeontx_bch_getp(void)
-{
- return token;
-}
-
-void octeontx_bch_putp(void *token)
-{
- bch_pf = token;
- bch_pf_initialized = !!token;
-}
-
-static int do_bch_init(struct bch_device *bch)
-{
- return 0;
-}
-
-static void bch_reset(struct bch_device *bch)
-{
- writeq(1, bch->reg_base + BCH_CTL);
- mdelay(2);
-}
-
-static void bch_disable(struct bch_device *bch)
-{
- writeq(~0ull, bch->reg_base + BCH_ERR_INT_ENA_W1C);
- writeq(~0ull, bch->reg_base + BCH_ERR_INT);
- bch_reset(bch);
-}
-
-static u32 bch_check_bist_status(struct bch_device *bch)
-{
- return readq(bch->reg_base + BCH_BIST_RESULT);
-}
-
-static int bch_device_init(struct bch_device *bch)
-{
- u64 bist;
- int rc;
-
- debug("%s: Resetting...\n", __func__);
- /* Reset the PF when probed first */
- bch_reset(bch);
-
- debug("%s: Checking BIST...\n", __func__);
- /* Check BIST status */
- bist = (u64)bch_check_bist_status(bch);
- if (bist) {
- dev_err(dev, "BCH BIST failed with code 0x%llx\n", bist);
- return -ENODEV;
- }
-
- /* Get max VQs/VFs supported by the device */
-
- bch->max_vfs = pci_sriov_get_totalvfs(bch->dev);
- debug("%s: %d vfs\n", __func__, bch->max_vfs);
- if (num_vfs > bch->max_vfs) {
- dev_warn(dev, "Num of VFs to enable %d is greater than max available. Enabling %d VFs.\n",
- num_vfs, bch->max_vfs);
- num_vfs = bch->max_vfs;
- }
- bch->vfs_enabled = bch->max_vfs;
- /* Get number of VQs/VFs to be enabled */
- /* TODO: Get CLK frequency */
- /* Reset device parameters */
-
- debug("%s: Doing initialization\n", __func__);
- rc = do_bch_init(bch);
-
- return rc;
-}
-
-static int bch_sriov_configure(struct udevice *dev, int numvfs)
-{
- struct bch_device *bch = dev_get_priv(dev);
- int ret = -EBUSY;
-
- debug("%s(%s, %d), bch: %p, vfs_in_use: %d, enabled: %d\n", __func__,
- dev->name, numvfs, bch, bch->vfs_in_use, bch->vfs_enabled);
- if (bch->vfs_in_use)
- goto exit;
-
- ret = 0;
-
- if (numvfs > 0) {
- debug("%s: Enabling sriov\n", __func__);
- ret = pci_enable_sriov(dev, numvfs);
- if (ret == 0) {
- bch->flags |= BCH_FLAG_SRIOV_ENABLED;
- ret = numvfs;
- bch->vfs_enabled = numvfs;
- }
- }
-
- debug("VFs enabled: %d\n", ret);
-exit:
- debug("%s: Returning %d\n", __func__, ret);
- return ret;
-}
-
-static int octeontx_pci_bchpf_probe(struct udevice *dev)
-{
- struct bch_device *bch;
- int ret;
-
- debug("%s(%s)\n", __func__, dev->name);
- bch = dev_get_priv(dev);
- if (!bch)
- return -ENOMEM;
-
- bch->reg_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, 0, 0,
- PCI_REGION_TYPE, PCI_REGION_MEM);
- bch->dev = dev;
-
- debug("%s: base address: %p\n", __func__, bch->reg_base);
- ret = bch_device_init(bch);
- if (ret) {
- printf("%s(%s): init returned %d\n", __func__, dev->name, ret);
- return ret;
- }
- INIT_LIST_HEAD(&bch->list);
- list_add(&bch->list, &octeontx_bch_devices);
- token = (void *)dev;
-
- debug("%s: Configuring SRIOV\n", __func__);
- bch_sriov_configure(dev, num_vfs);
- debug("%s: Done.\n", __func__);
- octeontx_bch_putp(bch);
-
- return 0;
-}
-
-static const struct pci_device_id octeontx_bchpf_pci_id_table[] = {
- { PCI_VDEVICE(CAVIUM, PCI_DEVICE_ID_CAVIUM_BCH) },
- {},
-};
-
-static const struct pci_device_id octeontx_bchvf_pci_id_table[] = {
- { PCI_VDEVICE(CAVIUM, PCI_DEVICE_ID_CAVIUM_BCHVF)},
- {},
-};
-
-/**
- * Given a data block calculate the ecc data and fill in the response
- *
- * @param[in] block 8-byte aligned pointer to data block to calculate ECC
- * @param block_size Size of block in bytes, must be a multiple of two.
- * @param bch_level Number of errors that must be corrected. The number of
- * parity bytes is equal to ((15 * bch_level) + 7) / 8.
- * Must be 4, 8, 16, 24, 32, 40, 48, 56, 60 or 64.
- * @param[out] ecc 8-byte aligned pointer to where ecc data should go
- * @param[in] resp pointer to where responses will be written.
- *
- * Return: Zero on success, negative on failure.
- */
-int octeontx_bch_encode(struct bch_vf *vf, dma_addr_t block, u16 block_size,
- u8 bch_level, dma_addr_t ecc, dma_addr_t resp)
-{
- union bch_cmd cmd;
- int rc;
-
- memset(&cmd, 0, sizeof(cmd));
- cmd.s.cword.ecc_gen = eg_gen;
- cmd.s.cword.ecc_level = bch_level;
- cmd.s.cword.size = block_size;
-
- cmd.s.oword.ptr = ecc;
- cmd.s.iword.ptr = block;
- cmd.s.rword.ptr = resp;
- rc = octeontx_cmd_queue_write(QID_BCH, 1,
- sizeof(cmd) / sizeof(uint64_t), cmd.u);
- if (rc)
- return -1;
-
- octeontx_bch_write_doorbell(1, vf);
-
- return 0;
-}
-
-/**
- * Given a data block and ecc data correct the data block
- *
- * @param[in] block_ecc_in 8-byte aligned pointer to data block with ECC
- * data concatenated to the end to correct
- * @param block_size Size of block in bytes, must be a multiple of
- * two.
- * @param bch_level Number of errors that must be corrected. The
- * number of parity bytes is equal to
- * ((15 * bch_level) + 7) / 8.
- * Must be 4, 8, 16, 24, 32, 40, 48, 56, 60 or 64.
- * @param[out] block_out 8-byte aligned pointer to corrected data buffer.
- * This should not be the same as block_ecc_in.
- * @param[in] resp pointer to where responses will be written.
- *
- * Return: Zero on success, negative on failure.
- */
-
-int octeontx_bch_decode(struct bch_vf *vf, dma_addr_t block_ecc_in,
- u16 block_size, u8 bch_level,
- dma_addr_t block_out, dma_addr_t resp)
-{
- union bch_cmd cmd;
- int rc;
-
- memset(&cmd, 0, sizeof(cmd));
- cmd.s.cword.ecc_gen = eg_correct;
- cmd.s.cword.ecc_level = bch_level;
- cmd.s.cword.size = block_size;
-
- cmd.s.oword.ptr = block_out;
- cmd.s.iword.ptr = block_ecc_in;
- cmd.s.rword.ptr = resp;
- rc = octeontx_cmd_queue_write(QID_BCH, 1,
- sizeof(cmd) / sizeof(uint64_t), cmd.u);
- if (rc)
- return -1;
-
- octeontx_bch_write_doorbell(1, vf);
- return 0;
-}
-EXPORT_SYMBOL(octeontx_bch_decode);
-
-int octeontx_bch_wait(struct bch_vf *vf, union bch_resp *resp,
- dma_addr_t handle)
-{
- ulong start = get_timer(0);
-
- __iormb(); /* HW is updating *resp */
- while (!resp->s.done && get_timer(start) < 10)
- __iormb(); /* HW is updating *resp */
-
- if (resp->s.done)
- return 0;
-
- return -ETIMEDOUT;
-}
-
-struct bch_q octeontx_bch_q[QID_MAX];
-
-static int octeontx_cmd_queue_initialize(struct udevice *dev, int queue_id,
- int max_depth, int fpa_pool,
- int pool_size)
-{
- /* some params are for later merge with CPT or cn83xx */
- struct bch_q *q = &octeontx_bch_q[queue_id];
- unsigned long paddr;
- u64 *chunk_buffer;
- int chunk = max_depth + 1;
- int i, size;
-
- if ((unsigned int)queue_id >= QID_MAX)
- return -EINVAL;
- if (max_depth & chunk) /* must be 2^N - 1 */
- return -EINVAL;
-
- size = NQS * chunk * sizeof(u64);
- chunk_buffer = dma_alloc_coherent(size, &paddr);
- if (!chunk_buffer)
- return -ENOMEM;
-
- q->base_paddr = paddr;
- q->dev = dev;
- q->index = 0;
- q->max_depth = max_depth;
- q->pool_size_m1 = pool_size;
- q->base_vaddr = chunk_buffer;
-
- for (i = 0; i < NQS; i++) {
- u64 *ixp;
- int inext = (i + 1) * chunk - 1;
- int j = (i + 1) % NQS;
- int jnext = j * chunk;
- dma_addr_t jbase = q->base_paddr + jnext * sizeof(u64);
-
- ixp = &chunk_buffer[inext];
- *ixp = jbase;
- }
-
- return 0;
-}
-
-static int octeontx_pci_bchvf_probe(struct udevice *dev)
-{
- struct bch_vf *vf;
- union bch_vqx_ctl ctl;
- union bch_vqx_cmd_buf cbuf;
- int err;
-
- debug("%s(%s)\n", __func__, dev->name);
- vf = dev_get_priv(dev);
- if (!vf)
- return -ENOMEM;
-
- vf->dev = dev;
-
- /* Map PF's configuration registers */
- vf->reg_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, 0, 0,
- PCI_REGION_TYPE, PCI_REGION_MEM);
- debug("%s: reg base: %p\n", __func__, vf->reg_base);
-
- err = octeontx_cmd_queue_initialize(dev, QID_BCH, QDEPTH - 1, 0,
- sizeof(union bch_cmd) * QDEPTH);
- if (err) {
- dev_err(dev, "octeontx_cmd_queue_initialize() failed\n");
- goto release;
- }
-
- ctl.u = readq(vf->reg_base + BCH_VQX_CTL(0));
-
- cbuf.u = 0;
- cbuf.s.ldwb = 1;
- cbuf.s.dfb = 1;
- cbuf.s.size = QDEPTH;
- writeq(cbuf.u, vf->reg_base + BCH_VQX_CMD_BUF(0));
-
- writeq(ctl.u, vf->reg_base + BCH_VQX_CTL(0));
-
- writeq(octeontx_bch_q[QID_BCH].base_paddr,
- vf->reg_base + BCH_VQX_CMD_PTR(0));
-
- octeontx_bch_putv(vf);
-
- debug("%s: bch vf initialization complete\n", __func__);
-
- if (octeontx_bch_getv())
- return octeontx_pci_nand_deferred_probe();
-
- return -1;
-
-release:
- return err;
-}
-
-static int octeontx_pci_bchpf_remove(struct udevice *dev)
-{
- struct bch_device *bch = dev_get_priv(dev);
-
- bch_disable(bch);
- return 0;
-}
-
-U_BOOT_DRIVER(octeontx_pci_bchpf) = {
- .name = BCHPF_DRIVER_NAME,
- .id = UCLASS_MISC,
- .probe = octeontx_pci_bchpf_probe,
- .remove = octeontx_pci_bchpf_remove,
- .priv_auto = sizeof(struct bch_device),
- .flags = DM_FLAG_OS_PREPARE,
-};
-
-U_BOOT_DRIVER(octeontx_pci_bchvf) = {
- .name = BCHVF_DRIVER_NAME,
- .id = UCLASS_MISC,
- .probe = octeontx_pci_bchvf_probe,
- .priv_auto = sizeof(struct bch_vf),
-};
-
-U_BOOT_PCI_DEVICE(octeontx_pci_bchpf, octeontx_bchpf_pci_id_table);
-U_BOOT_PCI_DEVICE(octeontx_pci_bchvf, octeontx_bchvf_pci_id_table);
diff --git a/drivers/mtd/nand/raw/octeontx_bch.h b/drivers/mtd/nand/raw/octeontx_bch.h
deleted file mode 100644
index 95a9b7126fb..00000000000
--- a/drivers/mtd/nand/raw/octeontx_bch.h
+++ /dev/null
@@ -1,131 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0
- *
- * Copyright (C) 2018 Marvell International Ltd.
- */
-
-#ifndef __OCTEONTX_BCH_H__
-#define __OCTEONTX_BCH_H__
-
-#include "octeontx_bch_regs.h"
-
-/* flags to indicate the features supported */
-#define BCH_FLAG_SRIOV_ENABLED BIT(1)
-
-/*
- * BCH Registers map for 81xx
- */
-
-/* PF registers */
-#define BCH_CTL 0x0ull
-#define BCH_ERR_CFG 0x10ull
-#define BCH_BIST_RESULT 0x80ull
-#define BCH_ERR_INT 0x88ull
-#define BCH_ERR_INT_W1S 0x90ull
-#define BCH_ERR_INT_ENA_W1C 0xA0ull
-#define BCH_ERR_INT_ENA_W1S 0xA8ull
-
-/* VF registers */
-#define BCH_VQX_CTL(z) 0x0ull
-#define BCH_VQX_CMD_BUF(z) 0x8ull
-#define BCH_VQX_CMD_PTR(z) 0x20ull
-#define BCH_VQX_DOORBELL(z) 0x800ull
-
-#define BCHPF_DRIVER_NAME "octeontx-bchpf"
-#define BCHVF_DRIVER_NAME "octeontx-bchvf"
-
-struct bch_device {
- struct list_head list;
- u8 max_vfs;
- u8 vfs_enabled;
- u8 vfs_in_use;
- u32 flags;
- void __iomem *reg_base;
- struct udevice *dev;
-};
-
-struct bch_vf {
- u16 flags;
- u8 vfid;
- u8 node;
- u8 priority;
- struct udevice *dev;
- void __iomem *reg_base;
-};
-
-struct buf_ptr {
- u8 *vptr;
- dma_addr_t dma_addr;
- u16 size;
-};
-
-void *octeontx_bch_getv(void);
-void octeontx_bch_putv(void *token);
-void *octeontx_bch_getp(void);
-void octeontx_bch_putp(void *token);
-int octeontx_bch_wait(struct bch_vf *vf, union bch_resp *resp,
- dma_addr_t handle);
-/**
- * Given a data block calculate the ecc data and fill in the response
- *
- * @param[in] block 8-byte aligned pointer to data block to calculate ECC
- * @param block_size Size of block in bytes, must be a multiple of two.
- * @param bch_level Number of errors that must be corrected. The number of
- * parity bytes is equal to ((15 * bch_level) + 7) / 8.
- * Must be 4, 8, 16, 24, 32, 40, 48, 56, 60 or 64.
- * @param[out] ecc 8-byte aligned pointer to where ecc data should go
- * @param[in] resp pointer to where responses will be written.
- *
- * Return: Zero on success, negative on failure.
- */
-int octeontx_bch_encode(struct bch_vf *vf, dma_addr_t block, u16 block_size,
- u8 bch_level, dma_addr_t ecc, dma_addr_t resp);
-
-/**
- * Given a data block and ecc data correct the data block
- *
- * @param[in] block_ecc_in 8-byte aligned pointer to data block with ECC
- * data concatenated to the end to correct
- * @param block_size Size of block in bytes, must be a multiple of
- * two.
- * @param bch_level Number of errors that must be corrected. The
- * number of parity bytes is equal to
- * ((15 * bch_level) + 7) / 8.
- * Must be 4, 8, 16, 24, 32, 40, 48, 56, 60 or 64.
- * @param[out] block_out 8-byte aligned pointer to corrected data buffer.
- * This should not be the same as block_ecc_in.
- * @param[in] resp pointer to where responses will be written.
- *
- * Return: Zero on success, negative on failure.
- */
-
-int octeontx_bch_decode(struct bch_vf *vf, dma_addr_t block_ecc_in,
- u16 block_size, u8 bch_level,
- dma_addr_t block_out, dma_addr_t resp);
-
-/**
- * Ring the BCH doorbell telling it that new commands are
- * available.
- *
- * @param num_commands Number of new commands
- * @param vf virtual function handle
- */
-static inline void octeontx_bch_write_doorbell(u64 num_commands,
- struct bch_vf *vf)
-{
- u64 num_words = num_commands * sizeof(union bch_cmd) / sizeof(uint64_t);
-
- writeq(num_words, vf->reg_base + BCH_VQX_DOORBELL(0));
-}
-
-/**
- * Since it's possible (and even likely) that the NAND device will be probed
- * before the BCH device has been probed, we may need to defer the probing.
- *
- * In this case, the initial probe returns success but the actual probing
- * is deferred until the BCH VF has been probed.
- *
- * Return: 0 for success, otherwise error
- */
-int octeontx_pci_nand_deferred_probe(void);
-
-#endif /* __OCTEONTX_BCH_H__ */
diff --git a/drivers/mtd/nand/raw/octeontx_bch_regs.h b/drivers/mtd/nand/raw/octeontx_bch_regs.h
deleted file mode 100644
index 7d34438fec0..00000000000
--- a/drivers/mtd/nand/raw/octeontx_bch_regs.h
+++ /dev/null
@@ -1,167 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0
- *
- * Copyright (C) 2018 Marvell International Ltd.
- */
-
-#ifndef __OCTEONTX_BCH_REGS_H__
-#define __OCTEONTX_BCH_REGS_H__
-
-#define BCH_NR_VF 1
-
-union bch_cmd {
- u64 u[4];
- struct fields {
- struct {
- u64 size:12;
- u64 reserved_12_31:20;
- u64 ecc_level:4;
- u64 reserved_36_61:26;
- u64 ecc_gen:2;
- } cword;
- struct {
- u64 ptr:49;
- u64 reserved_49_55:7;
- u64 nc:1;
- u64 fw:1;
- u64 reserved_58_63:6;
- } oword;
- struct {
- u64 ptr:49;
- u64 reserved_49_55:7;
- u64 nc:1;
- u64 reserved_57_63:7;
- } iword;
- struct {
- u64 ptr:49;
- u64 reserved_49_63:15;
- } rword;
- } s;
-};
-
-enum ecc_gen {
- eg_correct,
- eg_copy,
- eg_gen,
- eg_copy3,
-};
-
-/** Response from BCH instruction */
-union bch_resp {
- u16 u16;
- struct {
- u16 num_errors:7; /** Number of errors in block */
- u16 zero:6; /** Always zero, ignore */
- u16 erased:1; /** Block is erased */
- u16 uncorrectable:1;/** too many bits flipped */
- u16 done:1; /** Block is done */
- } s;
-};
-
-union bch_vqx_ctl {
- u64 u;
- struct {
- u64 reserved_0:1;
- u64 cmd_be:1;
- u64 max_read:4;
- u64 reserved_6_15:10;
- u64 erase_disable:1;
- u64 one_cmd:1;
- u64 early_term:4;
- u64 reserved_22_63:42;
- } s;
-};
-
-union bch_vqx_cmd_buf {
- u64 u;
- struct {
- u64 reserved_0_32:33;
- u64 size:13;
- u64 dfb:1;
- u64 ldwb:1;
- u64 reserved_48_63:16;
- } s;
-};
-
-/* keep queue state indexed, even though just one supported here,
- * for later generalization to similarly-shaped queues on other Cavium devices
- */
-enum {
- QID_BCH,
- QID_MAX
-};
-
-struct bch_q {
- struct udevice *dev;
- int index;
- u16 max_depth;
- u16 pool_size_m1;
- u64 *base_vaddr;
- dma_addr_t base_paddr;
-};
-
-extern struct bch_q octeontx_bch_q[QID_MAX];
-
-/* with one dma-mapped area, virt<->phys conversions by +/- (vaddr-paddr) */
-static inline dma_addr_t qphys(int qid, void *v)
-{
- struct bch_q *q = &octeontx_bch_q[qid];
- int off = (u8 *)v - (u8 *)q->base_vaddr;
-
- return q->base_paddr + off;
-}
-
-#define octeontx_ptr_to_phys(v) qphys(QID_BCH, (v))
-
-static inline void *qvirt(int qid, dma_addr_t p)
-{
- struct bch_q *q = &octeontx_bch_q[qid];
- int off = p - q->base_paddr;
-
- return q->base_vaddr + off;
-}
-
-#define octeontx_phys_to_ptr(p) qvirt(QID_BCH, (p))
-
-/* plenty for interleaved r/w on two planes with 16k page, ecc_size 1k */
-/* QDEPTH >= 16, as successive chunks must align on 128-byte boundaries */
-#define QDEPTH 256 /* u64s in a command queue chunk, incl next-pointer */
-#define NQS 1 /* linked chunks in the chain */
-
-/**
- * Write an arbitrary number of command words to a command queue.
- * This is a generic function; the fixed number of command word
- * functions yield higher performance.
- *
- * Could merge with crypto version for FPA use on cn83xx
- */
-static inline int octeontx_cmd_queue_write(int queue_id, bool use_locking,
- int cmd_count, const u64 *cmds)
-{
- int ret = 0;
- u64 *cmd_ptr;
- struct bch_q *qptr = &octeontx_bch_q[queue_id];
-
- if (unlikely(cmd_count < 1 || cmd_count > 32))
- return -EINVAL;
- if (unlikely(!cmds))
- return -EINVAL;
-
- cmd_ptr = qptr->base_vaddr;
-
- while (cmd_count > 0) {
- int slot = qptr->index % (QDEPTH * NQS);
-
- if (slot % QDEPTH != QDEPTH - 1) {
- cmd_ptr[slot] = *cmds++;
- cmd_count--;
- }
-
- qptr->index++;
- }
-
- __iowmb(); /* flush commands before ringing bell */
-
- return ret;
-}
-
-#endif /* __OCTEONTX_BCH_REGS_H__ */
diff --git a/drivers/mtd/nand/raw/octeontx_nand.c b/drivers/mtd/nand/raw/octeontx_nand.c
deleted file mode 100644
index 3b20685fac0..00000000000
--- a/drivers/mtd/nand/raw/octeontx_nand.c
+++ /dev/null
@@ -1,2254 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Copyright (C) 2018 Marvell International Ltd.
- */
-
-#include <dm.h>
-#include <dm/device-internal.h>
-#include <dm/devres.h>
-#include <dm/of_access.h>
-#include <malloc.h>
-#include <memalign.h>
-#include <nand.h>
-#include <pci.h>
-#include <time.h>
-#include <linux/bitfield.h>
-#include <linux/ctype.h>
-#include <linux/dma-mapping.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/ioport.h>
-#include <linux/libfdt.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/nand_bch.h>
-#include <linux/mtd/nand_ecc.h>
-#include <linux/mtd/rawnand.h>
-#include <linux/time.h>
-#include <asm/global_data.h>
-#include <asm/io.h>
-#include <asm/types.h>
-#include <asm/dma-mapping.h>
-#include <asm/arch/clock.h>
-#include "octeontx_bch.h"
-
-/*
- * The NDF_CMD queue takes commands between 16 - 128 bit.
- * All commands must be 16 bit aligned and are little endian.
- * WAIT_STATUS commands must be 64 bit aligned.
- * Commands are selected by the 4 bit opcode.
- *
- * Available Commands:
- *
- * 16 Bit:
- * NOP
- * WAIT
- * BUS_ACQ, BUS_REL
- * CHIP_EN, CHIP_DIS
- *
- * 32 Bit:
- * CLE_CMD
- * RD_CMD, RD_EDO_CMD
- * WR_CMD
- *
- * 64 Bit:
- * SET_TM_PAR
- *
- * 96 Bit:
- * ALE_CMD
- *
- * 128 Bit:
- * WAIT_STATUS, WAIT_STATUS_ALE
- */
-
-/* NDF Register offsets */
-#define NDF_CMD 0x0
-#define NDF_MISC 0x8
-#define NDF_ECC_CNT 0x10
-#define NDF_DRBELL 0x30
-#define NDF_ST_REG 0x38 /* status */
-#define NDF_INT 0x40
-#define NDF_INT_W1S 0x48
-#define NDF_DMA_CFG 0x50
-#define NDF_DMA_ADR 0x58
-#define NDF_INT_ENA_W1C 0x60
-#define NDF_INT_ENA_W1S 0x68
-
-/* NDF command opcodes */
-#define NDF_OP_NOP 0x0
-#define NDF_OP_SET_TM_PAR 0x1
-#define NDF_OP_WAIT 0x2
-#define NDF_OP_CHIP_EN_DIS 0x3
-#define NDF_OP_CLE_CMD 0x4
-#define NDF_OP_ALE_CMD 0x5
-#define NDF_OP_WR_CMD 0x8
-#define NDF_OP_RD_CMD 0x9
-#define NDF_OP_RD_EDO_CMD 0xa
-#define NDF_OP_WAIT_STATUS 0xb /* same opcode for WAIT_STATUS_ALE */
-#define NDF_OP_BUS_ACQ_REL 0xf
-
-#define NDF_BUS_ACQUIRE 1
-#define NDF_BUS_RELEASE 0
-
-#define DBGX_EDSCR(X) (0x87A008000088 + (X) * 0x80000)
-
-struct ndf_nop_cmd {
- u16 opcode: 4;
- u16 nop: 12;
-};
-
-struct ndf_wait_cmd {
- u16 opcode:4;
- u16 r_b:1; /* wait for one cycle or PBUS_WAIT deassert */
- u16:3;
- u16 wlen:3; /* timing parameter select */
- u16:5;
-};
-
-struct ndf_bus_cmd {
- u16 opcode:4;
- u16 direction:4; /* 1 = acquire, 0 = release */
- u16:8;
-};
-
-struct ndf_chip_cmd {
- u16 opcode:4;
- u16 chip:3; /* select chip, 0 = disable */
- u16 enable:1; /* 1 = enable, 0 = disable */
- u16 bus_width:2; /* 10 = 16 bit, 01 = 8 bit */
- u16:6;
-};
-
-struct ndf_cle_cmd {
- u32 opcode:4;
- u32:4;
- u32 cmd_data:8; /* command sent to the PBUS AD pins */
- u32 clen1:3; /* time between PBUS CLE and WE asserts */
- u32 clen2:3; /* time WE remains asserted */
- u32 clen3:3; /* time between WE deassert and CLE */
- u32:7;
-};
-
-/* RD_EDO_CMD uses the same layout as RD_CMD */
-struct ndf_rd_cmd {
- u32 opcode:4;
- u32 data:16; /* data bytes */
- u32 rlen1:3;
- u32 rlen2:3;
- u32 rlen3:3;
- u32 rlen4:3;
-};
-
-struct ndf_wr_cmd {
- u32 opcode:4;
- u32 data:16; /* data bytes */
- u32:4;
- u32 wlen1:3;
- u32 wlen2:3;
- u32:3;
-};
-
-struct ndf_set_tm_par_cmd {
- u64 opcode:4;
- u64 tim_mult:4; /* multiplier for the seven parameters */
- u64 tm_par1:8; /* --> Following are the 7 timing parameters that */
- u64 tm_par2:8; /* specify the number of coprocessor cycles. */
- u64 tm_par3:8; /* A value of zero means one cycle. */
- u64 tm_par4:8; /* All values are scaled by tim_mult */
- u64 tm_par5:8; /* using tim_par * (2 ^ tim_mult). */
- u64 tm_par6:8;
- u64 tm_par7:8;
-};
-
-struct ndf_ale_cmd {
- u32 opcode:4;
- u32:4;
- u32 adr_byte_num:4; /* number of address bytes to be sent */
- u32:4;
- u32 alen1:3;
- u32 alen2:3;
- u32 alen3:3;
- u32 alen4:3;
- u32:4;
- u8 adr_byt1;
- u8 adr_byt2;
- u8 adr_byt3;
- u8 adr_byt4;
- u8 adr_byt5;
- u8 adr_byt6;
- u8 adr_byt7;
- u8 adr_byt8;
-};
-
-struct ndf_wait_status_cmd {
- u32 opcode:4;
- u32:4;
- u32 data:8; /** data */
- u32 clen1:3;
- u32 clen2:3;
- u32 clen3:3;
- u32:8;
- /** set to 5 to select WAIT_STATUS_ALE command */
- u32 ale_ind:8;
- /** ALE only: number of address bytes to be sent */
- u32 adr_byte_num:4;
- u32:4;
- u32 alen1:3; /* ALE only */
- u32 alen2:3; /* ALE only */
- u32 alen3:3; /* ALE only */
- u32 alen4:3; /* ALE only */
- u32:4;
- u8 adr_byt[4]; /* ALE only */
- u32 nine:4; /* set to 9 */
- u32 and_mask:8;
- u32 comp_byte:8;
- u32 rlen1:3;
- u32 rlen2:3;
- u32 rlen3:3;
- u32 rlen4:3;
-};
-
-union ndf_cmd {
- u64 val[2];
- union {
- struct ndf_nop_cmd nop;
- struct ndf_wait_cmd wait;
- struct ndf_bus_cmd bus_acq_rel;
- struct ndf_chip_cmd chip_en_dis;
- struct ndf_cle_cmd cle_cmd;
- struct ndf_rd_cmd rd_cmd;
- struct ndf_wr_cmd wr_cmd;
- struct ndf_set_tm_par_cmd set_tm_par;
- struct ndf_ale_cmd ale_cmd;
- struct ndf_wait_status_cmd wait_status;
- } u;
-};
-
-/** Disable multi-bit error hangs */
-#define NDF_MISC_MB_DIS BIT_ULL(27)
-/** High watermark for NBR FIFO or load/store operations */
-#define NDF_MISC_NBR_HWM GENMASK_ULL(26, 24)
-/** Wait input filter count */
-#define NDF_MISC_WAIT_CNT GENMASK_ULL(23, 18)
-/** Unfilled NFD_CMD queue bytes */
-#define NDF_MISC_FR_BYTE GENMASK_ULL(17, 7)
-/** Set by HW when it reads the last 8 bytes of NDF_CMD */
-#define NDF_MISC_RD_DONE BIT_ULL(6)
-/** Set by HW when it reads. SW read of NDF_CMD clears it */
-#define NDF_MISC_RD_VAL BIT_ULL(5)
-/** Let HW read NDF_CMD queue. Cleared on SW NDF_CMD write */
-#define NDF_MISC_RD_CMD BIT_ULL(4)
-/** Boot disable */
-#define NDF_MISC_BT_DIS BIT_ULL(2)
-/** Stop command execution after completing command queue */
-#define NDF_MISC_EX_DIS BIT_ULL(1)
-/** Reset fifo */
-#define NDF_MISC_RST_FF BIT_ULL(0)
-
-/** DMA engine enable */
-#define NDF_DMA_CFG_EN BIT_ULL(63)
-/** Read or write */
-#define NDF_DMA_CFG_RW BIT_ULL(62)
-/** Terminates DMA and clears enable bit */
-#define NDF_DMA_CFG_CLR BIT_ULL(61)
-/** 32-bit swap enable */
-#define NDF_DMA_CFG_SWAP32 BIT_ULL(59)
-/** 16-bit swap enable */
-#define NDF_DMA_CFG_SWAP16 BIT_ULL(58)
-/** 8-bit swap enable */
-#define NDF_DMA_CFG_SWAP8 BIT_ULL(57)
-/** Endian mode */
-#define NDF_DMA_CFG_CMD_BE BIT_ULL(56)
-/** Number of 64 bit transfers */
-#define NDF_DMA_CFG_SIZE GENMASK_ULL(55, 36)
-
-/** Command execution status idle */
-#define NDF_ST_REG_EXE_IDLE BIT_ULL(15)
-/** Command execution SM states */
-#define NDF_ST_REG_EXE_SM GENMASK_ULL(14, 11)
-/** DMA and load SM states */
-#define NDF_ST_REG_BT_SM GENMASK_ULL(10, 7)
-/** Queue read-back SM bad state */
-#define NDF_ST_REG_RD_FF_BAD BIT_ULL(6)
-/** Queue read-back SM states */
-#define NDF_ST_REG_RD_FF GENMASK_ULL(5, 4)
-/** Main SM is in a bad state */
-#define NDF_ST_REG_MAIN_BAD BIT_ULL(3)
-/** Main SM states */
-#define NDF_ST_REG_MAIN_SM GENMASK_ULL(2, 0)
-
-#define MAX_NAND_NAME_LEN 64
-#if (defined(NAND_MAX_PAGESIZE) && (NAND_MAX_PAGESIZE > 4096)) || \
- !defined(NAND_MAX_PAGESIZE)
-# undef NAND_MAX_PAGESIZE
-# define NAND_MAX_PAGESIZE 4096
-#endif
-#if (defined(NAND_MAX_OOBSIZE) && (NAND_MAX_OOBSIZE > 256)) || \
- !defined(NAND_MAX_OOBSIZE)
-# undef NAND_MAX_OOBSIZE
-# define NAND_MAX_OOBSIZE 256
-#endif
-
-#define OCTEONTX_NAND_DRIVER_NAME "octeontx_nand"
-
-#define NDF_TIMEOUT 1000 /** Timeout in ms */
-#ifndef NAND_MAX_CHIPS
-# define NAND_MAX_CHIPS 8 /** Linux compatibility */
-#endif
-
-struct octeontx_nand_chip {
- struct list_head node;
- struct nand_chip nand;
- struct ndf_set_tm_par_cmd timings;
- int cs;
- int selected_page;
- int iface_mode;
- int row_bytes;
- int col_bytes;
- bool oob_only;
- bool iface_set;
-};
-
-struct octeontx_nand_buf {
- u8 *dmabuf;
- dma_addr_t dmaaddr;
- int dmabuflen;
- int data_len;
- int data_index;
-};
-
-/** NAND flash controller (NDF) related information */
-struct octeontx_nfc {
- struct nand_hw_control controller;
- struct udevice *dev;
- void __iomem *base;
- struct list_head chips;
- int selected_chip; /* Currently selected NAND chip number */
-
- /*
- * Status is separate from octeontx_nand_buf because
- * it can be used in parallel and during init.
- */
- u8 *stat;
- dma_addr_t stat_addr;
- bool use_status;
-
- struct octeontx_nand_buf buf;
- union bch_resp *bch_resp;
- dma_addr_t bch_rhandle;
-
- /* BCH of all-0xff, so erased pages read as error-free */
- unsigned char *eccmask;
-};
-
-/* settable timings - 0..7 select timing of alen1..4/clen1..3/etc */
-enum tm_idx {
- t0, /* fixed at 4<<mult cycles */
- t1, t2, t3, t4, t5, t6, t7, /* settable per ONFI-timing mode */
-};
-
-struct octeontx_probe_device {
- struct list_head list;
- struct udevice *dev;
-};
-
-static struct bch_vf *bch_vf;
-/** Deferred devices due to BCH not being ready */
-static LIST_HEAD(octeontx_pci_nand_deferred_devices);
-
-/** default parameters used for probing chips */
-#define MAX_ONFI_MODE 5
-
-static int default_onfi_timing;
-static int slew_ns = 2; /* default timing padding */
-static int def_ecc_size = 512; /* 1024 best for sw_bch, <= 4095 for hw_bch */
-static int default_width = 1; /* 8 bit */
-static int default_page_size = 2048;
-static struct ndf_set_tm_par_cmd default_timing_parms;
-
-/** Port from Linux */
-#define readq_poll_timeout(addr, val, cond, delay_us, timeout_us) \
-({ \
- ulong __start = get_timer(0); \
- void *__addr = (addr); \
- const ulong __timeout_ms = timeout_us / 1000; \
- do { \
- (val) = readq(__addr); \
- if (cond) \
- break; \
- if (timeout_us && get_timer(__start) > __timeout_ms) { \
- (val) = readq(__addr); \
- break; \
- } \
- if (delay_us) \
- udelay(delay_us); \
- } while (1); \
- (cond) ? 0 : -ETIMEDOUT; \
-})
-
-/** Ported from Linux 4.9.0 include/linux/of.h for compatibility */
-static inline int of_get_child_count(const ofnode node)
-{
- return fdtdec_get_child_count(gd->fdt_blob, ofnode_to_offset(node));
-}
-
-/**
- * Linux compatibility from Linux 4.9.0 drivers/mtd/nand/nand_base.c
- */
-static int nand_ooblayout_ecc_lp(struct mtd_info *mtd, int section,
- struct mtd_oob_region *oobregion)
-{
- struct nand_chip *chip = mtd_to_nand(mtd);
- struct nand_ecc_ctrl *ecc = &chip->ecc;
-
- if (section || !ecc->total)
- return -ERANGE;
-
- oobregion->length = ecc->total;
- oobregion->offset = mtd->oobsize - oobregion->length;
-
- return 0;
-}
-
-/**
- * Linux compatibility from Linux 4.9.0 drivers/mtd/nand/nand_base.c
- */
-static int nand_ooblayout_free_lp(struct mtd_info *mtd, int section,
- struct mtd_oob_region *oobregion)
-{
- struct nand_chip *chip = mtd_to_nand(mtd);
- struct nand_ecc_ctrl *ecc = &chip->ecc;
-
- if (section)
- return -ERANGE;
-
- oobregion->length = mtd->oobsize - ecc->total - 2;
- oobregion->offset = 2;
-
- return 0;
-}
-
-static const struct mtd_ooblayout_ops nand_ooblayout_lp_ops = {
- .ecc = nand_ooblayout_ecc_lp,
- .rfree = nand_ooblayout_free_lp,
-};
-
-static inline struct octeontx_nand_chip *to_otx_nand(struct nand_chip *nand)
-{
- return container_of(nand, struct octeontx_nand_chip, nand);
-}
-
-static inline struct octeontx_nfc *to_otx_nfc(struct nand_hw_control *ctrl)
-{
- return container_of(ctrl, struct octeontx_nfc, controller);
-}
-
-static int octeontx_nand_calc_ecc_layout(struct nand_chip *nand)
-{
- struct nand_ecclayout *layout = nand->ecc.layout;
- struct octeontx_nfc *tn = to_otx_nfc(nand->controller);
- struct mtd_info *mtd = &nand->mtd;
- int oobsize = mtd->oobsize;
- int i;
- bool layout_alloc = false;
-
- if (!layout) {
- layout = devm_kzalloc(tn->dev, sizeof(*layout), GFP_KERNEL);
- if (!layout)
- return -ENOMEM;
- nand->ecc.layout = layout;
- layout_alloc = true;
- }
- layout->eccbytes = nand->ecc.steps * nand->ecc.bytes;
- /* Reserve 2 bytes for bad block marker */
- if (layout->eccbytes + 2 > oobsize) {
- pr_err("No suitable oob scheme available for oobsize %d eccbytes %u\n",
- oobsize, layout->eccbytes);
- goto fail;
- }
- /* put ecc bytes at oob tail */
- for (i = 0; i < layout->eccbytes; i++)
- layout->eccpos[i] = oobsize - layout->eccbytes + i;
- layout->oobfree[0].offset = 2;
- layout->oobfree[0].length = oobsize - 2 - layout->eccbytes;
- nand->ecc.layout = layout;
- return 0;
-
-fail:
- if (layout_alloc)
- kfree(layout);
- return -1;
-}
-
-/*
- * Read a single byte from the temporary buffer. Used after READID
- * to get the NAND information and for STATUS.
- */
-static u8 octeontx_nand_read_byte(struct mtd_info *mtd)
-{
- struct nand_chip *nand = mtd_to_nand(mtd);
- struct octeontx_nfc *tn = to_otx_nfc(nand->controller);
-
- if (tn->use_status) {
- tn->use_status = false;
- return *tn->stat;
- }
-
- if (tn->buf.data_index < tn->buf.data_len)
- return tn->buf.dmabuf[tn->buf.data_index++];
-
- dev_err(tn->dev, "No data to read, idx: 0x%x, len: 0x%x\n",
- tn->buf.data_index, tn->buf.data_len);
-
- return 0xff;
-}
-
-/*
- * Read a number of pending bytes from the temporary buffer. Used
- * to get page and OOB data.
- */
-static void octeontx_nand_read_buf(struct mtd_info *mtd, u8 *buf, int len)
-{
- struct nand_chip *nand = mtd_to_nand(mtd);
- struct octeontx_nfc *tn = to_otx_nfc(nand->controller);
-
- if (len > tn->buf.data_len - tn->buf.data_index) {
- dev_err(tn->dev, "Not enough data for read of %d bytes\n", len);
- return;
- }
-
- memcpy(buf, tn->buf.dmabuf + tn->buf.data_index, len);
- tn->buf.data_index += len;
-}
-
-static void octeontx_nand_write_buf(struct mtd_info *mtd,
- const u8 *buf, int len)
-{
- struct nand_chip *nand = mtd_to_nand(mtd);
- struct octeontx_nfc *tn = to_otx_nfc(nand->controller);
-
- memcpy(tn->buf.dmabuf + tn->buf.data_len, buf, len);
- tn->buf.data_len += len;
-}
-
-/* Overwrite default function to avoid sync abort on chip = -1. */
-static void octeontx_nand_select_chip(struct mtd_info *mtd, int chip)
-{
-}
-
-static inline int timing_to_cycle(u32 psec, unsigned long clock)
-{
- unsigned int ns;
- int ticks;
-
- ns = DIV_ROUND_UP(psec, 1000);
- ns += slew_ns;
-
- /* no rounding needed since clock is multiple of 1MHz */
- clock /= 1000000;
- ns *= clock;
-
- ticks = DIV_ROUND_UP(ns, 1000);
-
- /* actual delay is (tm_parX+1)<<tim_mult */
- if (ticks)
- ticks--;
-
- return ticks;
-}
-
-static void set_timings(struct octeontx_nand_chip *chip,
- struct ndf_set_tm_par_cmd *tp,
- const struct nand_sdr_timings *timings,
- unsigned long sclk)
-{
- /* scaled coprocessor-cycle values */
- u32 s_wh, s_cls, s_clh, s_rp, s_wb, s_wc;
-
- tp->tim_mult = 0;
- s_wh = timing_to_cycle(timings->tWH_min, sclk);
- s_cls = timing_to_cycle(timings->tCLS_min, sclk);
- s_clh = timing_to_cycle(timings->tCLH_min, sclk);
- s_rp = timing_to_cycle(timings->tRP_min, sclk);
- s_wb = timing_to_cycle(timings->tWB_max, sclk);
- s_wc = timing_to_cycle(timings->tWC_min, sclk);
-
- tp->tm_par1 = s_wh;
- tp->tm_par2 = s_clh;
- tp->tm_par3 = s_rp + 1;
- tp->tm_par4 = s_cls - s_wh;
- tp->tm_par5 = s_wc - s_wh + 1;
- tp->tm_par6 = s_wb;
- tp->tm_par7 = 0;
- tp->tim_mult++; /* overcompensate for bad math */
-
- /* TODO: comment parameter re-use */
-
- pr_debug("%s: tim_par: mult: %d p1: %d p2: %d p3: %d\n",
- __func__, tp->tim_mult, tp->tm_par1, tp->tm_par2, tp->tm_par3);
- pr_debug(" p4: %d p5: %d p6: %d p7: %d\n",
- tp->tm_par4, tp->tm_par5, tp->tm_par6, tp->tm_par7);
-}
-
-static int set_default_timings(struct octeontx_nfc *tn,
- const struct nand_sdr_timings *timings)
-{
- unsigned long sclk = octeontx_get_io_clock();
-
- set_timings(NULL, &default_timing_parms, timings, sclk);
- return 0;
-}
-
-static int octeontx_nfc_chip_set_timings(struct octeontx_nand_chip *chip,
- const struct nand_sdr_timings *timings)
-{
- /*struct octeontx_nfc *tn = to_otx_nfc(chip->nand.controller);*/
- unsigned long sclk = octeontx_get_io_clock();
-
- set_timings(chip, &chip->timings, timings, sclk);
- return 0;
-}
-
-/* How many bytes are free in the NFD_CMD queue? */
-static int ndf_cmd_queue_free(struct octeontx_nfc *tn)
-{
- u64 ndf_misc;
-
- ndf_misc = readq(tn->base + NDF_MISC);
- return FIELD_GET(NDF_MISC_FR_BYTE, ndf_misc);
-}
-
-/* Submit a command to the NAND command queue. */
-static int ndf_submit(struct octeontx_nfc *tn, union ndf_cmd *cmd)
-{
- int opcode = cmd->val[0] & 0xf;
-
- switch (opcode) {
- /* All these commands fit in one 64bit word */
- case NDF_OP_NOP:
- case NDF_OP_SET_TM_PAR:
- case NDF_OP_WAIT:
- case NDF_OP_CHIP_EN_DIS:
- case NDF_OP_CLE_CMD:
- case NDF_OP_WR_CMD:
- case NDF_OP_RD_CMD:
- case NDF_OP_RD_EDO_CMD:
- case NDF_OP_BUS_ACQ_REL:
- if (ndf_cmd_queue_free(tn) < 8)
- goto full;
- writeq(cmd->val[0], tn->base + NDF_CMD);
- break;
- case NDF_OP_ALE_CMD:
- /* ALE commands take either one or two 64bit words */
- if (cmd->u.ale_cmd.adr_byte_num < 5) {
- if (ndf_cmd_queue_free(tn) < 8)
- goto full;
- writeq(cmd->val[0], tn->base + NDF_CMD);
- } else {
- if (ndf_cmd_queue_free(tn) < 16)
- goto full;
- writeq(cmd->val[0], tn->base + NDF_CMD);
- writeq(cmd->val[1], tn->base + NDF_CMD);
- }
- break;
- case NDF_OP_WAIT_STATUS: /* Wait status commands take two 64bit words */
- if (ndf_cmd_queue_free(tn) < 16)
- goto full;
- writeq(cmd->val[0], tn->base + NDF_CMD);
- writeq(cmd->val[1], tn->base + NDF_CMD);
- break;
- default:
- dev_err(tn->dev, "%s: unknown command: %u\n", __func__, opcode);
- return -EINVAL;
- }
- return 0;
-
-full:
- dev_err(tn->dev, "%s: no space left in command queue\n", __func__);
- return -ENOMEM;
-}
-
-/**
- * Wait for the ready/busy signal. First wait for busy to be valid,
- * then wait for busy to de-assert.
- */
-static int ndf_build_wait_busy(struct octeontx_nfc *tn)
-{
- union ndf_cmd cmd;
-
- memset(&cmd, 0, sizeof(cmd));
- cmd.u.wait.opcode = NDF_OP_WAIT;
- cmd.u.wait.r_b = 1;
- cmd.u.wait.wlen = t6;
-
- if (ndf_submit(tn, &cmd))
- return -ENOMEM;
- return 0;
-}
-
-static bool ndf_dma_done(struct octeontx_nfc *tn)
-{
- u64 dma_cfg;
-
- /* Enable bit should be clear after a transfer */
- dma_cfg = readq(tn->base + NDF_DMA_CFG);
- if (!(dma_cfg & NDF_DMA_CFG_EN))
- return true;
-
- return false;
-}
-
-static int ndf_wait(struct octeontx_nfc *tn)
-{
- ulong start = get_timer(0);
- bool done;
-
- while (!(done = ndf_dma_done(tn)) && get_timer(start) < NDF_TIMEOUT)
- ;
-
- if (!done) {
- dev_err(tn->dev, "%s: timeout error\n", __func__);
- return -ETIMEDOUT;
- }
- return 0;
-}
-
-static int ndf_wait_idle(struct octeontx_nfc *tn)
-{
- u64 val;
- u64 dval = 0;
- int rc;
- int pause = 100;
- u64 tot_us = USEC_PER_SEC / 10;
-
- rc = readq_poll_timeout(tn->base + NDF_ST_REG,
- val, val & NDF_ST_REG_EXE_IDLE, pause, tot_us);
- if (!rc)
- rc = readq_poll_timeout(tn->base + NDF_DMA_CFG,
- dval, !(dval & NDF_DMA_CFG_EN),
- pause, tot_us);
-
- return rc;
-}
-
-/** Issue set timing parameters */
-static int ndf_queue_cmd_timing(struct octeontx_nfc *tn,
- struct ndf_set_tm_par_cmd *timings)
-{
- union ndf_cmd cmd;
-
- memset(&cmd, 0, sizeof(cmd));
- cmd.u.set_tm_par.opcode = NDF_OP_SET_TM_PAR;
- cmd.u.set_tm_par.tim_mult = timings->tim_mult;
- cmd.u.set_tm_par.tm_par1 = timings->tm_par1;
- cmd.u.set_tm_par.tm_par2 = timings->tm_par2;
- cmd.u.set_tm_par.tm_par3 = timings->tm_par3;
- cmd.u.set_tm_par.tm_par4 = timings->tm_par4;
- cmd.u.set_tm_par.tm_par5 = timings->tm_par5;
- cmd.u.set_tm_par.tm_par6 = timings->tm_par6;
- cmd.u.set_tm_par.tm_par7 = timings->tm_par7;
- return ndf_submit(tn, &cmd);
-}
-
-/** Issue bus acquire or release */
-static int ndf_queue_cmd_bus(struct octeontx_nfc *tn, int direction)
-{
- union ndf_cmd cmd;
-
- memset(&cmd, 0, sizeof(cmd));
- cmd.u.bus_acq_rel.opcode = NDF_OP_BUS_ACQ_REL;
- cmd.u.bus_acq_rel.direction = direction;
- return ndf_submit(tn, &cmd);
-}
-
-/* Issue chip select or deselect */
-static int ndf_queue_cmd_chip(struct octeontx_nfc *tn, int enable, int chip,
- int width)
-{
- union ndf_cmd cmd;
-
- memset(&cmd, 0, sizeof(cmd));
- cmd.u.chip_en_dis.opcode = NDF_OP_CHIP_EN_DIS;
- cmd.u.chip_en_dis.chip = chip;
- cmd.u.chip_en_dis.enable = enable;
- cmd.u.chip_en_dis.bus_width = width;
- return ndf_submit(tn, &cmd);
-}
-
-static int ndf_queue_cmd_wait(struct octeontx_nfc *tn, int t_delay)
-{
- union ndf_cmd cmd;
-
- memset(&cmd, 0, sizeof(cmd));
- cmd.u.wait.opcode = NDF_OP_WAIT;
- cmd.u.wait.wlen = t_delay;
- return ndf_submit(tn, &cmd);
-}
-
-static int ndf_queue_cmd_cle(struct octeontx_nfc *tn, int command)
-{
- union ndf_cmd cmd;
-
- memset(&cmd, 0, sizeof(cmd));
- cmd.u.cle_cmd.opcode = NDF_OP_CLE_CMD;
- cmd.u.cle_cmd.cmd_data = command;
- cmd.u.cle_cmd.clen1 = t4;
- cmd.u.cle_cmd.clen2 = t1;
- cmd.u.cle_cmd.clen3 = t2;
- return ndf_submit(tn, &cmd);
-}
-
-static int ndf_queue_cmd_ale(struct octeontx_nfc *tn, int addr_bytes,
- struct nand_chip *nand, u64 page,
- u32 col, int page_size)
-{
- struct octeontx_nand_chip *octeontx_nand = (nand) ?
- to_otx_nand(nand) : NULL;
- union ndf_cmd cmd;
-
- memset(&cmd, 0, sizeof(cmd));
- cmd.u.ale_cmd.opcode = NDF_OP_ALE_CMD;
- cmd.u.ale_cmd.adr_byte_num = addr_bytes;
-
- /* set column bit for OOB area, assume OOB follows page */
- if (octeontx_nand && octeontx_nand->oob_only)
- col += page_size;
-
- /* page is u64 for this generality, even if cmdfunc() passes int */
- switch (addr_bytes) {
- /* 4-8 bytes: page, then 2-byte col */
- case 8:
- cmd.u.ale_cmd.adr_byt8 = (page >> 40) & 0xff;
- fallthrough;
- case 7:
- cmd.u.ale_cmd.adr_byt7 = (page >> 32) & 0xff;
- fallthrough;
- case 6:
- cmd.u.ale_cmd.adr_byt6 = (page >> 24) & 0xff;
- fallthrough;
- case 5:
- cmd.u.ale_cmd.adr_byt5 = (page >> 16) & 0xff;
- fallthrough;
- case 4:
- cmd.u.ale_cmd.adr_byt4 = (page >> 8) & 0xff;
- cmd.u.ale_cmd.adr_byt3 = page & 0xff;
- cmd.u.ale_cmd.adr_byt2 = (col >> 8) & 0xff;
- cmd.u.ale_cmd.adr_byt1 = col & 0xff;
- break;
- /* 1-3 bytes: just the page address */
- case 3:
- cmd.u.ale_cmd.adr_byt3 = (page >> 16) & 0xff;
- fallthrough;
- case 2:
- cmd.u.ale_cmd.adr_byt2 = (page >> 8) & 0xff;
- fallthrough;
- case 1:
- cmd.u.ale_cmd.adr_byt1 = page & 0xff;
- break;
- default:
- break;
- }
-
- cmd.u.ale_cmd.alen1 = t3;
- cmd.u.ale_cmd.alen2 = t1;
- cmd.u.ale_cmd.alen3 = t5;
- cmd.u.ale_cmd.alen4 = t2;
- return ndf_submit(tn, &cmd);
-}
-
-static int ndf_queue_cmd_write(struct octeontx_nfc *tn, int len)
-{
- union ndf_cmd cmd;
-
- memset(&cmd, 0, sizeof(cmd));
- cmd.u.wr_cmd.opcode = NDF_OP_WR_CMD;
- cmd.u.wr_cmd.data = len;
- cmd.u.wr_cmd.wlen1 = t3;
- cmd.u.wr_cmd.wlen2 = t1;
- return ndf_submit(tn, &cmd);
-}
-
-static int ndf_build_pre_cmd(struct octeontx_nfc *tn, int cmd1,
- int addr_bytes, u64 page, u32 col, int cmd2)
-{
- struct nand_chip *nand = tn->controller.active;
- struct octeontx_nand_chip *octeontx_nand;
- struct ndf_set_tm_par_cmd *timings;
- int width, page_size, rc;
-
- /* Also called before chip probing is finished */
- if (!nand) {
- timings = &default_timing_parms;
- page_size = default_page_size;
- width = default_width;
- } else {
- octeontx_nand = to_otx_nand(nand);
- timings = &octeontx_nand->timings;
- page_size = nand->mtd.writesize;
- if (nand->options & NAND_BUSWIDTH_16)
- width = 2;
- else
- width = 1;
- }
- rc = ndf_queue_cmd_timing(tn, timings);
- if (rc)
- return rc;
-
- rc = ndf_queue_cmd_bus(tn, NDF_BUS_ACQUIRE);
- if (rc)
- return rc;
-
- rc = ndf_queue_cmd_chip(tn, 1, tn->selected_chip, width);
- if (rc)
- return rc;
-
- rc = ndf_queue_cmd_wait(tn, t1);
- if (rc)
- return rc;
-
- rc = ndf_queue_cmd_cle(tn, cmd1);
- if (rc)
- return rc;
-
- if (addr_bytes) {
- rc = ndf_build_wait_busy(tn);
- if (rc)
- return rc;
-
- rc = ndf_queue_cmd_ale(tn, addr_bytes, nand,
- page, col, page_size);
- if (rc)
- return rc;
- }
-
- /* CLE 2 */
- if (cmd2) {
- rc = ndf_build_wait_busy(tn);
- if (rc)
- return rc;
-
- rc = ndf_queue_cmd_cle(tn, cmd2);
- if (rc)
- return rc;
- }
- return 0;
-}
-
-static int ndf_build_post_cmd(struct octeontx_nfc *tn, int hold_time)
-{
- int rc;
-
- /* Deselect chip */
- rc = ndf_queue_cmd_chip(tn, 0, 0, 0);
- if (rc)
- return rc;
-
- rc = ndf_queue_cmd_wait(tn, t2);
- if (rc)
- return rc;
-
- /* Release bus */
- rc = ndf_queue_cmd_bus(tn, 0);
- if (rc)
- return rc;
-
- rc = ndf_queue_cmd_wait(tn, hold_time);
- if (rc)
- return rc;
-
- /*
- * Last action is ringing the doorbell with number of bus
- * acquire-releases cycles (currently 1).
- */
- writeq(1, tn->base + NDF_DRBELL);
- return 0;
-}
-
-/* Setup the NAND DMA engine for a transfer. */
-static void ndf_setup_dma(struct octeontx_nfc *tn, int is_write,
- dma_addr_t bus_addr, int len)
-{
- u64 dma_cfg;
-
- dma_cfg = FIELD_PREP(NDF_DMA_CFG_RW, is_write) |
- FIELD_PREP(NDF_DMA_CFG_SIZE, (len >> 3) - 1);
- dma_cfg |= NDF_DMA_CFG_EN;
- writeq(bus_addr, tn->base + NDF_DMA_ADR);
- writeq(dma_cfg, tn->base + NDF_DMA_CFG);
-}
-
-static int octeontx_nand_reset(struct octeontx_nfc *tn)
-{
- int rc;
-
- rc = ndf_build_pre_cmd(tn, NAND_CMD_RESET, 0, 0, 0, 0);
- if (rc)
- return rc;
-
- rc = ndf_build_wait_busy(tn);
- if (rc)
- return rc;
-
- rc = ndf_build_post_cmd(tn, t2);
- if (rc)
- return rc;
-
- return 0;
-}
-
-static int ndf_read(struct octeontx_nfc *tn, int cmd1, int addr_bytes,
- u64 page, u32 col, int cmd2, int len)
-{
- dma_addr_t bus_addr = tn->use_status ? tn->stat_addr : tn->buf.dmaaddr;
- struct nand_chip *nand = tn->controller.active;
- int timing_mode, bytes, rc;
- union ndf_cmd cmd;
- u64 start, end;
-
- pr_debug("%s(%p, 0x%x, 0x%x, 0x%llx, 0x%x, 0x%x, 0x%x)\n", __func__,
- tn, cmd1, addr_bytes, page, col, cmd2, len);
- if (!nand)
- timing_mode = default_onfi_timing;
- else
- timing_mode = nand->onfi_timing_mode_default;
-
- /* Build the command and address cycles */
- rc = ndf_build_pre_cmd(tn, cmd1, addr_bytes, page, col, cmd2);
- if (rc) {
- dev_err(tn->dev, "Build pre command failed\n");
- return rc;
- }
-
- /* This waits for some time, then waits for busy to be de-asserted. */
- rc = ndf_build_wait_busy(tn);
- if (rc) {
- dev_err(tn->dev, "Wait timeout\n");
- return rc;
- }
-
- memset(&cmd, 0, sizeof(cmd));
-
- if (timing_mode < 4)
- cmd.u.rd_cmd.opcode = NDF_OP_RD_CMD;
- else
- cmd.u.rd_cmd.opcode = NDF_OP_RD_EDO_CMD;
-
- cmd.u.rd_cmd.data = len;
- cmd.u.rd_cmd.rlen1 = t7;
- cmd.u.rd_cmd.rlen2 = t3;
- cmd.u.rd_cmd.rlen3 = t1;
- cmd.u.rd_cmd.rlen4 = t7;
- rc = ndf_submit(tn, &cmd);
- if (rc) {
- dev_err(tn->dev, "Error submitting command\n");
- return rc;
- }
-
- start = (u64)bus_addr;
- ndf_setup_dma(tn, 0, bus_addr, len);
-
- rc = ndf_build_post_cmd(tn, t2);
- if (rc) {
- dev_err(tn->dev, "Build post command failed\n");
- return rc;
- }
-
- /* Wait for the DMA to complete */
- rc = ndf_wait(tn);
- if (rc) {
- dev_err(tn->dev, "DMA timed out\n");
- return rc;
- }
-
- end = readq(tn->base + NDF_DMA_ADR);
- bytes = end - start;
-
- /* Make sure NDF is really done */
- rc = ndf_wait_idle(tn);
- if (rc) {
- dev_err(tn->dev, "poll idle failed\n");
- return rc;
- }
-
- pr_debug("%s: Read %d bytes\n", __func__, bytes);
- return bytes;
-}
-
-static int octeontx_nand_get_features(struct mtd_info *mtd,
- struct nand_chip *chip, int feature_addr,
- u8 *subfeature_para)
-{
- struct nand_chip *nand = chip;
- struct octeontx_nfc *tn = to_otx_nfc(nand->controller);
- int len = 8;
- int rc;
-
- pr_debug("%s: feature addr: 0x%x\n", __func__, feature_addr);
- memset(tn->buf.dmabuf, 0xff, len);
- tn->buf.data_index = 0;
- tn->buf.data_len = 0;
- rc = ndf_read(tn, NAND_CMD_GET_FEATURES, 1, feature_addr, 0, 0, len);
- if (rc)
- return rc;
-
- memcpy(subfeature_para, tn->buf.dmabuf, ONFI_SUBFEATURE_PARAM_LEN);
-
- return 0;
-}
-
-static int octeontx_nand_set_features(struct mtd_info *mtd,
- struct nand_chip *chip, int feature_addr,
- u8 *subfeature_para)
-{
- struct nand_chip *nand = chip;
- struct octeontx_nfc *tn = to_otx_nfc(nand->controller);
- const int len = ONFI_SUBFEATURE_PARAM_LEN;
- int rc;
-
- rc = ndf_build_pre_cmd(tn, NAND_CMD_SET_FEATURES,
- 1, feature_addr, 0, 0);
- if (rc)
- return rc;
-
- memcpy(tn->buf.dmabuf, subfeature_para, len);
- memset(tn->buf.dmabuf + len, 0, 8 - len);
-
- ndf_setup_dma(tn, 1, tn->buf.dmaaddr, 8);
-
- rc = ndf_queue_cmd_write(tn, 8);
- if (rc)
- return rc;
-
- rc = ndf_build_wait_busy(tn);
- if (rc)
- return rc;
-
- rc = ndf_build_post_cmd(tn, t2);
- if (rc)
- return rc;
-
- return 0;
-}
-
-/*
- * Read a page from NAND. If the buffer has room, the out of band
- * data will be included.
- */
-static int ndf_page_read(struct octeontx_nfc *tn, u64 page, int col, int len)
-{
- debug("%s(%p, 0x%llx, 0x%x, 0x%x) active: %p\n", __func__,
- tn, page, col, len, tn->controller.active);
- struct nand_chip *nand = tn->controller.active;
- struct octeontx_nand_chip *chip = to_otx_nand(nand);
- int addr_bytes = chip->row_bytes + chip->col_bytes;
-
- memset(tn->buf.dmabuf, 0xff, len);
- return ndf_read(tn, NAND_CMD_READ0, addr_bytes,
- page, col, NAND_CMD_READSTART, len);
-}
-
-/* Erase a NAND block */
-static int ndf_block_erase(struct octeontx_nfc *tn, u64 page_addr)
-{
- struct nand_chip *nand = tn->controller.active;
- struct octeontx_nand_chip *chip = to_otx_nand(nand);
- int addr_bytes = chip->row_bytes;
- int rc;
-
- rc = ndf_build_pre_cmd(tn, NAND_CMD_ERASE1, addr_bytes,
- page_addr, 0, NAND_CMD_ERASE2);
- if (rc)
- return rc;
-
- /* Wait for R_B to signal erase is complete */
- rc = ndf_build_wait_busy(tn);
- if (rc)
- return rc;
-
- rc = ndf_build_post_cmd(tn, t2);
- if (rc)
- return rc;
-
- /* Wait until the command queue is idle */
- return ndf_wait_idle(tn);
-}
-
-/*
- * Write a page (or less) to NAND.
- */
-static int ndf_page_write(struct octeontx_nfc *tn, int page)
-{
- int len, rc;
- struct nand_chip *nand = tn->controller.active;
- struct octeontx_nand_chip *chip = to_otx_nand(nand);
- int addr_bytes = chip->row_bytes + chip->col_bytes;
-
- len = tn->buf.data_len - tn->buf.data_index;
- chip->oob_only = (tn->buf.data_index >= nand->mtd.writesize);
- WARN_ON_ONCE(len & 0x7);
-
- ndf_setup_dma(tn, 1, tn->buf.dmaaddr + tn->buf.data_index, len);
- rc = ndf_build_pre_cmd(tn, NAND_CMD_SEQIN, addr_bytes, page, 0, 0);
- if (rc)
- return rc;
-
- rc = ndf_queue_cmd_write(tn, len);
- if (rc)
- return rc;
-
- rc = ndf_queue_cmd_cle(tn, NAND_CMD_PAGEPROG);
- if (rc)
- return rc;
-
- /* Wait for R_B to signal program is complete */
- rc = ndf_build_wait_busy(tn);
- if (rc)
- return rc;
-
- rc = ndf_build_post_cmd(tn, t2);
- if (rc)
- return rc;
-
- /* Wait for the DMA to complete */
- rc = ndf_wait(tn);
- if (rc)
- return rc;
-
- /* Data transfer is done but NDF is not, it is waiting for R/B# */
- return ndf_wait_idle(tn);
-}
-
-static void octeontx_nand_cmdfunc(struct mtd_info *mtd, unsigned int command,
- int column, int page_addr)
-{
- struct nand_chip *nand = mtd_to_nand(mtd);
- struct octeontx_nand_chip *octeontx_nand = to_otx_nand(nand);
- struct octeontx_nfc *tn = to_otx_nfc(nand->controller);
- int rc;
-
- tn->selected_chip = octeontx_nand->cs;
- if (tn->selected_chip < 0 || tn->selected_chip >= NAND_MAX_CHIPS) {
- dev_err(tn->dev, "invalid chip select\n");
- return;
- }
-
- tn->use_status = false;
-
- pr_debug("%s(%p, 0x%x, 0x%x, 0x%x) cs: %d\n", __func__, mtd, command,
- column, page_addr, tn->selected_chip);
- switch (command) {
- case NAND_CMD_READID:
- tn->buf.data_index = 0;
- octeontx_nand->oob_only = false;
- rc = ndf_read(tn, command, 1, column, 0, 0, 8);
- if (rc < 0)
- dev_err(tn->dev, "READID failed with %d\n", rc);
- else
- tn->buf.data_len = rc;
- break;
-
- case NAND_CMD_READOOB:
- octeontx_nand->oob_only = true;
- tn->buf.data_index = 0;
- tn->buf.data_len = 0;
- rc = ndf_page_read(tn, page_addr, column, mtd->oobsize);
- if (rc < mtd->oobsize)
- dev_err(tn->dev, "READOOB failed with %d\n",
- tn->buf.data_len);
- else
- tn->buf.data_len = rc;
- break;
-
- case NAND_CMD_READ0:
- octeontx_nand->oob_only = false;
- tn->buf.data_index = 0;
- tn->buf.data_len = 0;
- rc = ndf_page_read(tn, page_addr, column,
- mtd->writesize + mtd->oobsize);
-
- if (rc < mtd->writesize + mtd->oobsize)
- dev_err(tn->dev, "READ0 failed with %d\n", rc);
- else
- tn->buf.data_len = rc;
- break;
-
- case NAND_CMD_STATUS:
- /* used in oob/not states */
- tn->use_status = true;
- rc = ndf_read(tn, command, 0, 0, 0, 0, 8);
- if (rc < 0)
- dev_err(tn->dev, "STATUS failed with %d\n", rc);
- break;
-
- case NAND_CMD_RESET:
- /* used in oob/not states */
- rc = octeontx_nand_reset(tn);
- if (rc < 0)
- dev_err(tn->dev, "RESET failed with %d\n", rc);
- break;
-
- case NAND_CMD_PARAM:
- octeontx_nand->oob_only = false;
- tn->buf.data_index = 0;
- rc = ndf_read(tn, command, 1, 0, 0, 0,
- min(tn->buf.dmabuflen, 3 * 512));
- if (rc < 0)
- dev_err(tn->dev, "PARAM failed with %d\n", rc);
- else
- tn->buf.data_len = rc;
- break;
-
- case NAND_CMD_RNDOUT:
- tn->buf.data_index = column;
- break;
-
- case NAND_CMD_ERASE1:
- if (ndf_block_erase(tn, page_addr))
- dev_err(tn->dev, "ERASE1 failed\n");
- break;
-
- case NAND_CMD_ERASE2:
- /* We do all erase processing in the first command, so ignore
- * this one.
- */
- break;
-
- case NAND_CMD_SEQIN:
- octeontx_nand->oob_only = (column >= mtd->writesize);
- tn->buf.data_index = column;
- tn->buf.data_len = column;
-
- octeontx_nand->selected_page = page_addr;
- break;
-
- case NAND_CMD_PAGEPROG:
- rc = ndf_page_write(tn, octeontx_nand->selected_page);
- if (rc)
- dev_err(tn->dev, "PAGEPROG failed with %d\n", rc);
- break;
-
- case NAND_CMD_SET_FEATURES:
- octeontx_nand->oob_only = false;
- /* assume tn->buf.data_len == 4 of data has been set there */
- rc = octeontx_nand_set_features(mtd, nand,
- page_addr, tn->buf.dmabuf);
- if (rc)
- dev_err(tn->dev, "SET_FEATURES failed with %d\n", rc);
- break;
-
- case NAND_CMD_GET_FEATURES:
- octeontx_nand->oob_only = false;
- rc = octeontx_nand_get_features(mtd, nand,
- page_addr, tn->buf.dmabuf);
- if (!rc) {
- tn->buf.data_index = 0;
- tn->buf.data_len = 4;
- } else {
- dev_err(tn->dev, "GET_FEATURES failed with %d\n", rc);
- }
- break;
-
- default:
- WARN_ON_ONCE(1);
- dev_err(tn->dev, "unhandled nand cmd: %x\n", command);
- }
-}
-
-static int octeontx_nand_waitfunc(struct mtd_info *mtd, struct nand_chip *chip)
-{
- struct octeontx_nfc *tn = to_otx_nfc(chip->controller);
- int ret;
-
- ret = ndf_wait_idle(tn);
- return (ret < 0) ? -EIO : 0;
-}
-
-/* check compatibility with ONFI timing mode#N, and optionally apply */
-/* TODO: Implement chipnr support? */
-static int octeontx_nand_setup_dat_intf(struct mtd_info *mtd, int chipnr,
- const struct nand_data_interface *conf)
-{
- static const bool check_only;
- struct nand_chip *nand = mtd_to_nand(mtd);
- struct octeontx_nand_chip *chip = to_otx_nand(nand);
- static u64 t_wc_n[MAX_ONFI_MODE + 2]; /* cache a mode signature */
- int mode; /* deduced mode number, for reporting and restricting */
- int rc;
-
- /*
- * Cache timing modes for reporting, and reducing needless change.
- *
- * Challenge: caller does not pass ONFI mode#, but reporting the mode
- * and restricting to a maximum, or a list, are useful for diagnosing
- * new hardware. So use tWC_min, distinct and monotonic across modes,
- * to discover the requested/accepted mode number
- */
- for (mode = MAX_ONFI_MODE; mode >= 0 && !t_wc_n[0]; mode--) {
- const struct nand_sdr_timings *t;
-
- t = onfi_async_timing_mode_to_sdr_timings(mode);
- if (!t)
- continue;
- t_wc_n[mode] = t->tWC_min;
- }
-
- if (!conf) {
- rc = -EINVAL;
- } else if (check_only) {
- rc = 0;
- } else if (nand->data_interface &&
- chip->iface_set && chip->iface_mode == mode) {
- /*
- * Cases:
- * - called from nand_reset, which clears DDR timing
- * mode back to SDR. BUT if we're already in SDR,
- * timing mode persists over resets.
- * While mtd/nand layer only supports SDR,
- * this is always safe. And this driver only supports SDR.
- *
- * - called from post-power-event nand_reset (maybe
- * NFC+flash power down, or system hibernate.
- * Address this when CONFIG_PM support added
- */
- rc = 0;
- } else {
- rc = octeontx_nfc_chip_set_timings(chip, &conf->timings.sdr);
- if (!rc) {
- chip->iface_mode = mode;
- chip->iface_set = true;
- }
- }
- return rc;
-}
-
-static void octeontx_bch_reset(void)
-{
-}
-
-/*
- * Given a page, calculate the ECC code
- *
- * chip: Pointer to NAND chip data structure
- * buf: Buffer to calculate ECC on
- * code: Buffer to hold ECC data
- *
- * Return 0 on success or -1 on failure
- */
-static int octeontx_nand_bch_calculate_ecc_internal(struct mtd_info *mtd,
- dma_addr_t ihandle,
- u8 *code)
-{
- struct nand_chip *nand = mtd_to_nand(mtd);
- struct octeontx_nfc *tn = to_otx_nfc(nand->controller);
- int rc;
- int i;
- static u8 *ecc_buffer;
- static int ecc_size;
- static unsigned long ecc_handle;
- union bch_resp *r = tn->bch_resp;
-
- if (!ecc_buffer || ecc_size < nand->ecc.size) {
- ecc_size = nand->ecc.size;
- ecc_buffer = dma_alloc_coherent(ecc_size,
- (unsigned long *)&ecc_handle);
- }
-
- memset(ecc_buffer, 0, nand->ecc.bytes);
-
- r->u16 = 0;
- __iowmb(); /* flush done=0 before making request */
-
- rc = octeontx_bch_encode(bch_vf, ihandle, nand->ecc.size,
- nand->ecc.strength,
- (dma_addr_t)ecc_handle, tn->bch_rhandle);
-
- if (!rc) {
- octeontx_bch_wait(bch_vf, r, tn->bch_rhandle);
- } else {
- dev_err(tn->dev, "octeontx_bch_encode failed\n");
- return -1;
- }
-
- if (!r->s.done || r->s.uncorrectable) {
- dev_err(tn->dev,
- "%s timeout, done:%d uncorr:%d corr:%d erased:%d\n",
- __func__, r->s.done, r->s.uncorrectable,
- r->s.num_errors, r->s.erased);
- octeontx_bch_reset();
- return -1;
- }
-
- memcpy(code, ecc_buffer, nand->ecc.bytes);
-
- for (i = 0; i < nand->ecc.bytes; i++)
- code[i] ^= tn->eccmask[i];
-
- return tn->bch_resp->s.num_errors;
-}
-
-/*
- * Given a page, calculate the ECC code
- *
- * mtd: MTD block structure
- * dat: raw data (unused)
- * ecc_code: buffer for ECC
- */
-static int octeontx_nand_bch_calculate(struct mtd_info *mtd,
- const u8 *dat, u8 *ecc_code)
-{
- struct nand_chip *nand = mtd_to_nand(mtd);
- dma_addr_t handle = dma_map_single((u8 *)dat,
- nand->ecc.size, DMA_TO_DEVICE);
- int ret;
-
- ret = octeontx_nand_bch_calculate_ecc_internal(mtd, handle,
- (void *)ecc_code);
-
- return ret;
-}
-
-/*
- * Detect and correct multi-bit ECC for a page
- *
- * mtd: MTD block structure
- * dat: raw data read from the chip
- * read_ecc: ECC from the chip (unused)
- * isnull: unused
- *
- * Returns number of bits corrected or -1 if unrecoverable
- */
-static int octeontx_nand_bch_correct(struct mtd_info *mtd, u_char *dat,
- u_char *read_ecc, u_char *isnull)
-{
- struct nand_chip *nand = mtd_to_nand(mtd);
- struct octeontx_nfc *tn = to_otx_nfc(nand->controller);
- int i = nand->ecc.size + nand->ecc.bytes;
- static u8 *data_buffer;
- static dma_addr_t ihandle;
- static int buffer_size;
- dma_addr_t ohandle;
- union bch_resp *r = tn->bch_resp;
- int rc;
-
- if (i > buffer_size) {
- if (buffer_size)
- free(data_buffer);
- data_buffer = dma_alloc_coherent(i,
- (unsigned long *)&ihandle);
- if (!data_buffer) {
- dev_err(tn->dev,
- "%s: Could not allocate %d bytes for buffer\n",
- __func__, i);
- goto error;
- }
- buffer_size = i;
- }
-
- memcpy(data_buffer, dat, nand->ecc.size);
- memcpy(data_buffer + nand->ecc.size, read_ecc, nand->ecc.bytes);
-
- for (i = 0; i < nand->ecc.bytes; i++)
- data_buffer[nand->ecc.size + i] ^= tn->eccmask[i];
-
- r->u16 = 0;
- __iowmb(); /* flush done=0 before making request */
-
- ohandle = dma_map_single(dat, nand->ecc.size, DMA_FROM_DEVICE);
- rc = octeontx_bch_decode(bch_vf, ihandle, nand->ecc.size,
- nand->ecc.strength, ohandle, tn->bch_rhandle);
-
- if (!rc)
- octeontx_bch_wait(bch_vf, r, tn->bch_rhandle);
-
- if (rc) {
- dev_err(tn->dev, "octeontx_bch_decode failed\n");
- goto error;
- }
-
- if (!r->s.done) {
- dev_err(tn->dev, "Error: BCH engine timeout\n");
- octeontx_bch_reset();
- goto error;
- }
-
- if (r->s.erased) {
- debug("Info: BCH block is erased\n");
- return 0;
- }
-
- if (r->s.uncorrectable) {
- debug("Cannot correct NAND block, response: 0x%x\n",
- r->u16);
- goto error;
- }
-
- return r->s.num_errors;
-
-error:
- debug("Error performing bch correction\n");
- return -1;
-}
-
-void octeontx_nand_bch_hwctl(struct mtd_info *mtd, int mode)
-{
- /* Do nothing. */
-}
-
-static int octeontx_nand_hw_bch_read_page(struct mtd_info *mtd,
- struct nand_chip *chip, u8 *buf,
- int oob_required, int page)
-{
- struct nand_chip *nand = mtd_to_nand(mtd);
- struct octeontx_nfc *tn = to_otx_nfc(nand->controller);
- int i, eccsize = chip->ecc.size, ret;
- int eccbytes = chip->ecc.bytes;
- int eccsteps = chip->ecc.steps;
- u8 *p;
- u8 *ecc_code = chip->buffers->ecccode;
- unsigned int max_bitflips = 0;
-
- /* chip->read_buf() insists on sequential order, we do OOB first */
- memcpy(chip->oob_poi, tn->buf.dmabuf + mtd->writesize, mtd->oobsize);
-
- /* Use private buffer as input for ECC correction */
- p = tn->buf.dmabuf;
-
- ret = mtd_ooblayout_get_eccbytes(mtd, ecc_code, chip->oob_poi, 0,
- chip->ecc.total);
- if (ret)
- return ret;
-
- for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
- int stat;
-
- debug("Correcting block offset %lx, ecc offset %x\n",
- p - buf, i);
- stat = chip->ecc.correct(mtd, p, &ecc_code[i], NULL);
-
- if (stat < 0) {
- mtd->ecc_stats.failed++;
- debug("Cannot correct NAND page %d\n", page);
- } else {
- mtd->ecc_stats.corrected += stat;
- max_bitflips = max_t(unsigned int, max_bitflips, stat);
- }
- }
-
- /* Copy corrected data to caller's buffer now */
- memcpy(buf, tn->buf.dmabuf, mtd->writesize);
-
- return max_bitflips;
-}
-
-static int octeontx_nand_hw_bch_write_page(struct mtd_info *mtd,
- struct nand_chip *chip,
- const u8 *buf, int oob_required,
- int page)
-{
- struct octeontx_nfc *tn = to_otx_nfc(chip->controller);
- int i, eccsize = chip->ecc.size, ret;
- int eccbytes = chip->ecc.bytes;
- int eccsteps = chip->ecc.steps;
- const u8 *p;
- u8 *ecc_calc = chip->buffers->ecccalc;
-
- debug("%s(buf?%p, oob%d p%x)\n",
- __func__, buf, oob_required, page);
- for (i = 0; i < chip->ecc.total; i++)
- ecc_calc[i] = 0xFF;
-
- /* Copy the page data from caller's buffers to private buffer */
- chip->write_buf(mtd, buf, mtd->writesize);
- /* Use private date as source for ECC calculation */
- p = tn->buf.dmabuf;
-
- /* Hardware ECC calculation */
- for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
- int ret;
-
- ret = chip->ecc.calculate(mtd, p, &ecc_calc[i]);
-
- if (ret < 0)
- debug("calculate(mtd, p?%p, &ecc_calc[%d]?%p) returned %d\n",
- p, i, &ecc_calc[i], ret);
-
- debug("block offset %lx, ecc offset %x\n", p - buf, i);
- }
-
- ret = mtd_ooblayout_set_eccbytes(mtd, ecc_calc, chip->oob_poi, 0,
- chip->ecc.total);
- if (ret)
- return ret;
-
- /* Store resulting OOB into private buffer, will be sent to HW */
- chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
-
- return 0;
-}
-
-/**
- * nand_write_page_raw - [INTERN] raw page write function
- * @mtd: mtd info structure
- * @chip: nand chip info structure
- * @buf: data buffer
- * @oob_required: must write chip->oob_poi to OOB
- * @page: page number to write
- *
- * Not for syndrome calculating ECC controllers, which use a special oob layout.
- */
-static int octeontx_nand_write_page_raw(struct mtd_info *mtd,
- struct nand_chip *chip,
- const u8 *buf, int oob_required,
- int page)
-{
- chip->write_buf(mtd, buf, mtd->writesize);
- if (oob_required)
- chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
-
- return 0;
-}
-
-/**
- * octeontx_nand_write_oob_std - [REPLACEABLE] the most common OOB data write
- * function
- * @mtd: mtd info structure
- * @chip: nand chip info structure
- * @page: page number to write
- */
-static int octeontx_nand_write_oob_std(struct mtd_info *mtd,
- struct nand_chip *chip,
- int page)
-{
- int status = 0;
- const u8 *buf = chip->oob_poi;
- int length = mtd->oobsize;
-
- chip->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize, page);
- chip->write_buf(mtd, buf, length);
- /* Send command to program the OOB data */
- chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
-
- status = chip->waitfunc(mtd, chip);
-
- return status & NAND_STATUS_FAIL ? -EIO : 0;
-}
-
-/**
- * octeontx_nand_read_page_raw - [INTERN] read raw page data without ecc
- * @mtd: mtd info structure
- * @chip: nand chip info structure
- * @buf: buffer to store read data
- * @oob_required: caller requires OOB data read to chip->oob_poi
- * @page: page number to read
- *
- * Not for syndrome calculating ECC controllers, which use a special oob layout.
- */
-static int octeontx_nand_read_page_raw(struct mtd_info *mtd,
- struct nand_chip *chip,
- u8 *buf, int oob_required, int page)
-{
- chip->read_buf(mtd, buf, mtd->writesize);
- if (oob_required)
- chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
- return 0;
-}
-
-static int octeontx_nand_read_oob_std(struct mtd_info *mtd,
- struct nand_chip *chip,
- int page)
-
-{
- chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page);
- chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
- return 0;
-}
-
-static int octeontx_nand_calc_bch_ecc_strength(struct nand_chip *nand)
-{
- struct mtd_info *mtd = nand_to_mtd(nand);
- struct nand_ecc_ctrl *ecc = &nand->ecc;
- struct octeontx_nfc *tn = to_otx_nfc(nand->controller);
- int nsteps = mtd->writesize / ecc->size;
- int oobchunk = mtd->oobsize / nsteps;
-
- /* ecc->strength determines ecc_level and OOB's ecc_bytes. */
- const u8 strengths[] = {4, 8, 16, 24, 32, 40, 48, 56, 60, 64};
- /* first set the desired ecc_level to match strengths[] */
- int index = ARRAY_SIZE(strengths) - 1;
- int need;
-
- while (index > 0 && !(ecc->options & NAND_ECC_MAXIMIZE) &&
- strengths[index - 1] >= ecc->strength)
- index--;
-
- do {
- need = DIV_ROUND_UP(15 * strengths[index], 8);
- if (need <= oobchunk - 2)
- break;
- } while (index > 0);
-
- debug("%s: steps ds: %d, strength ds: %d\n", __func__,
- nand->ecc_step_ds, nand->ecc_strength_ds);
- ecc->strength = strengths[index];
- ecc->bytes = need;
- debug("%s: strength: %d, bytes: %d\n", __func__, ecc->strength,
- ecc->bytes);
-
- if (!tn->eccmask)
- tn->eccmask = devm_kzalloc(tn->dev, ecc->bytes, GFP_KERNEL);
- if (!tn->eccmask)
- return -ENOMEM;
-
- return 0;
-}
-
-/* sample the BCH signature of an erased (all 0xff) page,
- * to XOR into all page traffic, so erased pages have no ECC errors
- */
-static int octeontx_bch_save_empty_eccmask(struct nand_chip *nand)
-{
- struct mtd_info *mtd = nand_to_mtd(nand);
- struct octeontx_nfc *tn = to_otx_nfc(nand->controller);
- unsigned int eccsize = nand->ecc.size;
- unsigned int eccbytes = nand->ecc.bytes;
- u8 erased_ecc[eccbytes];
- unsigned long erased_handle;
- unsigned char *erased_page = dma_alloc_coherent(eccsize,
- &erased_handle);
- int i;
- int rc = 0;
-
- if (!erased_page)
- return -ENOMEM;
-
- memset(erased_page, 0xff, eccsize);
- memset(erased_ecc, 0, eccbytes);
-
- rc = octeontx_nand_bch_calculate_ecc_internal(mtd,
- (dma_addr_t)erased_handle,
- erased_ecc);
-
- free(erased_page);
-
- for (i = 0; i < eccbytes; i++)
- tn->eccmask[i] = erased_ecc[i] ^ 0xff;
-
- return rc;
-}
-
-static void octeontx_nfc_chip_sizing(struct nand_chip *nand)
-{
- struct octeontx_nand_chip *chip = to_otx_nand(nand);
- struct mtd_info *mtd = nand_to_mtd(nand);
- struct nand_ecc_ctrl *ecc = &nand->ecc;
-
- chip->row_bytes = nand->onfi_params.addr_cycles & 0xf;
- chip->col_bytes = nand->onfi_params.addr_cycles >> 4;
- debug("%s(%p) row bytes: %d, col bytes: %d, ecc mode: %d\n",
- __func__, nand, chip->row_bytes, chip->col_bytes, ecc->mode);
-
- /*
- * HW_BCH using OcteonTX BCH engine, or SOFT_BCH laid out in
- * HW_BCH-compatible fashion, depending on devtree advice
- * and kernel config.
- * BCH/NFC hardware capable of subpage ops, not implemented.
- */
- mtd_set_ooblayout(mtd, &nand_ooblayout_lp_ops);
- nand->options |= NAND_NO_SUBPAGE_WRITE;
- debug("%s: start steps: %d, size: %d, bytes: %d\n",
- __func__, ecc->steps, ecc->size, ecc->bytes);
- debug("%s: step ds: %d, strength ds: %d\n", __func__,
- nand->ecc_step_ds, nand->ecc_strength_ds);
-
- if (ecc->mode != NAND_ECC_NONE) {
- int nsteps = ecc->steps ? ecc->steps : 1;
-
- if (ecc->size && ecc->size != mtd->writesize)
- nsteps = mtd->writesize / ecc->size;
- else if (mtd->writesize > def_ecc_size &&
- !(mtd->writesize & (def_ecc_size - 1)))
- nsteps = mtd->writesize / def_ecc_size;
- ecc->steps = nsteps;
- ecc->size = mtd->writesize / nsteps;
- ecc->bytes = mtd->oobsize / nsteps;
-
- if (nand->ecc_strength_ds)
- ecc->strength = nand->ecc_strength_ds;
- if (nand->ecc_step_ds)
- ecc->size = nand->ecc_step_ds;
- /*
- * no subpage ops, but set subpage-shift to match ecc->steps
- * so mtd_nandbiterrs tests appropriate boundaries
- */
- if (!mtd->subpage_sft && !(ecc->steps & (ecc->steps - 1)))
- mtd->subpage_sft = fls(ecc->steps) - 1;
-
- if (IS_ENABLED(CONFIG_NAND_OCTEONTX_HW_ECC)) {
- debug("%s: ecc mode: %d\n", __func__, ecc->mode);
- if (ecc->mode != NAND_ECC_SOFT &&
- !octeontx_nand_calc_bch_ecc_strength(nand)) {
- struct octeontx_nfc *tn =
- to_otx_nfc(nand->controller);
-
- debug("Using hardware BCH engine support\n");
- ecc->mode = NAND_ECC_HW_SYNDROME;
- ecc->read_page = octeontx_nand_hw_bch_read_page;
- ecc->write_page =
- octeontx_nand_hw_bch_write_page;
- ecc->read_page_raw =
- octeontx_nand_read_page_raw;
- ecc->write_page_raw =
- octeontx_nand_write_page_raw;
- ecc->read_oob = octeontx_nand_read_oob_std;
- ecc->write_oob = octeontx_nand_write_oob_std;
-
- ecc->calculate = octeontx_nand_bch_calculate;
- ecc->correct = octeontx_nand_bch_correct;
- ecc->hwctl = octeontx_nand_bch_hwctl;
-
- debug("NAND chip %d using hw_bch\n",
- tn->selected_chip);
- debug(" %d bytes ECC per %d byte block\n",
- ecc->bytes, ecc->size);
- debug(" for %d bits of correction per block.",
- ecc->strength);
- octeontx_nand_calc_ecc_layout(nand);
- octeontx_bch_save_empty_eccmask(nand);
- }
- }
- }
-}
-
-static int octeontx_nfc_chip_init(struct octeontx_nfc *tn, struct udevice *dev,
- ofnode node)
-{
- struct octeontx_nand_chip *chip;
- struct nand_chip *nand;
- struct mtd_info *mtd;
- int ret;
-
- chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
- if (!chip)
- return -ENOMEM;
-
- debug("%s: Getting chip select\n", __func__);
- ret = ofnode_read_s32(node, "reg", &chip->cs);
- if (ret) {
- dev_err(dev, "could not retrieve reg property: %d\n", ret);
- return ret;
- }
-
- if (chip->cs >= NAND_MAX_CHIPS) {
- dev_err(dev, "invalid reg value: %u (max CS = 7)\n", chip->cs);
- return -EINVAL;
- }
- debug("%s: chip select: %d\n", __func__, chip->cs);
- nand = &chip->nand;
- nand->controller = &tn->controller;
- if (!tn->controller.active)
- tn->controller.active = nand;
-
- debug("%s: Setting flash node\n", __func__);
- nand_set_flash_node(nand, node);
-
- nand->options = 0;
- nand->select_chip = octeontx_nand_select_chip;
- nand->cmdfunc = octeontx_nand_cmdfunc;
- nand->waitfunc = octeontx_nand_waitfunc;
- nand->read_byte = octeontx_nand_read_byte;
- nand->read_buf = octeontx_nand_read_buf;
- nand->write_buf = octeontx_nand_write_buf;
- nand->onfi_set_features = octeontx_nand_set_features;
- nand->onfi_get_features = octeontx_nand_get_features;
- nand->setup_data_interface = octeontx_nand_setup_dat_intf;
-
- mtd = nand_to_mtd(nand);
- debug("%s: mtd: %p\n", __func__, mtd);
- mtd->dev->parent = dev;
-
- debug("%s: NDF_MISC: 0x%llx\n", __func__,
- readq(tn->base + NDF_MISC));
-
- /* TODO: support more then 1 chip */
- debug("%s: Scanning identification\n", __func__);
- ret = nand_scan_ident(mtd, 1, NULL);
- if (ret)
- return ret;
-
- debug("%s: Sizing chip\n", __func__);
- octeontx_nfc_chip_sizing(nand);
-
- debug("%s: Scanning tail\n", __func__);
- ret = nand_scan_tail(mtd);
- if (ret) {
- dev_err(dev, "nand_scan_tail failed: %d\n", ret);
- return ret;
- }
-
- debug("%s: Registering mtd\n", __func__);
- ret = nand_register(0, mtd);
-
- debug("%s: Adding tail\n", __func__);
- list_add_tail(&chip->node, &tn->chips);
- return 0;
-}
-
-static int octeontx_nfc_chips_init(struct octeontx_nfc *tn)
-{
- struct udevice *dev = tn->dev;
- ofnode node = dev_ofnode(dev);
- ofnode nand_node;
- int nr_chips = of_get_child_count(node);
- int ret;
-
- debug("%s: node: %s\n", __func__, ofnode_get_name(node));
- debug("%s: %d chips\n", __func__, nr_chips);
- if (nr_chips > NAND_MAX_CHIPS) {
- dev_err(dev, "too many NAND chips: %d\n", nr_chips);
- return -EINVAL;
- }
-
- if (!nr_chips) {
- debug("no DT NAND chips found\n");
- return -ENODEV;
- }
-
- pr_info("%s: scanning %d chips DTs\n", __func__, nr_chips);
-
- ofnode_for_each_subnode(nand_node, node) {
- debug("%s: Calling octeontx_nfc_chip_init(%p, %s, %ld)\n",
- __func__, tn, dev->name, nand_node.of_offset);
- ret = octeontx_nfc_chip_init(tn, dev, nand_node);
- if (ret)
- return ret;
- }
- return 0;
-}
-
-/* Reset NFC and initialize registers. */
-static int octeontx_nfc_init(struct octeontx_nfc *tn)
-{
- const struct nand_sdr_timings *timings;
- u64 ndf_misc;
- int rc;
-
- /* Initialize values and reset the fifo */
- ndf_misc = readq(tn->base + NDF_MISC);
-
- ndf_misc &= ~NDF_MISC_EX_DIS;
- ndf_misc |= (NDF_MISC_BT_DIS | NDF_MISC_RST_FF);
- writeq(ndf_misc, tn->base + NDF_MISC);
- debug("%s: NDF_MISC: 0x%llx\n", __func__, readq(tn->base + NDF_MISC));
-
- /* Bring the fifo out of reset */
- ndf_misc &= ~(NDF_MISC_RST_FF);
-
- /* Maximum of co-processor cycles for glitch filtering */
- ndf_misc |= FIELD_PREP(NDF_MISC_WAIT_CNT, 0x3f);
-
- writeq(ndf_misc, tn->base + NDF_MISC);
-
- /* Set timing parameters to onfi mode 0 for probing */
- timings = onfi_async_timing_mode_to_sdr_timings(0);
- if (IS_ERR(timings))
- return PTR_ERR(timings);
- rc = set_default_timings(tn, timings);
- if (rc)
- return rc;
-
- return 0;
-}
-
-static int octeontx_pci_nand_probe(struct udevice *dev)
-{
- struct octeontx_nfc *tn = dev_get_priv(dev);
- int ret;
- static bool probe_done;
-
- debug("%s(%s) tn: %p\n", __func__, dev->name, tn);
- if (probe_done)
- return 0;
-
- if (IS_ENABLED(CONFIG_NAND_OCTEONTX_HW_ECC)) {
- bch_vf = octeontx_bch_getv();
- if (!bch_vf) {
- struct octeontx_probe_device *probe_dev;
-
- debug("%s: bch not yet initialized\n", __func__);
- probe_dev = calloc(sizeof(*probe_dev), 1);
- if (!probe_dev) {
- printf("%s: Out of memory\n", __func__);
- return -ENOMEM;
- }
- probe_dev->dev = dev;
- INIT_LIST_HEAD(&probe_dev->list);
- list_add_tail(&probe_dev->list,
- &octeontx_pci_nand_deferred_devices);
- debug("%s: Defering probe until after BCH initialization\n",
- __func__);
- return 0;
- }
- }
-
- tn->dev = dev;
- INIT_LIST_HEAD(&tn->chips);
-
- tn->base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, 0, 0, PCI_REGION_TYPE, PCI_REGION_MEM);
- if (!tn->base) {
- ret = -EINVAL;
- goto release;
- }
- debug("%s: bar at %p\n", __func__, tn->base);
- tn->buf.dmabuflen = NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZE;
- tn->buf.dmabuf = dma_alloc_coherent(tn->buf.dmabuflen,
- (unsigned long *)&tn->buf.dmaaddr);
- if (!tn->buf.dmabuf) {
- ret = -ENOMEM;
- debug("%s: Could not allocate DMA buffer\n", __func__);
- goto unclk;
- }
-
- /* one hw-bch response, for one outstanding transaction */
- tn->bch_resp = dma_alloc_coherent(sizeof(*tn->bch_resp),
- (unsigned long *)&tn->bch_rhandle);
-
- tn->stat = dma_alloc_coherent(8, (unsigned long *)&tn->stat_addr);
- if (!tn->stat || !tn->bch_resp) {
- debug("%s: Could not allocate bch status or response\n",
- __func__);
- ret = -ENOMEM;
- goto unclk;
- }
-
- debug("%s: Calling octeontx_nfc_init()\n", __func__);
- octeontx_nfc_init(tn);
- debug("%s: Initializing chips\n", __func__);
- ret = octeontx_nfc_chips_init(tn);
- debug("%s: init chips ret: %d\n", __func__, ret);
- if (ret) {
- if (ret != -ENODEV)
- dev_err(dev, "failed to init nand chips\n");
- goto unclk;
- }
- dev_info(dev, "probed\n");
- return 0;
-
-unclk:
-release:
- return ret;
-}
-
-int octeontx_pci_nand_disable(struct udevice *dev)
-{
- struct octeontx_nfc *tn = dev_get_priv(dev);
- u64 dma_cfg;
- u64 ndf_misc;
-
- debug("%s: Disabling NAND device %s\n", __func__, dev->name);
- dma_cfg = readq(tn->base + NDF_DMA_CFG);
- dma_cfg &= ~NDF_DMA_CFG_EN;
- dma_cfg |= NDF_DMA_CFG_CLR;
- writeq(dma_cfg, tn->base + NDF_DMA_CFG);
-
- /* Disable execution and put FIFO in reset mode */
- ndf_misc = readq(tn->base + NDF_MISC);
- ndf_misc |= NDF_MISC_EX_DIS | NDF_MISC_RST_FF;
- writeq(ndf_misc, tn->base + NDF_MISC);
- ndf_misc &= ~NDF_MISC_RST_FF;
- writeq(ndf_misc, tn->base + NDF_MISC);
-#ifdef DEBUG
- printf("%s: NDF_MISC: 0x%llx\n", __func__, readq(tn->base + NDF_MISC));
-#endif
- /* Clear any interrupts and enable bits */
- writeq(~0ull, tn->base + NDF_INT_ENA_W1C);
- writeq(~0ull, tn->base + NDF_INT);
- debug("%s: NDF_ST_REG: 0x%llx\n", __func__,
- readq(tn->base + NDF_ST_REG));
- return 0;
-}
-
-/**
- * Since it's possible (and even likely) that the NAND device will be probed
- * before the BCH device has been probed, we may need to defer the probing.
- *
- * In this case, the initial probe returns success but the actual probing
- * is deferred until the BCH VF has been probed.
- *
- * Return: 0 for success, otherwise error
- */
-int octeontx_pci_nand_deferred_probe(void)
-{
- int rc = 0;
- struct octeontx_probe_device *pdev;
-
- debug("%s: Performing deferred probing\n", __func__);
- list_for_each_entry(pdev, &octeontx_pci_nand_deferred_devices, list) {
- debug("%s: Probing %s\n", __func__, pdev->dev->name);
- dev_get_flags(pdev->dev) &= ~DM_FLAG_ACTIVATED;
- rc = device_probe(pdev->dev);
- if (rc && rc != -ENODEV) {
- printf("%s: Error %d with deferred probe of %s\n",
- __func__, rc, pdev->dev->name);
- break;
- }
- }
- return rc;
-}
-
-static const struct pci_device_id octeontx_nfc_pci_id_table[] = {
- { PCI_VDEVICE(CAVIUM, 0xA04F) },
- {}
-};
-
-static int octeontx_nand_of_to_plat(struct udevice *dev)
-{
- return 0;
-}
-
-static const struct udevice_id octeontx_nand_ids[] = {
- { .compatible = "cavium,cn8130-nand" },
- { },
-};
-
-U_BOOT_DRIVER(octeontx_pci_nand) = {
- .name = OCTEONTX_NAND_DRIVER_NAME,
- .id = UCLASS_MTD,
- .of_match = of_match_ptr(octeontx_nand_ids),
- .of_to_plat = octeontx_nand_of_to_plat,
- .probe = octeontx_pci_nand_probe,
- .priv_auto = sizeof(struct octeontx_nfc),
- .remove = octeontx_pci_nand_disable,
- .flags = DM_FLAG_OS_PREPARE,
-};
-
-U_BOOT_PCI_DEVICE(octeontx_pci_nand, octeontx_nfc_pci_id_table);
-
-void board_nand_init(void)
-{
- struct udevice *dev;
- int ret;
-
- if (IS_ENABLED(CONFIG_NAND_OCTEONTX_HW_ECC)) {
- ret = uclass_get_device_by_driver(UCLASS_MISC,
- DM_DRIVER_GET(octeontx_pci_bchpf),
- &dev);
- if (ret && ret != -ENODEV) {
- pr_err("Failed to initialize OcteonTX BCH PF controller. (error %d)\n",
- ret);
- }
- ret = uclass_get_device_by_driver(UCLASS_MISC,
- DM_DRIVER_GET(octeontx_pci_bchvf),
- &dev);
- if (ret && ret != -ENODEV) {
- pr_err("Failed to initialize OcteonTX BCH VF controller. (error %d)\n",
- ret);
- }
- }
-
- ret = uclass_get_device_by_driver(UCLASS_MTD,
- DM_DRIVER_GET(octeontx_pci_nand),
- &dev);
- if (ret && ret != -ENODEV)
- pr_err("Failed to initialize OcteonTX NAND controller. (error %d)\n",
- ret);
-}
diff --git a/drivers/mtd/nand/raw/pxa3xx_nand.c b/drivers/mtd/nand/raw/pxa3xx_nand.c
index b78b4e60238..7bf54fa4654 100644
--- a/drivers/mtd/nand/raw/pxa3xx_nand.c
+++ b/drivers/mtd/nand/raw/pxa3xx_nand.c
@@ -1765,6 +1765,7 @@ static int pxa3xx_nand_probe_dt(struct udevice *dev, struct pxa3xx_nand_info *in
pdata->num_cs = dev_read_u32_default(dev, "num-cs", 1);
if (pdata->num_cs != 1) {
pr_err("pxa3xx driver supports single CS only\n");
+ kfree(pdata);
return -EINVAL;
}
diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
index 083ea4c5a74..d1c88643c98 100644
--- a/drivers/mtd/nand/raw/stm32_fmc2_nand.c
+++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
@@ -942,21 +942,21 @@ static int stm32_fmc2_nfc_probe(struct udevice *dev)
addr = dev_read_addr_index(dev, mem_region);
if (addr == FDT_ADDR_T_NONE) {
dev_err(dev, "Resource data_base not found for cs%d", chip_cs);
- return ret;
+ return -EINVAL;
}
nfc->data_base[chip_cs] = addr;
addr = dev_read_addr_index(dev, mem_region + 1);
if (addr == FDT_ADDR_T_NONE) {
dev_err(dev, "Resource cmd_base not found for cs%d", chip_cs);
- return ret;
+ return -EINVAL;
}
nfc->cmd_base[chip_cs] = addr;
addr = dev_read_addr_index(dev, mem_region + 2);
if (addr == FDT_ADDR_T_NONE) {
dev_err(dev, "Resource addr_base not found for cs%d", chip_cs);
- return ret;
+ return -EINVAL;
}
nfc->addr_base[chip_cs] = addr;
}
diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c
index 34197bb09a1..1ce09b56b80 100644
--- a/drivers/mtd/nand/raw/sunxi_nand.c
+++ b/drivers/mtd/nand/raw/sunxi_nand.c
@@ -1403,8 +1403,10 @@ static int sunxi_nand_hw_common_ecc_ctrl_init(struct mtd_info *mtd,
if (!data)
return -ENOMEM;
- if (ecc->size != 512 && ecc->size != 1024)
+ if (ecc->size != 512 && ecc->size != 1024) {
+ kfree(data);
return -EINVAL;
+ }
/* Prefer 1k ECC chunk over 512 ones */
if (ecc->size == 512 && mtd->writesize > 512) {
@@ -1641,17 +1643,20 @@ static int sunxi_nand_chip_init(struct udevice *dev, struct sunxi_nfc *nfc,
if (ret) {
dev_err(dev, "could not retrieve reg property: %d\n",
ret);
+ kfree(chip);
return ret;
}
if (tmp > NFC_MAX_CS) {
dev_err(dev,
"invalid reg value: %u (max CS = 7)\n", tmp);
+ kfree(chip);
return -EINVAL;
}
if (test_and_set_bit(tmp, &nfc->assigned_cs)) {
dev_err(dev, "CS %d already assigned\n", tmp);
+ kfree(chip);
return -EINVAL;
}
@@ -1678,12 +1683,14 @@ static int sunxi_nand_chip_init(struct udevice *dev, struct sunxi_nfc *nfc,
dev_err(dev,
"could not retrieve timings for ONFI mode 0: %d\n",
ret);
+ kfree(chip);
return ret;
}
ret = sunxi_nand_chip_set_timings(nfc, chip, timings);
if (ret) {
dev_err(dev, "could not configure chip timings: %d\n", ret);
+ kfree(chip);
return ret;
}
@@ -1705,8 +1712,10 @@ static int sunxi_nand_chip_init(struct udevice *dev, struct sunxi_nfc *nfc,
mtd = nand_to_mtd(nand);
ret = nand_scan_ident(mtd, nsels, NULL);
- if (ret)
+ if (ret) {
+ kfree(chip);
return ret;
+ }
if (nand->bbt_options & NAND_BBT_USE_FLASH)
nand->bbt_options |= NAND_BBT_NO_OOB;
@@ -1719,24 +1728,28 @@ static int sunxi_nand_chip_init(struct udevice *dev, struct sunxi_nfc *nfc,
ret = sunxi_nand_chip_init_timings(nfc, chip);
if (ret) {
dev_err(dev, "could not configure chip timings: %d\n", ret);
+ kfree(chip);
return ret;
}
ret = sunxi_nand_ecc_init(mtd, &nand->ecc);
if (ret) {
dev_err(dev, "ECC init failed: %d\n", ret);
+ kfree(chip);
return ret;
}
ret = nand_scan_tail(mtd);
if (ret) {
dev_err(dev, "nand_scan_tail failed: %d\n", ret);
+ kfree(chip);
return ret;
}
ret = nand_register(devnum, mtd);
if (ret) {
dev_err(dev, "failed to register mtd device: %d\n", ret);
+ kfree(chip);
return ret;
}