diff options
Diffstat (limited to 'drivers/mtd/nand/raw')
-rw-r--r-- | drivers/mtd/nand/raw/Kconfig | 31 | ||||
-rw-r--r-- | drivers/mtd/nand/raw/Makefile | 4 | ||||
-rw-r--r-- | drivers/mtd/nand/raw/cortina_nand.c | 11 | ||||
-rw-r--r-- | drivers/mtd/nand/raw/denali.c | 10 | ||||
-rw-r--r-- | drivers/mtd/nand/raw/lpc32xx_nand_slc.c | 587 | ||||
-rw-r--r-- | drivers/mtd/nand/raw/mxic_nand.c | 602 | ||||
-rw-r--r-- | drivers/mtd/nand/raw/mxs_nand.c | 6 | ||||
-rw-r--r-- | drivers/mtd/nand/raw/octeontx_bch.c | 422 | ||||
-rw-r--r-- | drivers/mtd/nand/raw/octeontx_bch.h | 131 | ||||
-rw-r--r-- | drivers/mtd/nand/raw/octeontx_bch_regs.h | 167 | ||||
-rw-r--r-- | drivers/mtd/nand/raw/octeontx_nand.c | 2254 | ||||
-rw-r--r-- | drivers/mtd/nand/raw/pxa3xx_nand.c | 1 | ||||
-rw-r--r-- | drivers/mtd/nand/raw/stm32_fmc2_nand.c | 6 | ||||
-rw-r--r-- | drivers/mtd/nand/raw/sunxi_nand.c | 17 |
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; } |