summaryrefslogtreecommitdiffstats
path: root/qemu/roms/u-boot/drivers/mtd/nand
diff options
context:
space:
mode:
authorRajithaY <rajithax.yerrumsetty@intel.com>2017-04-25 03:31:15 -0700
committerRajitha Yerrumchetty <rajithax.yerrumsetty@intel.com>2017-05-22 06:48:08 +0000
commitbb756eebdac6fd24e8919e2c43f7d2c8c4091f59 (patch)
treeca11e03542edf2d8f631efeca5e1626d211107e3 /qemu/roms/u-boot/drivers/mtd/nand
parenta14b48d18a9ed03ec191cf16b162206998a895ce (diff)
Adding qemu as a submodule of KVMFORNFV
This Patch includes the changes to add qemu as a submodule to kvmfornfv repo and make use of the updated latest qemu for the execution of all testcase Change-Id: I1280af507a857675c7f81d30c95255635667bdd7 Signed-off-by:RajithaY<rajithax.yerrumsetty@intel.com>
Diffstat (limited to 'qemu/roms/u-boot/drivers/mtd/nand')
-rw-r--r--qemu/roms/u-boot/drivers/mtd/nand/Makefile72
-rw-r--r--qemu/roms/u-boot/drivers/mtd/nand/am335x_spl_bch.c226
-rw-r--r--qemu/roms/u-boot/drivers/mtd/nand/atmel_nand.c1437
-rw-r--r--qemu/roms/u-boot/drivers/mtd/nand/atmel_nand_ecc.h146
-rw-r--r--qemu/roms/u-boot/drivers/mtd/nand/bfin_nand.c393
-rw-r--r--qemu/roms/u-boot/drivers/mtd/nand/davinci_nand.c653
-rw-r--r--qemu/roms/u-boot/drivers/mtd/nand/docg4.c1028
-rw-r--r--qemu/roms/u-boot/drivers/mtd/nand/docg4_spl.c219
-rw-r--r--qemu/roms/u-boot/drivers/mtd/nand/fsl_elbc_nand.c829
-rw-r--r--qemu/roms/u-boot/drivers/mtd/nand/fsl_elbc_spl.c168
-rw-r--r--qemu/roms/u-boot/drivers/mtd/nand/fsl_ifc_nand.c1039
-rw-r--r--qemu/roms/u-boot/drivers/mtd/nand/fsl_ifc_spl.c252
-rw-r--r--qemu/roms/u-boot/drivers/mtd/nand/fsl_upm.c199
-rw-r--r--qemu/roms/u-boot/drivers/mtd/nand/fsmc_nand.c473
-rw-r--r--qemu/roms/u-boot/drivers/mtd/nand/jz4740_nand.c259
-rw-r--r--qemu/roms/u-boot/drivers/mtd/nand/kb9202_nand.c134
-rw-r--r--qemu/roms/u-boot/drivers/mtd/nand/kirkwood_nand.c70
-rw-r--r--qemu/roms/u-boot/drivers/mtd/nand/kmeter1_nand.c123
-rw-r--r--qemu/roms/u-boot/drivers/mtd/nand/mpc5121_nfc.c681
-rw-r--r--qemu/roms/u-boot/drivers/mtd/nand/mxc_nand.c1342
-rw-r--r--qemu/roms/u-boot/drivers/mtd/nand/mxc_nand.h209
-rw-r--r--qemu/roms/u-boot/drivers/mtd/nand/mxc_nand_spl.c351
-rw-r--r--qemu/roms/u-boot/drivers/mtd/nand/mxs_nand.c1179
-rw-r--r--qemu/roms/u-boot/drivers/mtd/nand/nand.c120
-rw-r--r--qemu/roms/u-boot/drivers/mtd/nand/nand_base.c3438
-rw-r--r--qemu/roms/u-boot/drivers/mtd/nand/nand_bbt.c1397
-rw-r--r--qemu/roms/u-boot/drivers/mtd/nand/nand_bch.c224
-rw-r--r--qemu/roms/u-boot/drivers/mtd/nand/nand_ecc.c191
-rw-r--r--qemu/roms/u-boot/drivers/mtd/nand/nand_ids.c182
-rw-r--r--qemu/roms/u-boot/drivers/mtd/nand/nand_plat.c64
-rw-r--r--qemu/roms/u-boot/drivers/mtd/nand/nand_spl_load.c42
-rw-r--r--qemu/roms/u-boot/drivers/mtd/nand/nand_spl_simple.c270
-rw-r--r--qemu/roms/u-boot/drivers/mtd/nand/nand_util.c861
-rw-r--r--qemu/roms/u-boot/drivers/mtd/nand/ndfc.c214
-rw-r--r--qemu/roms/u-boot/drivers/mtd/nand/nomadik.c206
-rw-r--r--qemu/roms/u-boot/drivers/mtd/nand/omap_elm.c196
-rw-r--r--qemu/roms/u-boot/drivers/mtd/nand/omap_gpmc.c836
-rw-r--r--qemu/roms/u-boot/drivers/mtd/nand/s3c2410_nand.c175
-rw-r--r--qemu/roms/u-boot/drivers/mtd/nand/tegra_nand.c1041
-rw-r--r--qemu/roms/u-boot/drivers/mtd/nand/tegra_nand.h241
40 files changed, 0 insertions, 21180 deletions
diff --git a/qemu/roms/u-boot/drivers/mtd/nand/Makefile b/qemu/roms/u-boot/drivers/mtd/nand/Makefile
deleted file mode 100644
index 4eb354da9..000000000
--- a/qemu/roms/u-boot/drivers/mtd/nand/Makefile
+++ /dev/null
@@ -1,72 +0,0 @@
-#
-# (C) Copyright 2006
-# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
-#
-# SPDX-License-Identifier: GPL-2.0+
-#
-
-ifdef CONFIG_SPL_BUILD
-
-ifdef CONFIG_SPL_NAND_DRIVERS
-NORMAL_DRIVERS=y
-endif
-
-obj-$(CONFIG_SPL_NAND_AM33XX_BCH) += am335x_spl_bch.o
-obj-$(CONFIG_SPL_NAND_DOCG4) += docg4_spl.o
-obj-$(CONFIG_SPL_NAND_SIMPLE) += nand_spl_simple.o
-obj-$(CONFIG_SPL_NAND_LOAD) += nand_spl_load.o
-obj-$(CONFIG_SPL_NAND_ECC) += nand_ecc.o
-obj-$(CONFIG_SPL_NAND_BASE) += nand_base.o
-obj-$(CONFIG_SPL_NAND_INIT) += nand.o
-ifeq ($(CONFIG_SPL_ENV_SUPPORT),y)
-obj-$(CONFIG_ENV_IS_IN_NAND) += nand_util.o
-endif
-
-else # not spl
-
-NORMAL_DRIVERS=y
-
-obj-y += nand.o
-obj-y += nand_bbt.o
-obj-y += nand_ids.o
-obj-y += nand_util.o
-obj-y += nand_ecc.o
-obj-y += nand_base.o
-
-endif # not spl
-
-ifdef NORMAL_DRIVERS
-
-obj-$(CONFIG_NAND_ECC_BCH) += nand_bch.o
-
-obj-$(CONFIG_NAND_ATMEL) += atmel_nand.o
-obj-$(CONFIG_DRIVER_NAND_BFIN) += bfin_nand.o
-obj-$(CONFIG_NAND_DAVINCI) += davinci_nand.o
-obj-$(CONFIG_NAND_FSL_ELBC) += fsl_elbc_nand.o
-obj-$(CONFIG_NAND_FSL_IFC) += fsl_ifc_nand.o
-obj-$(CONFIG_NAND_FSL_UPM) += fsl_upm.o
-obj-$(CONFIG_NAND_FSMC) += fsmc_nand.o
-obj-$(CONFIG_NAND_JZ4740) += jz4740_nand.o
-obj-$(CONFIG_NAND_KB9202) += kb9202_nand.o
-obj-$(CONFIG_NAND_KIRKWOOD) += kirkwood_nand.o
-obj-$(CONFIG_NAND_KMETER1) += kmeter1_nand.o
-obj-$(CONFIG_NAND_MPC5121_NFC) += mpc5121_nfc.o
-obj-$(CONFIG_NAND_MXC) += mxc_nand.o
-obj-$(CONFIG_NAND_MXS) += mxs_nand.o
-obj-$(CONFIG_NAND_NDFC) += ndfc.o
-obj-$(CONFIG_NAND_NOMADIK) += nomadik.o
-obj-$(CONFIG_NAND_S3C2410) += s3c2410_nand.o
-obj-$(CONFIG_NAND_SPEAR) += spr_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_PLAT) += nand_plat.o
-obj-$(CONFIG_NAND_DOCG4) += docg4.o
-
-else # minimal SPL drivers
-
-obj-$(CONFIG_NAND_FSL_ELBC) += fsl_elbc_spl.o
-obj-$(CONFIG_NAND_FSL_IFC) += fsl_ifc_spl.o
-obj-$(CONFIG_NAND_MXC) += mxc_nand_spl.o
-
-endif # drivers
diff --git a/qemu/roms/u-boot/drivers/mtd/nand/am335x_spl_bch.c b/qemu/roms/u-boot/drivers/mtd/nand/am335x_spl_bch.c
deleted file mode 100644
index bd89b067d..000000000
--- a/qemu/roms/u-boot/drivers/mtd/nand/am335x_spl_bch.c
+++ /dev/null
@@ -1,226 +0,0 @@
-/*
- * (C) Copyright 2012
- * Konstantin Kozhevnikov, Cogent Embedded
- *
- * based on nand_spl_simple code
- *
- * (C) Copyright 2006-2008
- * Stefan Roese, DENX Software Engineering, sr@denx.de.
- *
- * SPDX-License-Identifier: GPL-2.0+
- */
-
-#include <common.h>
-#include <nand.h>
-#include <asm/io.h>
-#include <linux/mtd/nand_ecc.h>
-
-static int nand_ecc_pos[] = CONFIG_SYS_NAND_ECCPOS;
-nand_info_t nand_info[1];
-static struct nand_chip nand_chip;
-
-#define ECCSTEPS (CONFIG_SYS_NAND_PAGE_SIZE / \
- CONFIG_SYS_NAND_ECCSIZE)
-#define ECCTOTAL (ECCSTEPS * CONFIG_SYS_NAND_ECCBYTES)
-
-
-/*
- * NAND command for large page NAND devices (2k)
- */
-static int nand_command(int block, int page, uint32_t offs,
- u8 cmd)
-{
- struct nand_chip *this = nand_info[0].priv;
- int page_addr = page + block * CONFIG_SYS_NAND_PAGE_COUNT;
- void (*hwctrl)(struct mtd_info *mtd, int cmd,
- unsigned int ctrl) = this->cmd_ctrl;
-
- while (!this->dev_ready(&nand_info[0]))
- ;
-
- /* Emulate NAND_CMD_READOOB */
- if (cmd == NAND_CMD_READOOB) {
- offs += CONFIG_SYS_NAND_PAGE_SIZE;
- cmd = NAND_CMD_READ0;
- }
-
- /* Begin command latch cycle */
- hwctrl(&nand_info[0], cmd, NAND_CTRL_CLE | NAND_CTRL_CHANGE);
-
- if (cmd == NAND_CMD_RESET) {
- hwctrl(&nand_info[0], NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
- while (!this->dev_ready(&nand_info[0]))
- ;
- return 0;
- }
-
- /* Shift the offset from byte addressing to word addressing. */
- if (this->options & NAND_BUSWIDTH_16)
- offs >>= 1;
-
- /* Set ALE and clear CLE to start address cycle */
- /* Column address */
- hwctrl(&nand_info[0], offs & 0xff,
- NAND_CTRL_ALE | NAND_CTRL_CHANGE); /* A[7:0] */
- hwctrl(&nand_info[0], (offs >> 8) & 0xff, NAND_CTRL_ALE); /* A[11:9] */
- /* Row address */
- hwctrl(&nand_info[0], (page_addr & 0xff), NAND_CTRL_ALE); /* A[19:12] */
- hwctrl(&nand_info[0], ((page_addr >> 8) & 0xff),
- NAND_CTRL_ALE); /* A[27:20] */
-#ifdef CONFIG_SYS_NAND_5_ADDR_CYCLE
- /* One more address cycle for devices > 128MiB */
- hwctrl(&nand_info[0], (page_addr >> 16) & 0x0f,
- NAND_CTRL_ALE); /* A[31:28] */
-#endif
- hwctrl(&nand_info[0], NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
-
- if (cmd == NAND_CMD_READ0) {
- /* Latch in address */
- hwctrl(&nand_info[0], NAND_CMD_READSTART,
- NAND_CTRL_CLE | NAND_CTRL_CHANGE);
- hwctrl(&nand_info[0], NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
-
- /*
- * Wait a while for the data to be ready
- */
- while (!this->dev_ready(&nand_info[0]))
- ;
- } else if (cmd == NAND_CMD_RNDOUT) {
- hwctrl(&nand_info[0], NAND_CMD_RNDOUTSTART, NAND_CTRL_CLE |
- NAND_CTRL_CHANGE);
- hwctrl(&nand_info[0], NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
- }
-
- return 0;
-}
-
-static int nand_is_bad_block(int block)
-{
- struct nand_chip *this = nand_info[0].priv;
-
- nand_command(block, 0, CONFIG_SYS_NAND_BAD_BLOCK_POS,
- NAND_CMD_READOOB);
-
- /*
- * Read one byte (or two if it's a 16 bit chip).
- */
- if (this->options & NAND_BUSWIDTH_16) {
- if (readw(this->IO_ADDR_R) != 0xffff)
- return 1;
- } else {
- if (readb(this->IO_ADDR_R) != 0xff)
- return 1;
- }
-
- return 0;
-}
-
-static int nand_read_page(int block, int page, void *dst)
-{
- struct nand_chip *this = nand_info[0].priv;
- u_char ecc_calc[ECCTOTAL];
- u_char ecc_code[ECCTOTAL];
- u_char oob_data[CONFIG_SYS_NAND_OOBSIZE];
- int i;
- int eccsize = CONFIG_SYS_NAND_ECCSIZE;
- int eccbytes = CONFIG_SYS_NAND_ECCBYTES;
- int eccsteps = ECCSTEPS;
- uint8_t *p = dst;
- uint32_t data_pos = 0;
- uint8_t *oob = &oob_data[0] + nand_ecc_pos[0];
- uint32_t oob_pos = eccsize * eccsteps + nand_ecc_pos[0];
-
- nand_command(block, page, 0, NAND_CMD_READ0);
-
- for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
- this->ecc.hwctl(&nand_info[0], NAND_ECC_READ);
- nand_command(block, page, data_pos, NAND_CMD_RNDOUT);
-
- this->read_buf(&nand_info[0], p, eccsize);
-
- nand_command(block, page, oob_pos, NAND_CMD_RNDOUT);
-
- this->read_buf(&nand_info[0], oob, eccbytes);
- this->ecc.calculate(&nand_info[0], p, &ecc_calc[i]);
-
- data_pos += eccsize;
- oob_pos += eccbytes;
- oob += eccbytes;
- }
-
- /* Pick the ECC bytes out of the oob data */
- for (i = 0; i < ECCTOTAL; i++)
- ecc_code[i] = oob_data[nand_ecc_pos[i]];
-
- eccsteps = ECCSTEPS;
- p = dst;
-
- for (i = 0 ; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
- /* No chance to do something with the possible error message
- * from correct_data(). We just hope that all possible errors
- * are corrected by this routine.
- */
- this->ecc.correct(&nand_info[0], p, &ecc_code[i], &ecc_calc[i]);
- }
-
- return 0;
-}
-
-int nand_spl_load_image(uint32_t offs, unsigned int size, void *dst)
-{
- unsigned int block, lastblock;
- unsigned int page;
-
- /*
- * offs has to be aligned to a page address!
- */
- block = offs / CONFIG_SYS_NAND_BLOCK_SIZE;
- lastblock = (offs + size - 1) / CONFIG_SYS_NAND_BLOCK_SIZE;
- page = (offs % CONFIG_SYS_NAND_BLOCK_SIZE) / CONFIG_SYS_NAND_PAGE_SIZE;
-
- while (block <= lastblock) {
- if (!nand_is_bad_block(block)) {
- /*
- * Skip bad blocks
- */
- while (page < CONFIG_SYS_NAND_PAGE_COUNT) {
- nand_read_page(block, page, dst);
- dst += CONFIG_SYS_NAND_PAGE_SIZE;
- page++;
- }
-
- page = 0;
- } else {
- lastblock++;
- }
-
- block++;
- }
-
- return 0;
-}
-
-/* nand_init() - initialize data to make nand usable by SPL */
-void nand_init(void)
-{
- /*
- * Init board specific nand support
- */
- nand_info[0].priv = &nand_chip;
- nand_chip.IO_ADDR_R = nand_chip.IO_ADDR_W =
- (void __iomem *)CONFIG_SYS_NAND_BASE;
- board_nand_init(&nand_chip);
-
- if (nand_chip.select_chip)
- nand_chip.select_chip(&nand_info[0], 0);
-
- /* NAND chip may require reset after power-on */
- nand_command(0, 0, 0, NAND_CMD_RESET);
-}
-
-/* Unselect after operation */
-void nand_deselect(void)
-{
- if (nand_chip.select_chip)
- nand_chip.select_chip(&nand_info[0], -1);
-}
diff --git a/qemu/roms/u-boot/drivers/mtd/nand/atmel_nand.c b/qemu/roms/u-boot/drivers/mtd/nand/atmel_nand.c
deleted file mode 100644
index e1fc48fca..000000000
--- a/qemu/roms/u-boot/drivers/mtd/nand/atmel_nand.c
+++ /dev/null
@@ -1,1437 +0,0 @@
-/*
- * (C) Copyright 2007-2008
- * Stelian Pop <stelian@popies.net>
- * Lead Tech Design <www.leadtechdesign.com>
- *
- * (C) Copyright 2006 ATMEL Rousset, Lacressonniere Nicolas
- *
- * Add Programmable Multibit ECC support for various AT91 SoC
- * (C) Copyright 2012 ATMEL, Hong Xu
- *
- * SPDX-License-Identifier: GPL-2.0+
- */
-
-#include <common.h>
-#include <asm/gpio.h>
-#include <asm/arch/gpio.h>
-
-#include <malloc.h>
-#include <nand.h>
-#include <watchdog.h>
-
-#ifdef CONFIG_ATMEL_NAND_HWECC
-
-/* Register access macros */
-#define ecc_readl(add, reg) \
- readl(AT91_BASE_SYS + add + ATMEL_ECC_##reg)
-#define ecc_writel(add, reg, value) \
- writel((value), AT91_BASE_SYS + add + ATMEL_ECC_##reg)
-
-#include "atmel_nand_ecc.h" /* Hardware ECC registers */
-
-#ifdef CONFIG_ATMEL_NAND_HW_PMECC
-
-#ifdef CONFIG_SPL_BUILD
-#undef CONFIG_SYS_NAND_ONFI_DETECTION
-#endif
-
-struct atmel_nand_host {
- struct pmecc_regs __iomem *pmecc;
- struct pmecc_errloc_regs __iomem *pmerrloc;
- void __iomem *pmecc_rom_base;
-
- u8 pmecc_corr_cap;
- u16 pmecc_sector_size;
- u32 pmecc_index_table_offset;
-
- int pmecc_bytes_per_sector;
- int pmecc_sector_number;
- int pmecc_degree; /* Degree of remainders */
- int pmecc_cw_len; /* Length of codeword */
-
- /* lookup table for alpha_to and index_of */
- void __iomem *pmecc_alpha_to;
- void __iomem *pmecc_index_of;
-
- /* data for pmecc computation */
- int16_t *pmecc_smu;
- int16_t *pmecc_partial_syn;
- int16_t *pmecc_si;
- int16_t *pmecc_lmu; /* polynomal order */
- int *pmecc_mu;
- int *pmecc_dmu;
- int *pmecc_delta;
-};
-
-static struct atmel_nand_host pmecc_host;
-static struct nand_ecclayout atmel_pmecc_oobinfo;
-
-/*
- * Return number of ecc bytes per sector according to sector size and
- * correction capability
- *
- * Following table shows what at91 PMECC supported:
- * Correction Capability Sector_512_bytes Sector_1024_bytes
- * ===================== ================ =================
- * 2-bits 4-bytes 4-bytes
- * 4-bits 7-bytes 7-bytes
- * 8-bits 13-bytes 14-bytes
- * 12-bits 20-bytes 21-bytes
- * 24-bits 39-bytes 42-bytes
- */
-static int pmecc_get_ecc_bytes(int cap, int sector_size)
-{
- int m = 12 + sector_size / 512;
- return (m * cap + 7) / 8;
-}
-
-static void pmecc_config_ecc_layout(struct nand_ecclayout *layout,
- int oobsize, int ecc_len)
-{
- int i;
-
- layout->eccbytes = ecc_len;
-
- /* ECC will occupy the last ecc_len bytes continuously */
- for (i = 0; i < ecc_len; i++)
- layout->eccpos[i] = oobsize - ecc_len + i;
-
- layout->oobfree[0].offset = 2;
- layout->oobfree[0].length =
- oobsize - ecc_len - layout->oobfree[0].offset;
-}
-
-static void __iomem *pmecc_get_alpha_to(struct atmel_nand_host *host)
-{
- int table_size;
-
- table_size = host->pmecc_sector_size == 512 ?
- PMECC_INDEX_TABLE_SIZE_512 : PMECC_INDEX_TABLE_SIZE_1024;
-
- /* the ALPHA lookup table is right behind the INDEX lookup table. */
- return host->pmecc_rom_base + host->pmecc_index_table_offset +
- table_size * sizeof(int16_t);
-}
-
-static void pmecc_data_free(struct atmel_nand_host *host)
-{
- free(host->pmecc_partial_syn);
- free(host->pmecc_si);
- free(host->pmecc_lmu);
- free(host->pmecc_smu);
- free(host->pmecc_mu);
- free(host->pmecc_dmu);
- free(host->pmecc_delta);
-}
-
-static int pmecc_data_alloc(struct atmel_nand_host *host)
-{
- const int cap = host->pmecc_corr_cap;
- int size;
-
- size = (2 * cap + 1) * sizeof(int16_t);
- host->pmecc_partial_syn = malloc(size);
- host->pmecc_si = malloc(size);
- host->pmecc_lmu = malloc((cap + 1) * sizeof(int16_t));
- host->pmecc_smu = malloc((cap + 2) * size);
-
- size = (cap + 1) * sizeof(int);
- host->pmecc_mu = malloc(size);
- host->pmecc_dmu = malloc(size);
- host->pmecc_delta = malloc(size);
-
- if (host->pmecc_partial_syn &&
- host->pmecc_si &&
- host->pmecc_lmu &&
- host->pmecc_smu &&
- host->pmecc_mu &&
- host->pmecc_dmu &&
- host->pmecc_delta)
- return 0;
-
- /* error happened */
- pmecc_data_free(host);
- return -ENOMEM;
-
-}
-
-static void pmecc_gen_syndrome(struct mtd_info *mtd, int sector)
-{
- struct nand_chip *nand_chip = mtd->priv;
- struct atmel_nand_host *host = nand_chip->priv;
- int i;
- uint32_t value;
-
- /* Fill odd syndromes */
- for (i = 0; i < host->pmecc_corr_cap; i++) {
- value = readl(&host->pmecc->rem_port[sector].rem[i / 2]);
- if (i & 1)
- value >>= 16;
- value &= 0xffff;
- host->pmecc_partial_syn[(2 * i) + 1] = (int16_t)value;
- }
-}
-
-static void pmecc_substitute(struct mtd_info *mtd)
-{
- struct nand_chip *nand_chip = mtd->priv;
- struct atmel_nand_host *host = nand_chip->priv;
- int16_t __iomem *alpha_to = host->pmecc_alpha_to;
- int16_t __iomem *index_of = host->pmecc_index_of;
- int16_t *partial_syn = host->pmecc_partial_syn;
- const int cap = host->pmecc_corr_cap;
- int16_t *si;
- int i, j;
-
- /* si[] is a table that holds the current syndrome value,
- * an element of that table belongs to the field
- */
- si = host->pmecc_si;
-
- memset(&si[1], 0, sizeof(int16_t) * (2 * cap - 1));
-
- /* Computation 2t syndromes based on S(x) */
- /* Odd syndromes */
- for (i = 1; i < 2 * cap; i += 2) {
- for (j = 0; j < host->pmecc_degree; j++) {
- if (partial_syn[i] & (0x1 << j))
- si[i] = readw(alpha_to + i * j) ^ si[i];
- }
- }
- /* Even syndrome = (Odd syndrome) ** 2 */
- for (i = 2, j = 1; j <= cap; i = ++j << 1) {
- if (si[j] == 0) {
- si[i] = 0;
- } else {
- int16_t tmp;
-
- tmp = readw(index_of + si[j]);
- tmp = (tmp * 2) % host->pmecc_cw_len;
- si[i] = readw(alpha_to + tmp);
- }
- }
-}
-
-/*
- * This function defines a Berlekamp iterative procedure for
- * finding the value of the error location polynomial.
- * The input is si[], initialize by pmecc_substitute().
- * The output is smu[][].
- *
- * This function is written according to chip datasheet Chapter:
- * Find the Error Location Polynomial Sigma(x) of Section:
- * Programmable Multibit ECC Control (PMECC).
- */
-static void pmecc_get_sigma(struct mtd_info *mtd)
-{
- struct nand_chip *nand_chip = mtd->priv;
- struct atmel_nand_host *host = nand_chip->priv;
-
- int16_t *lmu = host->pmecc_lmu;
- int16_t *si = host->pmecc_si;
- int *mu = host->pmecc_mu;
- int *dmu = host->pmecc_dmu; /* Discrepancy */
- int *delta = host->pmecc_delta; /* Delta order */
- int cw_len = host->pmecc_cw_len;
- const int16_t cap = host->pmecc_corr_cap;
- const int num = 2 * cap + 1;
- int16_t __iomem *index_of = host->pmecc_index_of;
- int16_t __iomem *alpha_to = host->pmecc_alpha_to;
- int i, j, k;
- uint32_t dmu_0_count, tmp;
- int16_t *smu = host->pmecc_smu;
-
- /* index of largest delta */
- int ro;
- int largest;
- int diff;
-
- /* Init the Sigma(x) */
- memset(smu, 0, sizeof(int16_t) * ARRAY_SIZE(smu));
-
- dmu_0_count = 0;
-
- /* First Row */
-
- /* Mu */
- mu[0] = -1;
-
- smu[0] = 1;
-
- /* discrepancy set to 1 */
- dmu[0] = 1;
- /* polynom order set to 0 */
- lmu[0] = 0;
- /* delta[0] = (mu[0] * 2 - lmu[0]) >> 1; */
- delta[0] = -1;
-
- /* Second Row */
-
- /* Mu */
- mu[1] = 0;
- /* Sigma(x) set to 1 */
- smu[num] = 1;
-
- /* discrepancy set to S1 */
- dmu[1] = si[1];
-
- /* polynom order set to 0 */
- lmu[1] = 0;
-
- /* delta[1] = (mu[1] * 2 - lmu[1]) >> 1; */
- delta[1] = 0;
-
- for (i = 1; i <= cap; i++) {
- mu[i + 1] = i << 1;
- /* Begin Computing Sigma (Mu+1) and L(mu) */
- /* check if discrepancy is set to 0 */
- if (dmu[i] == 0) {
- dmu_0_count++;
-
- tmp = ((cap - (lmu[i] >> 1) - 1) / 2);
- if ((cap - (lmu[i] >> 1) - 1) & 0x1)
- tmp += 2;
- else
- tmp += 1;
-
- if (dmu_0_count == tmp) {
- for (j = 0; j <= (lmu[i] >> 1) + 1; j++)
- smu[(cap + 1) * num + j] =
- smu[i * num + j];
-
- lmu[cap + 1] = lmu[i];
- return;
- }
-
- /* copy polynom */
- for (j = 0; j <= lmu[i] >> 1; j++)
- smu[(i + 1) * num + j] = smu[i * num + j];
-
- /* copy previous polynom order to the next */
- lmu[i + 1] = lmu[i];
- } else {
- ro = 0;
- largest = -1;
- /* find largest delta with dmu != 0 */
- for (j = 0; j < i; j++) {
- if ((dmu[j]) && (delta[j] > largest)) {
- largest = delta[j];
- ro = j;
- }
- }
-
- /* compute difference */
- diff = (mu[i] - mu[ro]);
-
- /* Compute degree of the new smu polynomial */
- if ((lmu[i] >> 1) > ((lmu[ro] >> 1) + diff))
- lmu[i + 1] = lmu[i];
- else
- lmu[i + 1] = ((lmu[ro] >> 1) + diff) * 2;
-
- /* Init smu[i+1] with 0 */
- for (k = 0; k < num; k++)
- smu[(i + 1) * num + k] = 0;
-
- /* Compute smu[i+1] */
- for (k = 0; k <= lmu[ro] >> 1; k++) {
- int16_t a, b, c;
-
- if (!(smu[ro * num + k] && dmu[i]))
- continue;
- a = readw(index_of + dmu[i]);
- b = readw(index_of + dmu[ro]);
- c = readw(index_of + smu[ro * num + k]);
- tmp = a + (cw_len - b) + c;
- a = readw(alpha_to + tmp % cw_len);
- smu[(i + 1) * num + (k + diff)] = a;
- }
-
- for (k = 0; k <= lmu[i] >> 1; k++)
- smu[(i + 1) * num + k] ^= smu[i * num + k];
- }
-
- /* End Computing Sigma (Mu+1) and L(mu) */
- /* In either case compute delta */
- delta[i + 1] = (mu[i + 1] * 2 - lmu[i + 1]) >> 1;
-
- /* Do not compute discrepancy for the last iteration */
- if (i >= cap)
- continue;
-
- for (k = 0; k <= (lmu[i + 1] >> 1); k++) {
- tmp = 2 * (i - 1);
- if (k == 0) {
- dmu[i + 1] = si[tmp + 3];
- } else if (smu[(i + 1) * num + k] && si[tmp + 3 - k]) {
- int16_t a, b, c;
- a = readw(index_of +
- smu[(i + 1) * num + k]);
- b = si[2 * (i - 1) + 3 - k];
- c = readw(index_of + b);
- tmp = a + c;
- tmp %= cw_len;
- dmu[i + 1] = readw(alpha_to + tmp) ^
- dmu[i + 1];
- }
- }
- }
-}
-
-static int pmecc_err_location(struct mtd_info *mtd)
-{
- struct nand_chip *nand_chip = mtd->priv;
- struct atmel_nand_host *host = nand_chip->priv;
- const int cap = host->pmecc_corr_cap;
- const int num = 2 * cap + 1;
- int sector_size = host->pmecc_sector_size;
- int err_nbr = 0; /* number of error */
- int roots_nbr; /* number of roots */
- int i;
- uint32_t val;
- int16_t *smu = host->pmecc_smu;
- int timeout = PMECC_MAX_TIMEOUT_US;
-
- writel(PMERRLOC_DISABLE, &host->pmerrloc->eldis);
-
- for (i = 0; i <= host->pmecc_lmu[cap + 1] >> 1; i++) {
- writel(smu[(cap + 1) * num + i], &host->pmerrloc->sigma[i]);
- err_nbr++;
- }
-
- val = PMERRLOC_ELCFG_NUM_ERRORS(err_nbr - 1);
- if (sector_size == 1024)
- val |= PMERRLOC_ELCFG_SECTOR_1024;
-
- writel(val, &host->pmerrloc->elcfg);
- writel(sector_size * 8 + host->pmecc_degree * cap,
- &host->pmerrloc->elen);
-
- while (--timeout) {
- if (readl(&host->pmerrloc->elisr) & PMERRLOC_CALC_DONE)
- break;
- WATCHDOG_RESET();
- udelay(1);
- }
-
- if (!timeout) {
- dev_err(host->dev, "atmel_nand : Timeout to calculate PMECC error location\n");
- return -1;
- }
-
- roots_nbr = (readl(&host->pmerrloc->elisr) & PMERRLOC_ERR_NUM_MASK)
- >> 8;
- /* Number of roots == degree of smu hence <= cap */
- if (roots_nbr == host->pmecc_lmu[cap + 1] >> 1)
- return err_nbr - 1;
-
- /* Number of roots does not match the degree of smu
- * unable to correct error */
- return -1;
-}
-
-static void pmecc_correct_data(struct mtd_info *mtd, uint8_t *buf, uint8_t *ecc,
- int sector_num, int extra_bytes, int err_nbr)
-{
- struct nand_chip *nand_chip = mtd->priv;
- struct atmel_nand_host *host = nand_chip->priv;
- int i = 0;
- int byte_pos, bit_pos, sector_size, pos;
- uint32_t tmp;
- uint8_t err_byte;
-
- sector_size = host->pmecc_sector_size;
-
- while (err_nbr) {
- tmp = readl(&host->pmerrloc->el[i]) - 1;
- byte_pos = tmp / 8;
- bit_pos = tmp % 8;
-
- if (byte_pos >= (sector_size + extra_bytes))
- BUG(); /* should never happen */
-
- if (byte_pos < sector_size) {
- err_byte = *(buf + byte_pos);
- *(buf + byte_pos) ^= (1 << bit_pos);
-
- pos = sector_num * host->pmecc_sector_size + byte_pos;
- dev_dbg(host->dev, "Bit flip in data area, byte_pos: %d, bit_pos: %d, 0x%02x -> 0x%02x\n",
- pos, bit_pos, err_byte, *(buf + byte_pos));
- } else {
- /* Bit flip in OOB area */
- tmp = sector_num * host->pmecc_bytes_per_sector
- + (byte_pos - sector_size);
- err_byte = ecc[tmp];
- ecc[tmp] ^= (1 << bit_pos);
-
- pos = tmp + nand_chip->ecc.layout->eccpos[0];
- dev_dbg(host->dev, "Bit flip in OOB, oob_byte_pos: %d, bit_pos: %d, 0x%02x -> 0x%02x\n",
- pos, bit_pos, err_byte, ecc[tmp]);
- }
-
- i++;
- err_nbr--;
- }
-
- return;
-}
-
-static int pmecc_correction(struct mtd_info *mtd, u32 pmecc_stat, uint8_t *buf,
- u8 *ecc)
-{
- struct nand_chip *nand_chip = mtd->priv;
- struct atmel_nand_host *host = nand_chip->priv;
- int i, err_nbr, eccbytes;
- uint8_t *buf_pos;
-
- eccbytes = nand_chip->ecc.bytes;
- for (i = 0; i < eccbytes; i++)
- if (ecc[i] != 0xff)
- goto normal_check;
- /* Erased page, return OK */
- return 0;
-
-normal_check:
- for (i = 0; i < host->pmecc_sector_number; i++) {
- err_nbr = 0;
- if (pmecc_stat & 0x1) {
- buf_pos = buf + i * host->pmecc_sector_size;
-
- pmecc_gen_syndrome(mtd, i);
- pmecc_substitute(mtd);
- pmecc_get_sigma(mtd);
-
- err_nbr = pmecc_err_location(mtd);
- if (err_nbr == -1) {
- dev_err(host->dev, "PMECC: Too many errors\n");
- mtd->ecc_stats.failed++;
- return -EIO;
- } else {
- pmecc_correct_data(mtd, buf_pos, ecc, i,
- host->pmecc_bytes_per_sector, err_nbr);
- mtd->ecc_stats.corrected += err_nbr;
- }
- }
- pmecc_stat >>= 1;
- }
-
- return 0;
-}
-
-static int atmel_nand_pmecc_read_page(struct mtd_info *mtd,
- struct nand_chip *chip, uint8_t *buf, int oob_required, int page)
-{
- struct atmel_nand_host *host = chip->priv;
- int eccsize = chip->ecc.size;
- uint8_t *oob = chip->oob_poi;
- uint32_t *eccpos = chip->ecc.layout->eccpos;
- uint32_t stat;
- int timeout = PMECC_MAX_TIMEOUT_US;
-
- pmecc_writel(host->pmecc, ctrl, PMECC_CTRL_RST);
- pmecc_writel(host->pmecc, ctrl, PMECC_CTRL_DISABLE);
- pmecc_writel(host->pmecc, cfg, ((pmecc_readl(host->pmecc, cfg))
- & ~PMECC_CFG_WRITE_OP) | PMECC_CFG_AUTO_ENABLE);
-
- pmecc_writel(host->pmecc, ctrl, PMECC_CTRL_ENABLE);
- pmecc_writel(host->pmecc, ctrl, PMECC_CTRL_DATA);
-
- chip->read_buf(mtd, buf, eccsize);
- chip->read_buf(mtd, oob, mtd->oobsize);
-
- while (--timeout) {
- if (!(pmecc_readl(host->pmecc, sr) & PMECC_SR_BUSY))
- break;
- WATCHDOG_RESET();
- udelay(1);
- }
-
- if (!timeout) {
- dev_err(host->dev, "atmel_nand : Timeout to read PMECC page\n");
- return -1;
- }
-
- stat = pmecc_readl(host->pmecc, isr);
- if (stat != 0)
- if (pmecc_correction(mtd, stat, buf, &oob[eccpos[0]]) != 0)
- return -EIO;
-
- return 0;
-}
-
-static int atmel_nand_pmecc_write_page(struct mtd_info *mtd,
- struct nand_chip *chip, const uint8_t *buf,
- int oob_required)
-{
- struct atmel_nand_host *host = chip->priv;
- uint32_t *eccpos = chip->ecc.layout->eccpos;
- int i, j;
- int timeout = PMECC_MAX_TIMEOUT_US;
-
- pmecc_writel(host->pmecc, ctrl, PMECC_CTRL_RST);
- pmecc_writel(host->pmecc, ctrl, PMECC_CTRL_DISABLE);
-
- pmecc_writel(host->pmecc, cfg, (pmecc_readl(host->pmecc, cfg) |
- PMECC_CFG_WRITE_OP) & ~PMECC_CFG_AUTO_ENABLE);
-
- pmecc_writel(host->pmecc, ctrl, PMECC_CTRL_ENABLE);
- pmecc_writel(host->pmecc, ctrl, PMECC_CTRL_DATA);
-
- chip->write_buf(mtd, (u8 *)buf, mtd->writesize);
-
- while (--timeout) {
- if (!(pmecc_readl(host->pmecc, sr) & PMECC_SR_BUSY))
- break;
- WATCHDOG_RESET();
- udelay(1);
- }
-
- if (!timeout) {
- dev_err(host->dev, "atmel_nand : Timeout to read PMECC status, fail to write PMECC in oob\n");
- goto out;
- }
-
- for (i = 0; i < host->pmecc_sector_number; i++) {
- for (j = 0; j < host->pmecc_bytes_per_sector; j++) {
- int pos;
-
- pos = i * host->pmecc_bytes_per_sector + j;
- chip->oob_poi[eccpos[pos]] =
- readb(&host->pmecc->ecc_port[i].ecc[j]);
- }
- }
- chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
-out:
- return 0;
-}
-
-static void atmel_pmecc_core_init(struct mtd_info *mtd)
-{
- struct nand_chip *nand_chip = mtd->priv;
- struct atmel_nand_host *host = nand_chip->priv;
- uint32_t val = 0;
- struct nand_ecclayout *ecc_layout;
-
- pmecc_writel(host->pmecc, ctrl, PMECC_CTRL_RST);
- pmecc_writel(host->pmecc, ctrl, PMECC_CTRL_DISABLE);
-
- switch (host->pmecc_corr_cap) {
- case 2:
- val = PMECC_CFG_BCH_ERR2;
- break;
- case 4:
- val = PMECC_CFG_BCH_ERR4;
- break;
- case 8:
- val = PMECC_CFG_BCH_ERR8;
- break;
- case 12:
- val = PMECC_CFG_BCH_ERR12;
- break;
- case 24:
- val = PMECC_CFG_BCH_ERR24;
- break;
- }
-
- if (host->pmecc_sector_size == 512)
- val |= PMECC_CFG_SECTOR512;
- else if (host->pmecc_sector_size == 1024)
- val |= PMECC_CFG_SECTOR1024;
-
- switch (host->pmecc_sector_number) {
- case 1:
- val |= PMECC_CFG_PAGE_1SECTOR;
- break;
- case 2:
- val |= PMECC_CFG_PAGE_2SECTORS;
- break;
- case 4:
- val |= PMECC_CFG_PAGE_4SECTORS;
- break;
- case 8:
- val |= PMECC_CFG_PAGE_8SECTORS;
- break;
- }
-
- val |= (PMECC_CFG_READ_OP | PMECC_CFG_SPARE_DISABLE
- | PMECC_CFG_AUTO_DISABLE);
- pmecc_writel(host->pmecc, cfg, val);
-
- ecc_layout = nand_chip->ecc.layout;
- pmecc_writel(host->pmecc, sarea, mtd->oobsize - 1);
- pmecc_writel(host->pmecc, saddr, ecc_layout->eccpos[0]);
- pmecc_writel(host->pmecc, eaddr,
- ecc_layout->eccpos[ecc_layout->eccbytes - 1]);
- /* See datasheet about PMECC Clock Control Register */
- pmecc_writel(host->pmecc, clk, PMECC_CLK_133MHZ);
- pmecc_writel(host->pmecc, idr, 0xff);
- pmecc_writel(host->pmecc, ctrl, PMECC_CTRL_ENABLE);
-}
-
-#ifdef CONFIG_SYS_NAND_ONFI_DETECTION
-/*
- * get_onfi_ecc_param - Get ECC requirement from ONFI parameters
- * @ecc_bits: store the ONFI ECC correct bits capbility
- * @sector_size: in how many bytes that ONFI require to correct @ecc_bits
- *
- * Returns -1 if ONFI parameters is not supported. In this case @ecc_bits,
- * @sector_size are initialize to 0.
- * Return 0 if success to get the ECC requirement.
- */
-static int get_onfi_ecc_param(struct nand_chip *chip,
- int *ecc_bits, int *sector_size)
-{
- *ecc_bits = *sector_size = 0;
-
- if (chip->onfi_params.ecc_bits == 0xff)
- /* TODO: the sector_size and ecc_bits need to be find in
- * extended ecc parameter, currently we don't support it.
- */
- return -1;
-
- *ecc_bits = chip->onfi_params.ecc_bits;
-
- /* The default sector size (ecc codeword size) is 512 */
- *sector_size = 512;
-
- return 0;
-}
-
-/*
- * pmecc_choose_ecc - Get ecc requirement from ONFI parameters. If
- * pmecc_corr_cap or pmecc_sector_size is 0, then set it as
- * ONFI ECC parameters.
- * @host: point to an atmel_nand_host structure.
- * if host->pmecc_corr_cap is 0 then set it as the ONFI ecc_bits.
- * if host->pmecc_sector_size is 0 then set it as the ONFI sector_size.
- * @chip: point to an nand_chip structure.
- * @cap: store the ONFI ECC correct bits capbility
- * @sector_size: in how many bytes that ONFI require to correct @ecc_bits
- *
- * Return 0 if success. otherwise return the error code.
- */
-static int pmecc_choose_ecc(struct atmel_nand_host *host,
- struct nand_chip *chip,
- int *cap, int *sector_size)
-{
- /* Get ECC requirement from ONFI parameters */
- *cap = *sector_size = 0;
- if (chip->onfi_version) {
- if (!get_onfi_ecc_param(chip, cap, sector_size)) {
- MTDDEBUG(MTD_DEBUG_LEVEL1, "ONFI params, minimum required ECC: %d bits in %d bytes\n",
- *cap, *sector_size);
- } else {
- dev_info(host->dev, "NAND chip ECC reqirement is in Extended ONFI parameter, we don't support yet.\n");
- }
- } else {
- dev_info(host->dev, "NAND chip is not ONFI compliant, assume ecc_bits is 2 in 512 bytes");
- }
- if (*cap == 0 && *sector_size == 0) {
- /* Non-ONFI compliant or use extended ONFI parameters */
- *cap = 2;
- *sector_size = 512;
- }
-
- /* If head file doesn't specify then use the one in ONFI parameters */
- if (host->pmecc_corr_cap == 0) {
- /* use the most fitable ecc bits (the near bigger one ) */
- if (*cap <= 2)
- host->pmecc_corr_cap = 2;
- else if (*cap <= 4)
- host->pmecc_corr_cap = 4;
- else if (*cap <= 8)
- host->pmecc_corr_cap = 8;
- else if (*cap <= 12)
- host->pmecc_corr_cap = 12;
- else if (*cap <= 24)
- host->pmecc_corr_cap = 24;
- else
- return -EINVAL;
- }
- if (host->pmecc_sector_size == 0) {
- /* use the most fitable sector size (the near smaller one ) */
- if (*sector_size >= 1024)
- host->pmecc_sector_size = 1024;
- else if (*sector_size >= 512)
- host->pmecc_sector_size = 512;
- else
- return -EINVAL;
- }
- return 0;
-}
-#endif
-
-static int atmel_pmecc_nand_init_params(struct nand_chip *nand,
- struct mtd_info *mtd)
-{
- struct atmel_nand_host *host;
- int cap, sector_size;
-
- host = nand->priv = &pmecc_host;
-
- nand->ecc.mode = NAND_ECC_HW;
- nand->ecc.calculate = NULL;
- nand->ecc.correct = NULL;
- nand->ecc.hwctl = NULL;
-
-#ifdef CONFIG_SYS_NAND_ONFI_DETECTION
- host->pmecc_corr_cap = host->pmecc_sector_size = 0;
-
-#ifdef CONFIG_PMECC_CAP
- host->pmecc_corr_cap = CONFIG_PMECC_CAP;
-#endif
-#ifdef CONFIG_PMECC_SECTOR_SIZE
- host->pmecc_sector_size = CONFIG_PMECC_SECTOR_SIZE;
-#endif
- /* Get ECC requirement of ONFI parameters. And if CONFIG_PMECC_CAP or
- * CONFIG_PMECC_SECTOR_SIZE not defined, then use ecc_bits, sector_size
- * from ONFI.
- */
- if (pmecc_choose_ecc(host, nand, &cap, &sector_size)) {
- dev_err(host->dev, "The NAND flash's ECC requirement(ecc_bits: %d, sector_size: %d) are not support!",
- cap, sector_size);
- return -EINVAL;
- }
-
- if (cap > host->pmecc_corr_cap)
- dev_info(host->dev, "WARNING: Using different ecc correct bits(%d bit) from Nand ONFI ECC reqirement (%d bit).\n",
- host->pmecc_corr_cap, cap);
- if (sector_size < host->pmecc_sector_size)
- dev_info(host->dev, "WARNING: Using different ecc correct sector size (%d bytes) from Nand ONFI ECC reqirement (%d bytes).\n",
- host->pmecc_sector_size, sector_size);
-#else /* CONFIG_SYS_NAND_ONFI_DETECTION */
- host->pmecc_corr_cap = CONFIG_PMECC_CAP;
- host->pmecc_sector_size = CONFIG_PMECC_SECTOR_SIZE;
-#endif
-
- cap = host->pmecc_corr_cap;
- sector_size = host->pmecc_sector_size;
-
- /* TODO: need check whether cap & sector_size is validate */
-
- if (host->pmecc_sector_size == 512)
- host->pmecc_index_table_offset = ATMEL_PMECC_INDEX_OFFSET_512;
- else
- host->pmecc_index_table_offset = ATMEL_PMECC_INDEX_OFFSET_1024;
-
- MTDDEBUG(MTD_DEBUG_LEVEL1,
- "Initialize PMECC params, cap: %d, sector: %d\n",
- cap, sector_size);
-
- host->pmecc = (struct pmecc_regs __iomem *) ATMEL_BASE_PMECC;
- host->pmerrloc = (struct pmecc_errloc_regs __iomem *)
- ATMEL_BASE_PMERRLOC;
- host->pmecc_rom_base = (void __iomem *) ATMEL_BASE_ROM;
-
- /* ECC is calculated for the whole page (1 step) */
- nand->ecc.size = mtd->writesize;
-
- /* set ECC page size and oob layout */
- switch (mtd->writesize) {
- case 2048:
- case 4096:
- case 8192:
- host->pmecc_degree = (sector_size == 512) ?
- PMECC_GF_DIMENSION_13 : PMECC_GF_DIMENSION_14;
- host->pmecc_cw_len = (1 << host->pmecc_degree) - 1;
- host->pmecc_sector_number = mtd->writesize / sector_size;
- host->pmecc_bytes_per_sector = pmecc_get_ecc_bytes(
- cap, sector_size);
- host->pmecc_alpha_to = pmecc_get_alpha_to(host);
- host->pmecc_index_of = host->pmecc_rom_base +
- host->pmecc_index_table_offset;
-
- nand->ecc.steps = 1;
- nand->ecc.bytes = host->pmecc_bytes_per_sector *
- host->pmecc_sector_number;
-
- if (nand->ecc.bytes > MTD_MAX_ECCPOS_ENTRIES_LARGE) {
- dev_err(host->dev, "too large eccpos entries. max support ecc.bytes is %d\n",
- MTD_MAX_ECCPOS_ENTRIES_LARGE);
- return -EINVAL;
- }
-
- if (nand->ecc.bytes > mtd->oobsize - 2) {
- dev_err(host->dev, "No room for ECC bytes\n");
- return -EINVAL;
- }
- pmecc_config_ecc_layout(&atmel_pmecc_oobinfo,
- mtd->oobsize,
- nand->ecc.bytes);
- nand->ecc.layout = &atmel_pmecc_oobinfo;
- break;
- case 512:
- case 1024:
- /* TODO */
- dev_err(host->dev, "Unsupported page size for PMECC, use Software ECC\n");
- default:
- /* page size not handled by HW ECC */
- /* switching back to soft ECC */
- nand->ecc.mode = NAND_ECC_SOFT;
- nand->ecc.read_page = NULL;
- nand->ecc.postpad = 0;
- nand->ecc.prepad = 0;
- nand->ecc.bytes = 0;
- return 0;
- }
-
- /* Allocate data for PMECC computation */
- if (pmecc_data_alloc(host)) {
- dev_err(host->dev, "Cannot allocate memory for PMECC computation!\n");
- return -ENOMEM;
- }
-
- nand->ecc.read_page = atmel_nand_pmecc_read_page;
- nand->ecc.write_page = atmel_nand_pmecc_write_page;
- nand->ecc.strength = cap;
-
- atmel_pmecc_core_init(mtd);
-
- return 0;
-}
-
-#else
-
-/* oob layout for large page size
- * bad block info is on bytes 0 and 1
- * the bytes have to be consecutives to avoid
- * several NAND_CMD_RNDOUT during read
- */
-static struct nand_ecclayout atmel_oobinfo_large = {
- .eccbytes = 4,
- .eccpos = {60, 61, 62, 63},
- .oobfree = {
- {2, 58}
- },
-};
-
-/* oob layout for small page size
- * bad block info is on bytes 4 and 5
- * the bytes have to be consecutives to avoid
- * several NAND_CMD_RNDOUT during read
- */
-static struct nand_ecclayout atmel_oobinfo_small = {
- .eccbytes = 4,
- .eccpos = {0, 1, 2, 3},
- .oobfree = {
- {6, 10}
- },
-};
-
-/*
- * Calculate HW ECC
- *
- * function called after a write
- *
- * mtd: MTD block structure
- * dat: raw data (unused)
- * ecc_code: buffer for ECC
- */
-static int atmel_nand_calculate(struct mtd_info *mtd,
- const u_char *dat, unsigned char *ecc_code)
-{
- unsigned int ecc_value;
-
- /* get the first 2 ECC bytes */
- ecc_value = ecc_readl(CONFIG_SYS_NAND_ECC_BASE, PR);
-
- ecc_code[0] = ecc_value & 0xFF;
- ecc_code[1] = (ecc_value >> 8) & 0xFF;
-
- /* get the last 2 ECC bytes */
- ecc_value = ecc_readl(CONFIG_SYS_NAND_ECC_BASE, NPR) & ATMEL_ECC_NPARITY;
-
- ecc_code[2] = ecc_value & 0xFF;
- ecc_code[3] = (ecc_value >> 8) & 0xFF;
-
- return 0;
-}
-
-/*
- * HW ECC read page function
- *
- * mtd: mtd info structure
- * chip: nand chip info structure
- * buf: buffer to store read data
- * oob_required: caller expects OOB data read to chip->oob_poi
- */
-static int atmel_nand_read_page(struct mtd_info *mtd, struct nand_chip *chip,
- uint8_t *buf, int oob_required, int page)
-{
- int eccsize = chip->ecc.size;
- int eccbytes = chip->ecc.bytes;
- uint32_t *eccpos = chip->ecc.layout->eccpos;
- uint8_t *p = buf;
- uint8_t *oob = chip->oob_poi;
- uint8_t *ecc_pos;
- int stat;
-
- /* read the page */
- chip->read_buf(mtd, p, eccsize);
-
- /* move to ECC position if needed */
- if (eccpos[0] != 0) {
- /* This only works on large pages
- * because the ECC controller waits for
- * NAND_CMD_RNDOUTSTART after the
- * NAND_CMD_RNDOUT.
- * anyway, for small pages, the eccpos[0] == 0
- */
- chip->cmdfunc(mtd, NAND_CMD_RNDOUT,
- mtd->writesize + eccpos[0], -1);
- }
-
- /* the ECC controller needs to read the ECC just after the data */
- ecc_pos = oob + eccpos[0];
- chip->read_buf(mtd, ecc_pos, eccbytes);
-
- /* check if there's an error */
- stat = chip->ecc.correct(mtd, p, oob, NULL);
-
- if (stat < 0)
- mtd->ecc_stats.failed++;
- else
- mtd->ecc_stats.corrected += stat;
-
- /* get back to oob start (end of page) */
- chip->cmdfunc(mtd, NAND_CMD_RNDOUT, mtd->writesize, -1);
-
- /* read the oob */
- chip->read_buf(mtd, oob, mtd->oobsize);
-
- return 0;
-}
-
-/*
- * HW ECC Correction
- *
- * function called after a read
- *
- * mtd: MTD block structure
- * dat: raw data read from the chip
- * read_ecc: ECC from the chip (unused)
- * isnull: unused
- *
- * Detect and correct a 1 bit error for a page
- */
-static int atmel_nand_correct(struct mtd_info *mtd, u_char *dat,
- u_char *read_ecc, u_char *isnull)
-{
- struct nand_chip *nand_chip = mtd->priv;
- unsigned int ecc_status;
- unsigned int ecc_word, ecc_bit;
-
- /* get the status from the Status Register */
- ecc_status = ecc_readl(CONFIG_SYS_NAND_ECC_BASE, SR);
-
- /* if there's no error */
- if (likely(!(ecc_status & ATMEL_ECC_RECERR)))
- return 0;
-
- /* get error bit offset (4 bits) */
- ecc_bit = ecc_readl(CONFIG_SYS_NAND_ECC_BASE, PR) & ATMEL_ECC_BITADDR;
- /* get word address (12 bits) */
- ecc_word = ecc_readl(CONFIG_SYS_NAND_ECC_BASE, PR) & ATMEL_ECC_WORDADDR;
- ecc_word >>= 4;
-
- /* if there are multiple errors */
- if (ecc_status & ATMEL_ECC_MULERR) {
- /* check if it is a freshly erased block
- * (filled with 0xff) */
- if ((ecc_bit == ATMEL_ECC_BITADDR)
- && (ecc_word == (ATMEL_ECC_WORDADDR >> 4))) {
- /* the block has just been erased, return OK */
- return 0;
- }
- /* it doesn't seems to be a freshly
- * erased block.
- * We can't correct so many errors */
- dev_warn(host->dev, "atmel_nand : multiple errors detected."
- " Unable to correct.\n");
- return -EIO;
- }
-
- /* if there's a single bit error : we can correct it */
- if (ecc_status & ATMEL_ECC_ECCERR) {
- /* there's nothing much to do here.
- * the bit error is on the ECC itself.
- */
- dev_warn(host->dev, "atmel_nand : one bit error on ECC code."
- " Nothing to correct\n");
- return 0;
- }
-
- dev_warn(host->dev, "atmel_nand : one bit error on data."
- " (word offset in the page :"
- " 0x%x bit offset : 0x%x)\n",
- ecc_word, ecc_bit);
- /* correct the error */
- if (nand_chip->options & NAND_BUSWIDTH_16) {
- /* 16 bits words */
- ((unsigned short *) dat)[ecc_word] ^= (1 << ecc_bit);
- } else {
- /* 8 bits words */
- dat[ecc_word] ^= (1 << ecc_bit);
- }
- dev_warn(host->dev, "atmel_nand : error corrected\n");
- return 1;
-}
-
-/*
- * Enable HW ECC : unused on most chips
- */
-static void atmel_nand_hwctl(struct mtd_info *mtd, int mode)
-{
-}
-
-int atmel_hwecc_nand_init_param(struct nand_chip *nand, struct mtd_info *mtd)
-{
- nand->ecc.mode = NAND_ECC_HW;
- nand->ecc.calculate = atmel_nand_calculate;
- nand->ecc.correct = atmel_nand_correct;
- nand->ecc.hwctl = atmel_nand_hwctl;
- nand->ecc.read_page = atmel_nand_read_page;
- nand->ecc.bytes = 4;
-
- if (nand->ecc.mode == NAND_ECC_HW) {
- /* ECC is calculated for the whole page (1 step) */
- nand->ecc.size = mtd->writesize;
-
- /* set ECC page size and oob layout */
- switch (mtd->writesize) {
- case 512:
- nand->ecc.layout = &atmel_oobinfo_small;
- ecc_writel(CONFIG_SYS_NAND_ECC_BASE, MR,
- ATMEL_ECC_PAGESIZE_528);
- break;
- case 1024:
- nand->ecc.layout = &atmel_oobinfo_large;
- ecc_writel(CONFIG_SYS_NAND_ECC_BASE, MR,
- ATMEL_ECC_PAGESIZE_1056);
- break;
- case 2048:
- nand->ecc.layout = &atmel_oobinfo_large;
- ecc_writel(CONFIG_SYS_NAND_ECC_BASE, MR,
- ATMEL_ECC_PAGESIZE_2112);
- break;
- case 4096:
- nand->ecc.layout = &atmel_oobinfo_large;
- ecc_writel(CONFIG_SYS_NAND_ECC_BASE, MR,
- ATMEL_ECC_PAGESIZE_4224);
- break;
- default:
- /* page size not handled by HW ECC */
- /* switching back to soft ECC */
- nand->ecc.mode = NAND_ECC_SOFT;
- nand->ecc.calculate = NULL;
- nand->ecc.correct = NULL;
- nand->ecc.hwctl = NULL;
- nand->ecc.read_page = NULL;
- nand->ecc.postpad = 0;
- nand->ecc.prepad = 0;
- nand->ecc.bytes = 0;
- break;
- }
- }
-
- return 0;
-}
-
-#endif /* CONFIG_ATMEL_NAND_HW_PMECC */
-
-#endif /* CONFIG_ATMEL_NAND_HWECC */
-
-static void at91_nand_hwcontrol(struct mtd_info *mtd,
- int cmd, unsigned int ctrl)
-{
- struct nand_chip *this = mtd->priv;
-
- if (ctrl & NAND_CTRL_CHANGE) {
- ulong IO_ADDR_W = (ulong) this->IO_ADDR_W;
- IO_ADDR_W &= ~(CONFIG_SYS_NAND_MASK_ALE
- | CONFIG_SYS_NAND_MASK_CLE);
-
- if (ctrl & NAND_CLE)
- IO_ADDR_W |= CONFIG_SYS_NAND_MASK_CLE;
- if (ctrl & NAND_ALE)
- IO_ADDR_W |= CONFIG_SYS_NAND_MASK_ALE;
-
-#ifdef CONFIG_SYS_NAND_ENABLE_PIN
- gpio_set_value(CONFIG_SYS_NAND_ENABLE_PIN, !(ctrl & NAND_NCE));
-#endif
- this->IO_ADDR_W = (void *) IO_ADDR_W;
- }
-
- if (cmd != NAND_CMD_NONE)
- writeb(cmd, this->IO_ADDR_W);
-}
-
-#ifdef CONFIG_SYS_NAND_READY_PIN
-static int at91_nand_ready(struct mtd_info *mtd)
-{
- return gpio_get_value(CONFIG_SYS_NAND_READY_PIN);
-}
-#endif
-
-#ifdef CONFIG_SPL_BUILD
-/* The following code is for SPL */
-static nand_info_t mtd;
-static struct nand_chip nand_chip;
-
-static int nand_command(int block, int page, uint32_t offs, u8 cmd)
-{
- struct nand_chip *this = mtd.priv;
- int page_addr = page + block * CONFIG_SYS_NAND_PAGE_COUNT;
- void (*hwctrl)(struct mtd_info *mtd, int cmd,
- unsigned int ctrl) = this->cmd_ctrl;
-
- while (this->dev_ready(&mtd))
- ;
-
- if (cmd == NAND_CMD_READOOB) {
- offs += CONFIG_SYS_NAND_PAGE_SIZE;
- cmd = NAND_CMD_READ0;
- }
-
- hwctrl(&mtd, cmd, NAND_CTRL_CLE | NAND_CTRL_CHANGE);
-
- if (this->options & NAND_BUSWIDTH_16)
- offs >>= 1;
-
- hwctrl(&mtd, offs & 0xff, NAND_CTRL_ALE | NAND_CTRL_CHANGE);
- hwctrl(&mtd, (offs >> 8) & 0xff, NAND_CTRL_ALE);
- hwctrl(&mtd, (page_addr & 0xff), NAND_CTRL_ALE);
- hwctrl(&mtd, ((page_addr >> 8) & 0xff), NAND_CTRL_ALE);
-#ifdef CONFIG_SYS_NAND_5_ADDR_CYCLE
- hwctrl(&mtd, (page_addr >> 16) & 0x0f, NAND_CTRL_ALE);
-#endif
- hwctrl(&mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
-
- hwctrl(&mtd, NAND_CMD_READSTART, NAND_CTRL_CLE | NAND_CTRL_CHANGE);
- hwctrl(&mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
-
- while (this->dev_ready(&mtd))
- ;
-
- return 0;
-}
-
-static int nand_is_bad_block(int block)
-{
- struct nand_chip *this = mtd.priv;
-
- nand_command(block, 0, CONFIG_SYS_NAND_BAD_BLOCK_POS, NAND_CMD_READOOB);
-
- if (this->options & NAND_BUSWIDTH_16) {
- if (readw(this->IO_ADDR_R) != 0xffff)
- return 1;
- } else {
- if (readb(this->IO_ADDR_R) != 0xff)
- return 1;
- }
-
- return 0;
-}
-
-#ifdef CONFIG_SPL_NAND_ECC
-static int nand_ecc_pos[] = CONFIG_SYS_NAND_ECCPOS;
-#define ECCSTEPS (CONFIG_SYS_NAND_PAGE_SIZE / \
- CONFIG_SYS_NAND_ECCSIZE)
-#define ECCTOTAL (ECCSTEPS * CONFIG_SYS_NAND_ECCBYTES)
-
-static int nand_read_page(int block, int page, void *dst)
-{
- struct nand_chip *this = mtd.priv;
- u_char ecc_calc[ECCTOTAL];
- u_char ecc_code[ECCTOTAL];
- u_char oob_data[CONFIG_SYS_NAND_OOBSIZE];
- int eccsize = CONFIG_SYS_NAND_ECCSIZE;
- int eccbytes = CONFIG_SYS_NAND_ECCBYTES;
- int eccsteps = ECCSTEPS;
- int i;
- uint8_t *p = dst;
- nand_command(block, page, 0, NAND_CMD_READ0);
-
- for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
- if (this->ecc.mode != NAND_ECC_SOFT)
- this->ecc.hwctl(&mtd, NAND_ECC_READ);
- this->read_buf(&mtd, p, eccsize);
- this->ecc.calculate(&mtd, p, &ecc_calc[i]);
- }
- this->read_buf(&mtd, oob_data, CONFIG_SYS_NAND_OOBSIZE);
-
- for (i = 0; i < ECCTOTAL; i++)
- ecc_code[i] = oob_data[nand_ecc_pos[i]];
-
- eccsteps = ECCSTEPS;
- p = dst;
-
- for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize)
- this->ecc.correct(&mtd, p, &ecc_code[i], &ecc_calc[i]);
-
- return 0;
-}
-#else
-static int nand_read_page(int block, int page, void *dst)
-{
- struct nand_chip *this = mtd.priv;
-
- nand_command(block, page, 0, NAND_CMD_READ0);
- atmel_nand_pmecc_read_page(&mtd, this, dst, 0, page);
-
- return 0;
-}
-#endif /* CONFIG_SPL_NAND_ECC */
-
-int nand_spl_load_image(uint32_t offs, unsigned int size, void *dst)
-{
- unsigned int block, lastblock;
- unsigned int page;
-
- block = offs / CONFIG_SYS_NAND_BLOCK_SIZE;
- lastblock = (offs + size - 1) / CONFIG_SYS_NAND_BLOCK_SIZE;
- page = (offs % CONFIG_SYS_NAND_BLOCK_SIZE) / CONFIG_SYS_NAND_PAGE_SIZE;
-
- while (block <= lastblock) {
- if (!nand_is_bad_block(block)) {
- while (page < CONFIG_SYS_NAND_PAGE_COUNT) {
- nand_read_page(block, page, dst);
- dst += CONFIG_SYS_NAND_PAGE_SIZE;
- page++;
- }
-
- page = 0;
- } else {
- lastblock++;
- }
-
- block++;
- }
-
- return 0;
-}
-
-int at91_nand_wait_ready(struct mtd_info *mtd)
-{
- struct nand_chip *this = mtd->priv;
-
- udelay(this->chip_delay);
-
- return 0;
-}
-
-int board_nand_init(struct nand_chip *nand)
-{
- int ret = 0;
-
- nand->ecc.mode = NAND_ECC_SOFT;
-#ifdef CONFIG_SYS_NAND_DBW_16
- nand->options = NAND_BUSWIDTH_16;
- nand->read_buf = nand_read_buf16;
-#else
- nand->read_buf = nand_read_buf;
-#endif
- nand->cmd_ctrl = at91_nand_hwcontrol;
-#ifdef CONFIG_SYS_NAND_READY_PIN
- nand->dev_ready = at91_nand_ready;
-#else
- nand->dev_ready = at91_nand_wait_ready;
-#endif
- nand->chip_delay = 20;
-
-#ifdef CONFIG_ATMEL_NAND_HWECC
-#ifdef CONFIG_ATMEL_NAND_HW_PMECC
- ret = atmel_pmecc_nand_init_params(nand, &mtd);
-#endif
-#endif
-
- return ret;
-}
-
-void nand_init(void)
-{
- mtd.writesize = CONFIG_SYS_NAND_PAGE_SIZE;
- mtd.oobsize = CONFIG_SYS_NAND_OOBSIZE;
- mtd.priv = &nand_chip;
- nand_chip.IO_ADDR_R = (void __iomem *)CONFIG_SYS_NAND_BASE;
- nand_chip.IO_ADDR_W = (void __iomem *)CONFIG_SYS_NAND_BASE;
- board_nand_init(&nand_chip);
-
-#ifdef CONFIG_SPL_NAND_ECC
- if (nand_chip.ecc.mode == NAND_ECC_SOFT) {
- nand_chip.ecc.calculate = nand_calculate_ecc;
- nand_chip.ecc.correct = nand_correct_data;
- }
-#endif
-
- if (nand_chip.select_chip)
- nand_chip.select_chip(&mtd, 0);
-}
-
-void nand_deselect(void)
-{
- if (nand_chip.select_chip)
- nand_chip.select_chip(&mtd, -1);
-}
-
-#else
-
-#ifndef CONFIG_SYS_NAND_BASE_LIST
-#define CONFIG_SYS_NAND_BASE_LIST { CONFIG_SYS_NAND_BASE }
-#endif
-static struct nand_chip nand_chip[CONFIG_SYS_MAX_NAND_DEVICE];
-static ulong base_addr[CONFIG_SYS_MAX_NAND_DEVICE] = CONFIG_SYS_NAND_BASE_LIST;
-
-int atmel_nand_chip_init(int devnum, ulong base_addr)
-{
- int ret;
- struct mtd_info *mtd = &nand_info[devnum];
- struct nand_chip *nand = &nand_chip[devnum];
-
- mtd->priv = nand;
- nand->IO_ADDR_R = nand->IO_ADDR_W = (void __iomem *)base_addr;
-
-#ifdef CONFIG_NAND_ECC_BCH
- nand->ecc.mode = NAND_ECC_SOFT_BCH;
-#else
- nand->ecc.mode = NAND_ECC_SOFT;
-#endif
-#ifdef CONFIG_SYS_NAND_DBW_16
- nand->options = NAND_BUSWIDTH_16;
-#endif
- nand->cmd_ctrl = at91_nand_hwcontrol;
-#ifdef CONFIG_SYS_NAND_READY_PIN
- nand->dev_ready = at91_nand_ready;
-#endif
- nand->chip_delay = 75;
-
- ret = nand_scan_ident(mtd, CONFIG_SYS_NAND_MAX_CHIPS, NULL);
- if (ret)
- return ret;
-
-#ifdef CONFIG_ATMEL_NAND_HWECC
-#ifdef CONFIG_ATMEL_NAND_HW_PMECC
- ret = atmel_pmecc_nand_init_params(nand, mtd);
-#else
- ret = atmel_hwecc_nand_init_param(nand, mtd);
-#endif
- if (ret)
- return ret;
-#endif
-
- ret = nand_scan_tail(mtd);
- if (!ret)
- nand_register(devnum);
-
- return ret;
-}
-
-void board_nand_init(void)
-{
- int i;
- for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++)
- if (atmel_nand_chip_init(i, base_addr[i]))
- dev_err(host->dev, "atmel_nand: Fail to initialize #%d chip",
- i);
-}
-#endif /* CONFIG_SPL_BUILD */
diff --git a/qemu/roms/u-boot/drivers/mtd/nand/atmel_nand_ecc.h b/qemu/roms/u-boot/drivers/mtd/nand/atmel_nand_ecc.h
deleted file mode 100644
index 55d7711c8..000000000
--- a/qemu/roms/u-boot/drivers/mtd/nand/atmel_nand_ecc.h
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * Error Corrected Code Controller (ECC) - System peripherals regsters.
- * Based on AT91SAM9260 datasheet revision B.
- *
- * SPDX-License-Identifier: GPL-2.0+
- */
-
-#ifndef ATMEL_NAND_ECC_H
-#define ATMEL_NAND_ECC_H
-
-#define ATMEL_ECC_CR 0x00 /* Control register */
-#define ATMEL_ECC_RST (1 << 0) /* Reset parity */
-
-#define ATMEL_ECC_MR 0x04 /* Mode register */
-#define ATMEL_ECC_PAGESIZE (3 << 0) /* Page Size */
-#define ATMEL_ECC_PAGESIZE_528 (0)
-#define ATMEL_ECC_PAGESIZE_1056 (1)
-#define ATMEL_ECC_PAGESIZE_2112 (2)
-#define ATMEL_ECC_PAGESIZE_4224 (3)
-
-#define ATMEL_ECC_SR 0x08 /* Status register */
-#define ATMEL_ECC_RECERR (1 << 0) /* Recoverable Error */
-#define ATMEL_ECC_ECCERR (1 << 1) /* ECC Single Bit Error */
-#define ATMEL_ECC_MULERR (1 << 2) /* Multiple Errors */
-
-#define ATMEL_ECC_PR 0x0c /* Parity register */
-#define ATMEL_ECC_BITADDR (0xf << 0) /* Bit Error Address */
-#define ATMEL_ECC_WORDADDR (0xfff << 4) /* Word Error Address */
-
-#define ATMEL_ECC_NPR 0x10 /* NParity register */
-#define ATMEL_ECC_NPARITY (0xffff << 0) /* NParity */
-
-/* Register access macros for PMECC */
-#define pmecc_readl(addr, reg) \
- readl(&addr->reg)
-
-#define pmecc_writel(addr, reg, value) \
- writel((value), &addr->reg)
-
-/* PMECC Register Definitions */
-#define PMECC_MAX_SECTOR_NUM 8
-struct pmecc_regs {
- u32 cfg; /* 0x00 PMECC Configuration Register */
- u32 sarea; /* 0x04 PMECC Spare Area Size Register */
- u32 saddr; /* 0x08 PMECC Start Address Register */
- u32 eaddr; /* 0x0C PMECC End Address Register */
- u32 clk; /* 0x10 PMECC Clock Control Register */
- u32 ctrl; /* 0x14 PMECC Control Register */
- u32 sr; /* 0x18 PMECC Status Register */
- u32 ier; /* 0x1C PMECC Interrupt Enable Register */
- u32 idr; /* 0x20 PMECC Interrupt Disable Register */
- u32 imr; /* 0x24 PMECC Interrupt Mask Register */
- u32 isr; /* 0x28 PMECC Interrupt Status Register */
- u32 reserved0[5]; /* 0x2C-0x3C Reserved */
-
- /* 0x40 + sector_num * (0x40), Redundancy Registers */
- struct {
- u8 ecc[44]; /* PMECC Generated Redundancy Byte Per Sector */
- u32 reserved1[5];
- } ecc_port[PMECC_MAX_SECTOR_NUM];
-
- /* 0x240 + sector_num * (0x40) Remainder Registers */
- struct {
- u32 rem[12];
- u32 reserved2[4];
- } rem_port[PMECC_MAX_SECTOR_NUM];
- u32 reserved3[16]; /* 0x440-0x47C Reserved */
-};
-
-/* For PMECC Configuration Register */
-#define PMECC_CFG_BCH_ERR2 (0 << 0)
-#define PMECC_CFG_BCH_ERR4 (1 << 0)
-#define PMECC_CFG_BCH_ERR8 (2 << 0)
-#define PMECC_CFG_BCH_ERR12 (3 << 0)
-#define PMECC_CFG_BCH_ERR24 (4 << 0)
-
-#define PMECC_CFG_SECTOR512 (0 << 4)
-#define PMECC_CFG_SECTOR1024 (1 << 4)
-
-#define PMECC_CFG_PAGE_1SECTOR (0 << 8)
-#define PMECC_CFG_PAGE_2SECTORS (1 << 8)
-#define PMECC_CFG_PAGE_4SECTORS (2 << 8)
-#define PMECC_CFG_PAGE_8SECTORS (3 << 8)
-
-#define PMECC_CFG_READ_OP (0 << 12)
-#define PMECC_CFG_WRITE_OP (1 << 12)
-
-#define PMECC_CFG_SPARE_ENABLE (1 << 16)
-#define PMECC_CFG_SPARE_DISABLE (0 << 16)
-
-#define PMECC_CFG_AUTO_ENABLE (1 << 20)
-#define PMECC_CFG_AUTO_DISABLE (0 << 20)
-
-/* For PMECC Clock Control Register */
-#define PMECC_CLK_133MHZ (2 << 0)
-
-/* For PMECC Control Register */
-#define PMECC_CTRL_RST (1 << 0)
-#define PMECC_CTRL_DATA (1 << 1)
-#define PMECC_CTRL_USER (1 << 2)
-#define PMECC_CTRL_ENABLE (1 << 4)
-#define PMECC_CTRL_DISABLE (1 << 5)
-
-/* For PMECC Status Register */
-#define PMECC_SR_BUSY (1 << 0)
-#define PMECC_SR_ENABLE (1 << 4)
-
-/* PMERRLOC Register Definitions */
-struct pmecc_errloc_regs {
- u32 elcfg; /* 0x00 Error Location Configuration Register */
- u32 elprim; /* 0x04 Error Location Primitive Register */
- u32 elen; /* 0x08 Error Location Enable Register */
- u32 eldis; /* 0x0C Error Location Disable Register */
- u32 elsr; /* 0x10 Error Location Status Register */
- u32 elier; /* 0x14 Error Location Interrupt Enable Register */
- u32 elidr; /* 0x08 Error Location Interrupt Disable Register */
- u32 elimr; /* 0x0C Error Location Interrupt Mask Register */
- u32 elisr; /* 0x20 Error Location Interrupt Status Register */
- u32 reserved0; /* 0x24 Reserved */
- u32 sigma[25]; /* 0x28-0x88 Error Location Sigma Registers */
- u32 el[24]; /* 0x8C-0xE8 Error Location Registers */
- u32 reserved1[5]; /* 0xEC-0xFC Reserved */
-};
-
-/* For Error Location Configuration Register */
-#define PMERRLOC_ELCFG_SECTOR_512 (0 << 0)
-#define PMERRLOC_ELCFG_SECTOR_1024 (1 << 0)
-#define PMERRLOC_ELCFG_NUM_ERRORS(n) ((n) << 16)
-
-/* For Error Location Disable Register */
-#define PMERRLOC_DISABLE (1 << 0)
-
-/* For Error Location Interrupt Status Register */
-#define PMERRLOC_ERR_NUM_MASK (0x1f << 8)
-#define PMERRLOC_CALC_DONE (1 << 0)
-
-/* Galois field dimension */
-#define PMECC_GF_DIMENSION_13 13
-#define PMECC_GF_DIMENSION_14 14
-
-#define PMECC_INDEX_TABLE_SIZE_512 0x2000
-#define PMECC_INDEX_TABLE_SIZE_1024 0x4000
-
-#define PMECC_MAX_TIMEOUT_US (100 * 1000)
-
-#endif
diff --git a/qemu/roms/u-boot/drivers/mtd/nand/bfin_nand.c b/qemu/roms/u-boot/drivers/mtd/nand/bfin_nand.c
deleted file mode 100644
index 7e755e896..000000000
--- a/qemu/roms/u-boot/drivers/mtd/nand/bfin_nand.c
+++ /dev/null
@@ -1,393 +0,0 @@
-/*
- * Driver for Blackfin on-chip NAND controller.
- *
- * Enter bugs at http://blackfin.uclinux.org/
- *
- * Copyright (c) 2007-2008 Analog Devices Inc.
- *
- * Licensed under the GPL-2 or later.
- */
-
-/* TODO:
- * - move bit defines into mach-common/bits/nand.h
- * - try and replace all IRQSTAT usage with STAT polling
- * - have software ecc mode use same algo as hw ecc ?
- */
-
-#include <common.h>
-#include <asm/io.h>
-
-#ifdef DEBUG
-# define pr_stamp() printf("%s:%s:%i: here i am\n", __FILE__, __func__, __LINE__)
-#else
-# define pr_stamp()
-#endif
-
-#include <nand.h>
-
-#include <asm/blackfin.h>
-#include <asm/portmux.h>
-
-/* Bit masks for NFC_CTL */
-
-#define WR_DLY 0xf /* Write Strobe Delay */
-#define RD_DLY 0xf0 /* Read Strobe Delay */
-#define NWIDTH 0x100 /* NAND Data Width */
-#define PG_SIZE 0x200 /* Page Size */
-
-/* Bit masks for NFC_STAT */
-
-#define NBUSY 0x1 /* Not Busy */
-#define WB_FULL 0x2 /* Write Buffer Full */
-#define PG_WR_STAT 0x4 /* Page Write Pending */
-#define PG_RD_STAT 0x8 /* Page Read Pending */
-#define WB_EMPTY 0x10 /* Write Buffer Empty */
-
-/* Bit masks for NFC_IRQSTAT */
-
-#define NBUSYIRQ 0x1 /* Not Busy IRQ */
-#define WB_OVF 0x2 /* Write Buffer Overflow */
-#define WB_EDGE 0x4 /* Write Buffer Edge Detect */
-#define RD_RDY 0x8 /* Read Data Ready */
-#define WR_DONE 0x10 /* Page Write Done */
-
-#define NAND_IS_512() (CONFIG_BFIN_NFC_CTL_VAL & 0x200)
-
-/*
- * hardware specific access to control-lines
- */
-static void bfin_nfc_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
-{
- pr_stamp();
-
- if (cmd == NAND_CMD_NONE)
- return;
-
- while (bfin_read_NFC_STAT() & WB_FULL)
- continue;
-
- if (ctrl & NAND_CLE)
- bfin_write_NFC_CMD(cmd);
- else
- bfin_write_NFC_ADDR(cmd);
- SSYNC();
-}
-
-static int bfin_nfc_devready(struct mtd_info *mtd)
-{
- pr_stamp();
- return (bfin_read_NFC_STAT() & NBUSY) ? 1 : 0;
-}
-
-/*
- * PIO mode for buffer writing and reading
- */
-static void bfin_nfc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
-{
- pr_stamp();
-
- int i;
-
- /*
- * Data reads are requested by first writing to NFC_DATA_RD
- * and then reading back from NFC_READ.
- */
- for (i = 0; i < len; ++i) {
- while (bfin_read_NFC_STAT() & WB_FULL)
- if (ctrlc())
- return;
-
- /* Contents do not matter */
- bfin_write_NFC_DATA_RD(0x0000);
- SSYNC();
-
- while (!(bfin_read_NFC_IRQSTAT() & RD_RDY))
- if (ctrlc())
- return;
-
- buf[i] = bfin_read_NFC_READ();
-
- bfin_write_NFC_IRQSTAT(RD_RDY);
- }
-}
-
-static uint8_t bfin_nfc_read_byte(struct mtd_info *mtd)
-{
- pr_stamp();
-
- uint8_t val;
- bfin_nfc_read_buf(mtd, &val, 1);
- return val;
-}
-
-static void bfin_nfc_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
-{
- pr_stamp();
-
- int i;
-
- for (i = 0; i < len; ++i) {
- while (bfin_read_NFC_STAT() & WB_FULL)
- if (ctrlc())
- return;
-
- bfin_write_NFC_DATA_WR(buf[i]);
- }
-
- /* Wait for the buffer to drain before we return */
- while (!(bfin_read_NFC_STAT() & WB_EMPTY))
- if (ctrlc())
- return;
-}
-
-/*
- * ECC functions
- * These allow the bfin to use the controller's ECC
- * generator block to ECC the data as it passes through
- */
-
-/*
- * ECC error correction function
- */
-static int bfin_nfc_correct_data_256(struct mtd_info *mtd, u_char *dat,
- u_char *read_ecc, u_char *calc_ecc)
-{
- u32 syndrome[5];
- u32 calced, stored;
- unsigned short failing_bit, failing_byte;
- u_char data;
-
- pr_stamp();
-
- calced = calc_ecc[0] | (calc_ecc[1] << 8) | (calc_ecc[2] << 16);
- stored = read_ecc[0] | (read_ecc[1] << 8) | (read_ecc[2] << 16);
-
- syndrome[0] = (calced ^ stored);
-
- /*
- * syndrome 0: all zero
- * No error in data
- * No action
- */
- if (!syndrome[0] || !calced || !stored)
- return 0;
-
- /*
- * sysdrome 0: only one bit is one
- * ECC data was incorrect
- * No action
- */
- if (hweight32(syndrome[0]) == 1)
- return 1;
-
- syndrome[1] = (calced & 0x7FF) ^ (stored & 0x7FF);
- syndrome[2] = (calced & 0x7FF) ^ ((calced >> 11) & 0x7FF);
- syndrome[3] = (stored & 0x7FF) ^ ((stored >> 11) & 0x7FF);
- syndrome[4] = syndrome[2] ^ syndrome[3];
-
- /*
- * sysdrome 0: exactly 11 bits are one, each parity
- * and parity' pair is 1 & 0 or 0 & 1.
- * 1-bit correctable error
- * Correct the error
- */
- if (hweight32(syndrome[0]) == 11 && syndrome[4] == 0x7FF) {
- failing_bit = syndrome[1] & 0x7;
- failing_byte = syndrome[1] >> 0x3;
- data = *(dat + failing_byte);
- data = data ^ (0x1 << failing_bit);
- *(dat + failing_byte) = data;
-
- return 0;
- }
-
- /*
- * sysdrome 0: random data
- * More than 1-bit error, non-correctable error
- * Discard data, mark bad block
- */
-
- return 1;
-}
-
-static int bfin_nfc_correct_data(struct mtd_info *mtd, u_char *dat,
- u_char *read_ecc, u_char *calc_ecc)
-{
- int ret;
-
- pr_stamp();
-
- ret = bfin_nfc_correct_data_256(mtd, dat, read_ecc, calc_ecc);
-
- /* If page size is 512, correct second 256 bytes */
- if (NAND_IS_512()) {
- dat += 256;
- read_ecc += 8;
- calc_ecc += 8;
- ret |= bfin_nfc_correct_data_256(mtd, dat, read_ecc, calc_ecc);
- }
-
- return ret;
-}
-
-static void reset_ecc(void)
-{
- bfin_write_NFC_RST(0x1);
- while (bfin_read_NFC_RST() & 1)
- continue;
-}
-
-static void bfin_nfc_enable_hwecc(struct mtd_info *mtd, int mode)
-{
- reset_ecc();
-}
-
-static int bfin_nfc_calculate_ecc(struct mtd_info *mtd,
- const u_char *dat, u_char *ecc_code)
-{
- u16 ecc0, ecc1;
- u32 code[2];
- u8 *p;
-
- pr_stamp();
-
- /* first 4 bytes ECC code for 256 page size */
- ecc0 = bfin_read_NFC_ECC0();
- ecc1 = bfin_read_NFC_ECC1();
-
- code[0] = (ecc0 & 0x7FF) | ((ecc1 & 0x7FF) << 11);
-
- /* first 3 bytes in ecc_code for 256 page size */
- p = (u8 *) code;
- memcpy(ecc_code, p, 3);
-
- /* second 4 bytes ECC code for 512 page size */
- if (NAND_IS_512()) {
- ecc0 = bfin_read_NFC_ECC2();
- ecc1 = bfin_read_NFC_ECC3();
- code[1] = (ecc0 & 0x7FF) | ((ecc1 & 0x7FF) << 11);
-
- /* second 3 bytes in ecc_code for second 256
- * bytes of 512 page size
- */
- p = (u8 *) (code + 1);
- memcpy((ecc_code + 3), p, 3);
- }
-
- reset_ecc();
-
- return 0;
-}
-
-#ifdef CONFIG_BFIN_NFC_BOOTROM_ECC
-# define BOOTROM_ECC 1
-#else
-# define BOOTROM_ECC 0
-#endif
-
-static uint8_t bbt_pattern[] = { 0xff };
-
-static struct nand_bbt_descr bootrom_bbt = {
- .options = 0,
- .offs = 63,
- .len = 1,
- .pattern = bbt_pattern,
-};
-
-static struct nand_ecclayout bootrom_ecclayout = {
- .eccbytes = 24,
- .eccpos = {
- 0x8 * 0, 0x8 * 0 + 1, 0x8 * 0 + 2,
- 0x8 * 1, 0x8 * 1 + 1, 0x8 * 1 + 2,
- 0x8 * 2, 0x8 * 2 + 1, 0x8 * 2 + 2,
- 0x8 * 3, 0x8 * 3 + 1, 0x8 * 3 + 2,
- 0x8 * 4, 0x8 * 4 + 1, 0x8 * 4 + 2,
- 0x8 * 5, 0x8 * 5 + 1, 0x8 * 5 + 2,
- 0x8 * 6, 0x8 * 6 + 1, 0x8 * 6 + 2,
- 0x8 * 7, 0x8 * 7 + 1, 0x8 * 7 + 2
- },
- .oobfree = {
- { 0x8 * 0 + 3, 5 },
- { 0x8 * 1 + 3, 5 },
- { 0x8 * 2 + 3, 5 },
- { 0x8 * 3 + 3, 5 },
- { 0x8 * 4 + 3, 5 },
- { 0x8 * 5 + 3, 5 },
- { 0x8 * 6 + 3, 5 },
- { 0x8 * 7 + 3, 5 },
- }
-};
-
-/*
- * Board-specific NAND initialization. The following members of the
- * argument are board-specific (per include/linux/mtd/nand.h):
- * - IO_ADDR_R?: address to read the 8 I/O lines of the flash device
- * - IO_ADDR_W?: address to write the 8 I/O lines of the flash device
- * - cmd_ctrl: hardwarespecific function for accesing control-lines
- * - dev_ready: hardwarespecific function for accesing device ready/busy line
- * - enable_hwecc?: function to enable (reset) hardware ecc generator. Must
- * only be provided if a hardware ECC is available
- * - ecc.mode: mode of ecc, see defines
- * - chip_delay: chip dependent delay for transfering data from array to
- * read regs (tR)
- * - options: various chip options. They can partly be set to inform
- * nand_scan about special functionality. See the defines for further
- * explanation
- * Members with a "?" were not set in the merged testing-NAND branch,
- * so they are not set here either.
- */
-int board_nand_init(struct nand_chip *chip)
-{
- const unsigned short pins[] = {
- P_NAND_CE, P_NAND_RB, P_NAND_D0, P_NAND_D1, P_NAND_D2,
- P_NAND_D3, P_NAND_D4, P_NAND_D5, P_NAND_D6, P_NAND_D7,
- P_NAND_WE, P_NAND_RE, P_NAND_CLE, P_NAND_ALE, 0,
- };
-
- pr_stamp();
-
- /* set width/ecc/timings/etc... */
- bfin_write_NFC_CTL(CONFIG_BFIN_NFC_CTL_VAL);
-
- /* clear interrupt status */
- bfin_write_NFC_IRQMASK(0x0);
- bfin_write_NFC_IRQSTAT(0xffff);
-
- /* enable GPIO function enable register */
- peripheral_request_list(pins, "bfin_nand");
-
- chip->cmd_ctrl = bfin_nfc_cmd_ctrl;
- chip->read_buf = bfin_nfc_read_buf;
- chip->write_buf = bfin_nfc_write_buf;
- chip->read_byte = bfin_nfc_read_byte;
-
-#ifdef CONFIG_BFIN_NFC_NO_HW_ECC
-# define ECC_HW 0
-#else
-# define ECC_HW 1
-#endif
- if (ECC_HW) {
- if (BOOTROM_ECC) {
- chip->badblock_pattern = &bootrom_bbt;
- chip->ecc.layout = &bootrom_ecclayout;
- }
- if (!NAND_IS_512()) {
- chip->ecc.bytes = 3;
- chip->ecc.size = 256;
- chip->ecc.strength = 1;
- } else {
- chip->ecc.bytes = 6;
- chip->ecc.size = 512;
- chip->ecc.strength = 2;
- }
- chip->ecc.mode = NAND_ECC_HW;
- chip->ecc.calculate = bfin_nfc_calculate_ecc;
- chip->ecc.correct = bfin_nfc_correct_data;
- chip->ecc.hwctl = bfin_nfc_enable_hwecc;
- } else
- chip->ecc.mode = NAND_ECC_SOFT;
- chip->dev_ready = bfin_nfc_devready;
- chip->chip_delay = 0;
-
- return 0;
-}
diff --git a/qemu/roms/u-boot/drivers/mtd/nand/davinci_nand.c b/qemu/roms/u-boot/drivers/mtd/nand/davinci_nand.c
deleted file mode 100644
index 75b03a74b..000000000
--- a/qemu/roms/u-boot/drivers/mtd/nand/davinci_nand.c
+++ /dev/null
@@ -1,653 +0,0 @@
-/*
- * NAND driver for TI DaVinci based boards.
- *
- * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net>
- *
- * Based on Linux DaVinci NAND driver by TI. Original copyright follows:
- */
-
-/*
- *
- * linux/drivers/mtd/nand/nand_davinci.c
- *
- * NAND Flash Driver
- *
- * Copyright (C) 2006 Texas Instruments.
- *
- * ----------------------------------------------------------------------------
- *
- * SPDX-License-Identifier: GPL-2.0+
- *
- * ----------------------------------------------------------------------------
- *
- * Overview:
- * This is a device driver for the NAND flash device found on the
- * DaVinci board which utilizes the Samsung k9k2g08 part.
- *
- Modifications:
- ver. 1.0: Feb 2005, Vinod/Sudhakar
- -
- */
-
-#include <common.h>
-#include <asm/io.h>
-#include <nand.h>
-#include <asm/arch/nand_defs.h>
-#include <asm/arch/emif_defs.h>
-
-/* Definitions for 4-bit hardware ECC */
-#define NAND_TIMEOUT 10240
-#define NAND_ECC_BUSY 0xC
-#define NAND_4BITECC_MASK 0x03FF03FF
-#define EMIF_NANDFSR_ECC_STATE_MASK 0x00000F00
-#define ECC_STATE_NO_ERR 0x0
-#define ECC_STATE_TOO_MANY_ERRS 0x1
-#define ECC_STATE_ERR_CORR_COMP_P 0x2
-#define ECC_STATE_ERR_CORR_COMP_N 0x3
-
-/*
- * Exploit the little endianness of the ARM to do multi-byte transfers
- * per device read. This can perform over twice as quickly as individual
- * byte transfers when buffer alignment is conducive.
- *
- * NOTE: This only works if the NAND is not connected to the 2 LSBs of
- * the address bus. On Davinci EVM platforms this has always been true.
- */
-static void nand_davinci_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
-{
- struct nand_chip *chip = mtd->priv;
- const u32 *nand = chip->IO_ADDR_R;
-
- /* Make sure that buf is 32 bit aligned */
- if (((int)buf & 0x3) != 0) {
- if (((int)buf & 0x1) != 0) {
- if (len) {
- *buf = readb(nand);
- buf += 1;
- len--;
- }
- }
-
- if (((int)buf & 0x3) != 0) {
- if (len >= 2) {
- *(u16 *)buf = readw(nand);
- buf += 2;
- len -= 2;
- }
- }
- }
-
- /* copy aligned data */
- while (len >= 4) {
- *(u32 *)buf = __raw_readl(nand);
- buf += 4;
- len -= 4;
- }
-
- /* mop up any remaining bytes */
- if (len) {
- if (len >= 2) {
- *(u16 *)buf = readw(nand);
- buf += 2;
- len -= 2;
- }
-
- if (len)
- *buf = readb(nand);
- }
-}
-
-static void nand_davinci_write_buf(struct mtd_info *mtd, const uint8_t *buf,
- int len)
-{
- struct nand_chip *chip = mtd->priv;
- const u32 *nand = chip->IO_ADDR_W;
-
- /* Make sure that buf is 32 bit aligned */
- if (((int)buf & 0x3) != 0) {
- if (((int)buf & 0x1) != 0) {
- if (len) {
- writeb(*buf, nand);
- buf += 1;
- len--;
- }
- }
-
- if (((int)buf & 0x3) != 0) {
- if (len >= 2) {
- writew(*(u16 *)buf, nand);
- buf += 2;
- len -= 2;
- }
- }
- }
-
- /* copy aligned data */
- while (len >= 4) {
- __raw_writel(*(u32 *)buf, nand);
- buf += 4;
- len -= 4;
- }
-
- /* mop up any remaining bytes */
- if (len) {
- if (len >= 2) {
- writew(*(u16 *)buf, nand);
- buf += 2;
- len -= 2;
- }
-
- if (len)
- writeb(*buf, nand);
- }
-}
-
-static void nand_davinci_hwcontrol(struct mtd_info *mtd, int cmd,
- unsigned int ctrl)
-{
- struct nand_chip *this = mtd->priv;
- u_int32_t IO_ADDR_W = (u_int32_t)this->IO_ADDR_W;
-
- if (ctrl & NAND_CTRL_CHANGE) {
- IO_ADDR_W &= ~(MASK_ALE|MASK_CLE);
-
- if (ctrl & NAND_CLE)
- IO_ADDR_W |= MASK_CLE;
- if (ctrl & NAND_ALE)
- IO_ADDR_W |= MASK_ALE;
- this->IO_ADDR_W = (void __iomem *) IO_ADDR_W;
- }
-
- if (cmd != NAND_CMD_NONE)
- writeb(cmd, IO_ADDR_W);
-}
-
-#ifdef CONFIG_SYS_NAND_HW_ECC
-
-static u_int32_t nand_davinci_readecc(struct mtd_info *mtd)
-{
- u_int32_t ecc = 0;
-
- ecc = __raw_readl(&(davinci_emif_regs->nandfecc[
- CONFIG_SYS_NAND_CS - 2]));
-
- return ecc;
-}
-
-static void nand_davinci_enable_hwecc(struct mtd_info *mtd, int mode)
-{
- u_int32_t val;
-
- /* reading the ECC result register resets the ECC calculation */
- nand_davinci_readecc(mtd);
-
- val = __raw_readl(&davinci_emif_regs->nandfcr);
- val |= DAVINCI_NANDFCR_NAND_ENABLE(CONFIG_SYS_NAND_CS);
- val |= DAVINCI_NANDFCR_1BIT_ECC_START(CONFIG_SYS_NAND_CS);
- __raw_writel(val, &davinci_emif_regs->nandfcr);
-}
-
-static int nand_davinci_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
- u_char *ecc_code)
-{
- u_int32_t tmp;
-
- tmp = nand_davinci_readecc(mtd);
-
- /* Squeeze 4 bytes ECC into 3 bytes by removing RESERVED bits
- * and shifting. RESERVED bits are 31 to 28 and 15 to 12. */
- tmp = (tmp & 0x00000fff) | ((tmp & 0x0fff0000) >> 4);
-
- /* Invert so that erased block ECC is correct */
- tmp = ~tmp;
-
- *ecc_code++ = tmp;
- *ecc_code++ = tmp >> 8;
- *ecc_code++ = tmp >> 16;
-
- /* NOTE: the above code matches mainline Linux:
- * .PQR.stu ==> ~PQRstu
- *
- * MontaVista/TI kernels encode those bytes differently, use
- * complicated (and allegedly sometimes-wrong) correction code,
- * and usually shipped with U-Boot that uses software ECC:
- * .PQR.stu ==> PsQRtu
- *
- * If you need MV/TI compatible NAND I/O in U-Boot, it should
- * be possible to (a) change the mangling above, (b) reverse
- * that mangling in nand_davinci_correct_data() below.
- */
-
- return 0;
-}
-
-static int nand_davinci_correct_data(struct mtd_info *mtd, u_char *dat,
- u_char *read_ecc, u_char *calc_ecc)
-{
- struct nand_chip *this = mtd->priv;
- u_int32_t ecc_nand = read_ecc[0] | (read_ecc[1] << 8) |
- (read_ecc[2] << 16);
- u_int32_t ecc_calc = calc_ecc[0] | (calc_ecc[1] << 8) |
- (calc_ecc[2] << 16);
- u_int32_t diff = ecc_calc ^ ecc_nand;
-
- if (diff) {
- if ((((diff >> 12) ^ diff) & 0xfff) == 0xfff) {
- /* Correctable error */
- if ((diff >> (12 + 3)) < this->ecc.size) {
- uint8_t find_bit = 1 << ((diff >> 12) & 7);
- uint32_t find_byte = diff >> (12 + 3);
-
- dat[find_byte] ^= find_bit;
- MTDDEBUG(MTD_DEBUG_LEVEL0, "Correcting single "
- "bit ECC error at offset: %d, bit: "
- "%d\n", find_byte, find_bit);
- return 1;
- } else {
- return -1;
- }
- } else if (!(diff & (diff - 1))) {
- /* Single bit ECC error in the ECC itself,
- nothing to fix */
- MTDDEBUG(MTD_DEBUG_LEVEL0, "Single bit ECC error in "
- "ECC.\n");
- return 1;
- } else {
- /* Uncorrectable error */
- MTDDEBUG(MTD_DEBUG_LEVEL0, "ECC UNCORRECTED_ERROR 1\n");
- return -1;
- }
- }
- return 0;
-}
-#endif /* CONFIG_SYS_NAND_HW_ECC */
-
-#ifdef CONFIG_SYS_NAND_4BIT_HW_ECC_OOBFIRST
-static struct nand_ecclayout nand_davinci_4bit_layout_oobfirst = {
-#if defined(CONFIG_SYS_NAND_PAGE_2K)
- .eccbytes = 40,
-#ifdef CONFIG_NAND_6BYTES_OOB_FREE_10BYTES_ECC
- .eccpos = {
- 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
- 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
- 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
- 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
- },
- .oobfree = {
- {2, 4}, {16, 6}, {32, 6}, {48, 6},
- },
-#else
- .eccpos = {
- 24, 25, 26, 27, 28,
- 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
- 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
- 49, 50, 51, 52, 53, 54, 55, 56, 57, 58,
- 59, 60, 61, 62, 63,
- },
- .oobfree = {
- {.offset = 2, .length = 22, },
- },
-#endif /* #ifdef CONFIG_NAND_6BYTES_OOB_FREE_10BYTES_ECC */
-#elif defined(CONFIG_SYS_NAND_PAGE_4K)
- .eccbytes = 80,
- .eccpos = {
- 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
- 58, 59, 60, 61, 62, 63, 64, 65, 66, 67,
- 68, 69, 70, 71, 72, 73, 74, 75, 76, 77,
- 78, 79, 80, 81, 82, 83, 84, 85, 86, 87,
- 88, 89, 90, 91, 92, 93, 94, 95, 96, 97,
- 98, 99, 100, 101, 102, 103, 104, 105, 106, 107,
- 108, 109, 110, 111, 112, 113, 114, 115, 116, 117,
- 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
- },
- .oobfree = {
- {.offset = 2, .length = 46, },
- },
-#endif
-};
-
-static void nand_davinci_4bit_enable_hwecc(struct mtd_info *mtd, int mode)
-{
- u32 val;
-
- switch (mode) {
- case NAND_ECC_WRITE:
- case NAND_ECC_READ:
- /*
- * Start a new ECC calculation for reading or writing 512 bytes
- * of data.
- */
- val = __raw_readl(&davinci_emif_regs->nandfcr);
- val &= ~DAVINCI_NANDFCR_4BIT_ECC_SEL_MASK;
- val |= DAVINCI_NANDFCR_NAND_ENABLE(CONFIG_SYS_NAND_CS);
- val |= DAVINCI_NANDFCR_4BIT_ECC_SEL(CONFIG_SYS_NAND_CS);
- val |= DAVINCI_NANDFCR_4BIT_ECC_START;
- __raw_writel(val, &davinci_emif_regs->nandfcr);
- break;
- case NAND_ECC_READSYN:
- val = __raw_readl(&davinci_emif_regs->nand4bitecc[0]);
- break;
- default:
- break;
- }
-}
-
-static u32 nand_davinci_4bit_readecc(struct mtd_info *mtd, unsigned int ecc[4])
-{
- int i;
-
- for (i = 0; i < 4; i++) {
- ecc[i] = __raw_readl(&davinci_emif_regs->nand4bitecc[i]) &
- NAND_4BITECC_MASK;
- }
-
- return 0;
-}
-
-static int nand_davinci_4bit_calculate_ecc(struct mtd_info *mtd,
- const uint8_t *dat,
- uint8_t *ecc_code)
-{
- unsigned int hw_4ecc[4];
- unsigned int i;
-
- nand_davinci_4bit_readecc(mtd, hw_4ecc);
-
- /*Convert 10 bit ecc value to 8 bit */
- for (i = 0; i < 2; i++) {
- unsigned int hw_ecc_low = hw_4ecc[i * 2];
- unsigned int hw_ecc_hi = hw_4ecc[(i * 2) + 1];
-
- /* Take first 8 bits from val1 (count1=0) or val5 (count1=1) */
- *ecc_code++ = hw_ecc_low & 0xFF;
-
- /*
- * Take 2 bits as LSB bits from val1 (count1=0) or val5
- * (count1=1) and 6 bits from val2 (count1=0) or
- * val5 (count1=1)
- */
- *ecc_code++ =
- ((hw_ecc_low >> 8) & 0x3) | ((hw_ecc_low >> 14) & 0xFC);
-
- /*
- * Take 4 bits from val2 (count1=0) or val5 (count1=1) and
- * 4 bits from val3 (count1=0) or val6 (count1=1)
- */
- *ecc_code++ =
- ((hw_ecc_low >> 22) & 0xF) | ((hw_ecc_hi << 4) & 0xF0);
-
- /*
- * Take 6 bits from val3(count1=0) or val6 (count1=1) and
- * 2 bits from val4 (count1=0) or val7 (count1=1)
- */
- *ecc_code++ =
- ((hw_ecc_hi >> 4) & 0x3F) | ((hw_ecc_hi >> 10) & 0xC0);
-
- /* Take 8 bits from val4 (count1=0) or val7 (count1=1) */
- *ecc_code++ = (hw_ecc_hi >> 18) & 0xFF;
- }
-
- return 0;
-}
-
-static int nand_davinci_4bit_correct_data(struct mtd_info *mtd, uint8_t *dat,
- uint8_t *read_ecc, uint8_t *calc_ecc)
-{
- int i;
- unsigned int hw_4ecc[4];
- unsigned int iserror;
- unsigned short *ecc16;
- unsigned int numerrors, erroraddress, errorvalue;
- u32 val;
-
- /*
- * Check for an ECC where all bytes are 0xFF. If this is the case, we
- * will assume we are looking at an erased page and we should ignore
- * the ECC.
- */
- for (i = 0; i < 10; i++) {
- if (read_ecc[i] != 0xFF)
- break;
- }
- if (i == 10)
- return 0;
-
- /* Convert 8 bit in to 10 bit */
- ecc16 = (unsigned short *)&read_ecc[0];
-
- /*
- * Write the parity values in the NAND Flash 4-bit ECC Load register.
- * Write each parity value one at a time starting from 4bit_ecc_val8
- * to 4bit_ecc_val1.
- */
-
- /*Take 2 bits from 8th byte and 8 bits from 9th byte */
- __raw_writel(((ecc16[4]) >> 6) & 0x3FF,
- &davinci_emif_regs->nand4biteccload);
-
- /* Take 4 bits from 7th byte and 6 bits from 8th byte */
- __raw_writel((((ecc16[3]) >> 12) & 0xF) | ((((ecc16[4])) << 4) & 0x3F0),
- &davinci_emif_regs->nand4biteccload);
-
- /* Take 6 bits from 6th byte and 4 bits from 7th byte */
- __raw_writel((ecc16[3] >> 2) & 0x3FF,
- &davinci_emif_regs->nand4biteccload);
-
- /* Take 8 bits from 5th byte and 2 bits from 6th byte */
- __raw_writel(((ecc16[2]) >> 8) | ((((ecc16[3])) << 8) & 0x300),
- &davinci_emif_regs->nand4biteccload);
-
- /*Take 2 bits from 3rd byte and 8 bits from 4th byte */
- __raw_writel((((ecc16[1]) >> 14) & 0x3) | ((((ecc16[2])) << 2) & 0x3FC),
- &davinci_emif_regs->nand4biteccload);
-
- /* Take 4 bits form 2nd bytes and 6 bits from 3rd bytes */
- __raw_writel(((ecc16[1]) >> 4) & 0x3FF,
- &davinci_emif_regs->nand4biteccload);
-
- /* Take 6 bits from 1st byte and 4 bits from 2nd byte */
- __raw_writel((((ecc16[0]) >> 10) & 0x3F) | (((ecc16[1]) << 6) & 0x3C0),
- &davinci_emif_regs->nand4biteccload);
-
- /* Take 10 bits from 0th and 1st bytes */
- __raw_writel((ecc16[0]) & 0x3FF,
- &davinci_emif_regs->nand4biteccload);
-
- /*
- * Perform a dummy read to the EMIF Revision Code and Status register.
- * This is required to ensure time for syndrome calculation after
- * writing the ECC values in previous step.
- */
-
- val = __raw_readl(&davinci_emif_regs->nandfsr);
-
- /*
- * Read the syndrome from the NAND Flash 4-Bit ECC 1-4 registers.
- * A syndrome value of 0 means no bit errors. If the syndrome is
- * non-zero then go further otherwise return.
- */
- nand_davinci_4bit_readecc(mtd, hw_4ecc);
-
- if (!(hw_4ecc[0] | hw_4ecc[1] | hw_4ecc[2] | hw_4ecc[3]))
- return 0;
-
- /*
- * Clear any previous address calculation by doing a dummy read of an
- * error address register.
- */
- val = __raw_readl(&davinci_emif_regs->nanderradd1);
-
- /*
- * Set the addr_calc_st bit(bit no 13) in the NAND Flash Control
- * register to 1.
- */
- __raw_writel(DAVINCI_NANDFCR_4BIT_CALC_START,
- &davinci_emif_regs->nandfcr);
-
- /*
- * Wait for the corr_state field (bits 8 to 11) in the
- * NAND Flash Status register to be not equal to 0x0, 0x1, 0x2, or 0x3.
- * Otherwise ECC calculation has not even begun and the next loop might
- * fail because of a false positive!
- */
- i = NAND_TIMEOUT;
- do {
- val = __raw_readl(&davinci_emif_regs->nandfsr);
- val &= 0xc00;
- i--;
- } while ((i > 0) && !val);
-
- /*
- * Wait for the corr_state field (bits 8 to 11) in the
- * NAND Flash Status register to be equal to 0x0, 0x1, 0x2, or 0x3.
- */
- i = NAND_TIMEOUT;
- do {
- val = __raw_readl(&davinci_emif_regs->nandfsr);
- val &= 0xc00;
- i--;
- } while ((i > 0) && val);
-
- iserror = __raw_readl(&davinci_emif_regs->nandfsr);
- iserror &= EMIF_NANDFSR_ECC_STATE_MASK;
- iserror = iserror >> 8;
-
- /*
- * ECC_STATE_TOO_MANY_ERRS (0x1) means errors cannot be
- * corrected (five or more errors). The number of errors
- * calculated (err_num field) differs from the number of errors
- * searched. ECC_STATE_ERR_CORR_COMP_P (0x2) means error
- * correction complete (errors on bit 8 or 9).
- * ECC_STATE_ERR_CORR_COMP_N (0x3) means error correction
- * complete (error exists).
- */
-
- if (iserror == ECC_STATE_NO_ERR) {
- val = __raw_readl(&davinci_emif_regs->nanderrval1);
- return 0;
- } else if (iserror == ECC_STATE_TOO_MANY_ERRS) {
- val = __raw_readl(&davinci_emif_regs->nanderrval1);
- return -1;
- }
-
- numerrors = ((__raw_readl(&davinci_emif_regs->nandfsr) >> 16)
- & 0x3) + 1;
-
- /* Read the error address, error value and correct */
- for (i = 0; i < numerrors; i++) {
- if (i > 1) {
- erroraddress =
- ((__raw_readl(&davinci_emif_regs->nanderradd2) >>
- (16 * (i & 1))) & 0x3FF);
- erroraddress = ((512 + 7) - erroraddress);
- errorvalue =
- ((__raw_readl(&davinci_emif_regs->nanderrval2) >>
- (16 * (i & 1))) & 0xFF);
- } else {
- erroraddress =
- ((__raw_readl(&davinci_emif_regs->nanderradd1) >>
- (16 * (i & 1))) & 0x3FF);
- erroraddress = ((512 + 7) - erroraddress);
- errorvalue =
- ((__raw_readl(&davinci_emif_regs->nanderrval1) >>
- (16 * (i & 1))) & 0xFF);
- }
- /* xor the corrupt data with error value */
- if (erroraddress < 512)
- dat[erroraddress] ^= errorvalue;
- }
-
- return numerrors;
-}
-#endif /* CONFIG_SYS_NAND_4BIT_HW_ECC_OOBFIRST */
-
-static int nand_davinci_dev_ready(struct mtd_info *mtd)
-{
- return __raw_readl(&davinci_emif_regs->nandfsr) & 0x1;
-}
-
-static void nand_flash_init(void)
-{
- /* This is for DM6446 EVM and *very* similar. DO NOT GROW THIS!
- * Instead, have your board_init() set EMIF timings, based on its
- * knowledge of the clocks and what devices are hooked up ... and
- * don't even do that unless no UBL handled it.
- */
-#ifdef CONFIG_SOC_DM644X
- u_int32_t acfg1 = 0x3ffffffc;
-
- /*------------------------------------------------------------------*
- * NAND FLASH CHIP TIMEOUT @ 459 MHz *
- * *
- * AEMIF.CLK freq = PLL1/6 = 459/6 = 76.5 MHz *
- * AEMIF.CLK period = 1/76.5 MHz = 13.1 ns *
- * *
- *------------------------------------------------------------------*/
- acfg1 = 0
- | (0 << 31) /* selectStrobe */
- | (0 << 30) /* extWait */
- | (1 << 26) /* writeSetup 10 ns */
- | (3 << 20) /* writeStrobe 40 ns */
- | (1 << 17) /* writeHold 10 ns */
- | (1 << 13) /* readSetup 10 ns */
- | (5 << 7) /* readStrobe 60 ns */
- | (1 << 4) /* readHold 10 ns */
- | (3 << 2) /* turnAround ?? ns */
- | (0 << 0) /* asyncSize 8-bit bus */
- ;
-
- __raw_writel(acfg1, &davinci_emif_regs->ab1cr); /* CS2 */
-
- /* NAND flash on CS2 */
- __raw_writel(0x00000101, &davinci_emif_regs->nandfcr);
-#endif
-}
-
-void davinci_nand_init(struct nand_chip *nand)
-{
- nand->chip_delay = 0;
-#ifdef CONFIG_SYS_NAND_USE_FLASH_BBT
- nand->bbt_options |= NAND_BBT_USE_FLASH;
-#endif
-#ifdef CONFIG_SYS_NAND_NO_SUBPAGE_WRITE
- nand->options |= NAND_NO_SUBPAGE_WRITE;
-#endif
-#ifdef CONFIG_SYS_NAND_HW_ECC
- nand->ecc.mode = NAND_ECC_HW;
- nand->ecc.size = 512;
- nand->ecc.bytes = 3;
- nand->ecc.strength = 1;
- nand->ecc.calculate = nand_davinci_calculate_ecc;
- nand->ecc.correct = nand_davinci_correct_data;
- nand->ecc.hwctl = nand_davinci_enable_hwecc;
-#else
- nand->ecc.mode = NAND_ECC_SOFT;
-#endif /* CONFIG_SYS_NAND_HW_ECC */
-#ifdef CONFIG_SYS_NAND_4BIT_HW_ECC_OOBFIRST
- nand->ecc.mode = NAND_ECC_HW_OOB_FIRST;
- nand->ecc.size = 512;
- nand->ecc.bytes = 10;
- nand->ecc.strength = 4;
- nand->ecc.calculate = nand_davinci_4bit_calculate_ecc;
- nand->ecc.correct = nand_davinci_4bit_correct_data;
- nand->ecc.hwctl = nand_davinci_4bit_enable_hwecc;
- nand->ecc.layout = &nand_davinci_4bit_layout_oobfirst;
-#endif
- /* Set address of hardware control function */
- nand->cmd_ctrl = nand_davinci_hwcontrol;
-
- nand->read_buf = nand_davinci_read_buf;
- nand->write_buf = nand_davinci_write_buf;
-
- nand->dev_ready = nand_davinci_dev_ready;
-
- nand_flash_init();
-}
-
-int board_nand_init(struct nand_chip *chip) __attribute__((weak));
-
-int board_nand_init(struct nand_chip *chip)
-{
- davinci_nand_init(chip);
- return 0;
-}
diff --git a/qemu/roms/u-boot/drivers/mtd/nand/docg4.c b/qemu/roms/u-boot/drivers/mtd/nand/docg4.c
deleted file mode 100644
index b9121c397..000000000
--- a/qemu/roms/u-boot/drivers/mtd/nand/docg4.c
+++ /dev/null
@@ -1,1028 +0,0 @@
-/*
- * drivers/mtd/nand/docg4.c
- *
- * Copyright (C) 2013 Mike Dunn <mikedunn@newsguy.com>
- *
- * SPDX-License-Identifier: GPL-2.0+
- *
- * mtd nand driver for M-Systems DiskOnChip G4
- *
- * Tested on the Palm Treo 680. The G4 is also present on Toshiba Portege, Asus
- * P526, some HTC smartphones (Wizard, Prophet, ...), O2 XDA Zinc, maybe others.
- * Should work on these as well. Let me know!
- *
- * TODO:
- *
- * Mechanism for management of password-protected areas
- *
- * Hamming ecc when reading oob only
- *
- * According to the M-Sys documentation, this device is also available in a
- * "dual-die" configuration having a 256MB capacity, but no mechanism for
- * detecting this variant is documented. Currently this driver assumes 128MB
- * capacity.
- *
- * Support for multiple cascaded devices ("floors"). Not sure which gadgets
- * contain multiple G4s in a cascaded configuration, if any.
- */
-
-
-#include <common.h>
-#include <asm/arch/hardware.h>
-#include <asm/io.h>
-#include <asm/bitops.h>
-#include <asm/errno.h>
-#include <malloc.h>
-#include <nand.h>
-#include <linux/bch.h>
-#include <linux/bitrev.h>
-#include <linux/mtd/docg4.h>
-
-/*
- * The device has a nop register which M-Sys claims is for the purpose of
- * inserting precise delays. But beware; at least some operations fail if the
- * nop writes are replaced with a generic delay!
- */
-static inline void write_nop(void __iomem *docptr)
-{
- writew(0, docptr + DOC_NOP);
-}
-
-
-static int poll_status(void __iomem *docptr)
-{
- /*
- * Busy-wait for the FLASHREADY bit to be set in the FLASHCONTROL
- * register. Operations known to take a long time (e.g., block erase)
- * should sleep for a while before calling this.
- */
-
- uint8_t flash_status;
-
- /* hardware quirk requires reading twice initially */
- flash_status = readb(docptr + DOC_FLASHCONTROL);
-
- do {
- flash_status = readb(docptr + DOC_FLASHCONTROL);
- } while (!(flash_status & DOC_CTRL_FLASHREADY));
-
- return 0;
-}
-
-static void write_addr(void __iomem *docptr, uint32_t docg4_addr)
-{
- /* write the four address bytes packed in docg4_addr to the device */
-
- writeb(docg4_addr & 0xff, docptr + DOC_FLASHADDRESS);
- docg4_addr >>= 8;
- writeb(docg4_addr & 0xff, docptr + DOC_FLASHADDRESS);
- docg4_addr >>= 8;
- writeb(docg4_addr & 0xff, docptr + DOC_FLASHADDRESS);
- docg4_addr >>= 8;
- writeb(docg4_addr & 0xff, docptr + DOC_FLASHADDRESS);
-}
-
-/*
- * This is a module parameter in the linux kernel version of this driver. It is
- * hard-coded to 'off' for u-boot. This driver uses oob to mark bad blocks.
- * This can be problematic when dealing with data not intended for the mtd/nand
- * subsystem. For example, on boards that boot from the docg4 and use the IPL
- * to load an spl + u-boot image, the blocks containing the image will be
- * reported as "bad" because the oob of the first page of each block contains a
- * magic number that the IPL looks for, which causes the badblock scan to
- * erroneously add them to the bad block table. To erase such a block, use
- * u-boot's 'nand scrub'. scrub is safe for the docg4. The device does have a
- * factory bad block table, but it is read-only, and is used in conjunction with
- * oob bad block markers that are written by mtd/nand when a block is deemed to
- * be bad. To read data from "bad" blocks, use 'read.raw'. Unfortunately,
- * read.raw does not use ecc, which would still work fine on such misidentified
- * bad blocks. TODO: u-boot nand utilities need the ability to ignore bad
- * blocks.
- */
-static const int ignore_badblocks; /* remains false */
-
-struct docg4_priv {
- int status;
- struct {
- unsigned int command;
- int column;
- int page;
- } last_command;
- uint8_t oob_buf[16];
- uint8_t ecc_buf[7];
- int oob_page;
- struct bch_control *bch;
-};
-/*
- * Oob bytes 0 - 6 are available to the user.
- * Byte 7 is hamming ecc for first 7 bytes. Bytes 8 - 14 are hw-generated ecc.
- * Byte 15 (the last) is used by the driver as a "page written" flag.
- */
-static struct nand_ecclayout docg4_oobinfo = {
- .eccbytes = 9,
- .eccpos = {7, 8, 9, 10, 11, 12, 13, 14, 15},
- .oobavail = 7,
- .oobfree = { {0, 7} }
-};
-
-static void reset(void __iomem *docptr)
-{
- /* full device reset */
-
- writew(DOC_ASICMODE_RESET | DOC_ASICMODE_MDWREN, docptr + DOC_ASICMODE);
- writew(~(DOC_ASICMODE_RESET | DOC_ASICMODE_MDWREN),
- docptr + DOC_ASICMODECONFIRM);
- write_nop(docptr);
-
- writew(DOC_ASICMODE_NORMAL | DOC_ASICMODE_MDWREN,
- docptr + DOC_ASICMODE);
- writew(~(DOC_ASICMODE_NORMAL | DOC_ASICMODE_MDWREN),
- docptr + DOC_ASICMODECONFIRM);
-
- writew(DOC_ECCCONF1_ECC_ENABLE, docptr + DOC_ECCCONF1);
-
- poll_status(docptr);
-}
-
-static void docg4_select_chip(struct mtd_info *mtd, int chip)
-{
- /*
- * Select among multiple cascaded chips ("floors"). Multiple floors are
- * not yet supported, so the only valid non-negative value is 0.
- */
- void __iomem *docptr = CONFIG_SYS_NAND_BASE;
-
- if (chip < 0)
- return; /* deselected */
-
- if (chip > 0)
- printf("multiple floors currently unsupported\n");
-
- writew(0, docptr + DOC_DEVICESELECT);
-}
-
-static void read_hw_ecc(void __iomem *docptr, uint8_t *ecc_buf)
-{
- /* read the 7 hw-generated ecc bytes */
-
- int i;
- for (i = 0; i < 7; i++) { /* hw quirk; read twice */
- ecc_buf[i] = readb(docptr + DOC_BCH_SYNDROM(i));
- ecc_buf[i] = readb(docptr + DOC_BCH_SYNDROM(i));
- }
-}
-
-static int correct_data(struct mtd_info *mtd, uint8_t *buf, int page)
-{
- /*
- * Called after a page read when hardware reports bitflips.
- * Up to four bitflips can be corrected.
- */
-
- struct nand_chip *nand = mtd->priv;
- struct docg4_priv *doc = nand->priv;
- void __iomem *docptr = CONFIG_SYS_NAND_BASE;
- int i, numerrs;
- unsigned int errpos[4];
- const uint8_t blank_read_hwecc[8] = {
- 0xcf, 0x72, 0xfc, 0x1b, 0xa9, 0xc7, 0xb9, 0 };
-
- read_hw_ecc(docptr, doc->ecc_buf); /* read 7 hw-generated ecc bytes */
-
- /* check if read error is due to a blank page */
- if (!memcmp(doc->ecc_buf, blank_read_hwecc, 7))
- return 0; /* yes */
-
- /* skip additional check of "written flag" if ignore_badblocks */
- if (!ignore_badblocks) {
- /*
- * If the hw ecc bytes are not those of a blank page, there's
- * still a chance that the page is blank, but was read with
- * errors. Check the "written flag" in last oob byte, which
- * is set to zero when a page is written. If more than half
- * the bits are set, assume a blank page. Unfortunately, the
- * bit flips(s) are not reported in stats.
- */
-
- if (doc->oob_buf[15]) {
- int bit, numsetbits = 0;
- unsigned long written_flag = doc->oob_buf[15];
-
- for (bit = 0; bit < 8; bit++) {
- if (written_flag & 0x01)
- numsetbits++;
- written_flag >>= 1;
- }
- if (numsetbits > 4) { /* assume blank */
- printf("errors in blank page at offset %08x\n",
- page * DOCG4_PAGE_SIZE);
- return 0;
- }
- }
- }
-
- /*
- * The hardware ecc unit produces oob_ecc ^ calc_ecc. The kernel's bch
- * algorithm is used to decode this. However the hw operates on page
- * data in a bit order that is the reverse of that of the bch alg,
- * requiring that the bits be reversed on the result. Thanks to Ivan
- * Djelic for his analysis!
- */
- for (i = 0; i < 7; i++)
- doc->ecc_buf[i] = bitrev8(doc->ecc_buf[i]);
-
- numerrs = decode_bch(doc->bch, NULL, DOCG4_USERDATA_LEN, NULL,
- doc->ecc_buf, NULL, errpos);
-
- if (numerrs == -EBADMSG) {
- printf("uncorrectable errors at offset %08x\n",
- page * DOCG4_PAGE_SIZE);
- return -EBADMSG;
- }
-
- BUG_ON(numerrs < 0); /* -EINVAL, or anything other than -EBADMSG */
-
- /* undo last step in BCH alg (modulo mirroring not needed) */
- for (i = 0; i < numerrs; i++)
- errpos[i] = (errpos[i] & ~7)|(7-(errpos[i] & 7));
-
- /* fix the errors */
- for (i = 0; i < numerrs; i++) {
- /* ignore if error within oob ecc bytes */
- if (errpos[i] > DOCG4_USERDATA_LEN * 8)
- continue;
-
- /* if error within oob area preceeding ecc bytes... */
- if (errpos[i] > DOCG4_PAGE_SIZE * 8)
- __change_bit(errpos[i] - DOCG4_PAGE_SIZE * 8,
- (unsigned long *)doc->oob_buf);
-
- else /* error in page data */
- __change_bit(errpos[i], (unsigned long *)buf);
- }
-
- printf("%d error(s) corrected at offset %08x\n",
- numerrs, page * DOCG4_PAGE_SIZE);
-
- return numerrs;
-}
-
-static int read_progstatus(struct docg4_priv *doc, void __iomem *docptr)
-{
- /*
- * This apparently checks the status of programming. Done after an
- * erasure, and after page data is written. On error, the status is
- * saved, to be later retrieved by the nand infrastructure code.
- */
-
- /* status is read from the I/O reg */
- uint16_t status1 = readw(docptr + DOC_IOSPACE_DATA);
- uint16_t status2 = readw(docptr + DOC_IOSPACE_DATA);
- uint16_t status3 = readw(docptr + DOCG4_MYSTERY_REG);
-
- MTDDEBUG(MTD_DEBUG_LEVEL3, "docg4: %s: %02x %02x %02x\n",
- __func__, status1, status2, status3);
-
- if (status1 != DOCG4_PROGSTATUS_GOOD ||
- status2 != DOCG4_PROGSTATUS_GOOD_2 ||
- status3 != DOCG4_PROGSTATUS_GOOD_2) {
- doc->status = NAND_STATUS_FAIL;
- printf("read_progstatus failed: %02x, %02x, %02x\n",
- status1, status2, status3);
- return -EIO;
- }
- return 0;
-}
-
-static int pageprog(struct mtd_info *mtd)
-{
- /*
- * Final step in writing a page. Writes the contents of its
- * internal buffer out to the flash array, or some such.
- */
-
- struct nand_chip *nand = mtd->priv;
- struct docg4_priv *doc = nand->priv;
- void __iomem *docptr = CONFIG_SYS_NAND_BASE;
- int retval = 0;
-
- MTDDEBUG(MTD_DEBUG_LEVEL3, "docg4: %s\n", __func__);
-
- writew(DOCG4_SEQ_PAGEPROG, docptr + DOC_FLASHSEQUENCE);
- writew(DOC_CMD_PROG_CYCLE2, docptr + DOC_FLASHCOMMAND);
- write_nop(docptr);
- write_nop(docptr);
-
- /* Just busy-wait; usleep_range() slows things down noticeably. */
- poll_status(docptr);
-
- writew(DOCG4_SEQ_FLUSH, docptr + DOC_FLASHSEQUENCE);
- writew(DOCG4_CMD_FLUSH, docptr + DOC_FLASHCOMMAND);
- writew(DOC_ECCCONF0_READ_MODE | 4, docptr + DOC_ECCCONF0);
- write_nop(docptr);
- write_nop(docptr);
- write_nop(docptr);
- write_nop(docptr);
- write_nop(docptr);
-
- retval = read_progstatus(doc, docptr);
- writew(0, docptr + DOC_DATAEND);
- write_nop(docptr);
- poll_status(docptr);
- write_nop(docptr);
-
- return retval;
-}
-
-static void sequence_reset(void __iomem *docptr)
-{
- /* common starting sequence for all operations */
-
- writew(DOC_CTRL_UNKNOWN | DOC_CTRL_CE, docptr + DOC_FLASHCONTROL);
- writew(DOC_SEQ_RESET, docptr + DOC_FLASHSEQUENCE);
- writew(DOC_CMD_RESET, docptr + DOC_FLASHCOMMAND);
- write_nop(docptr);
- write_nop(docptr);
- poll_status(docptr);
- write_nop(docptr);
-}
-
-static void read_page_prologue(void __iomem *docptr, uint32_t docg4_addr)
-{
- /* first step in reading a page */
-
- sequence_reset(docptr);
-
- writew(DOCG4_SEQ_PAGE_READ, docptr + DOC_FLASHSEQUENCE);
- writew(DOCG4_CMD_PAGE_READ, docptr + DOC_FLASHCOMMAND);
- write_nop(docptr);
-
- write_addr(docptr, docg4_addr);
-
- write_nop(docptr);
- writew(DOCG4_CMD_READ2, docptr + DOC_FLASHCOMMAND);
- write_nop(docptr);
- write_nop(docptr);
-
- poll_status(docptr);
-}
-
-static void write_page_prologue(void __iomem *docptr, uint32_t docg4_addr)
-{
- /* first step in writing a page */
-
- sequence_reset(docptr);
- writew(DOCG4_SEQ_PAGEWRITE, docptr + DOC_FLASHSEQUENCE);
- writew(DOCG4_CMD_PAGEWRITE, docptr + DOC_FLASHCOMMAND);
- write_nop(docptr);
- write_addr(docptr, docg4_addr);
- write_nop(docptr);
- write_nop(docptr);
- poll_status(docptr);
-}
-
-static uint32_t mtd_to_docg4_address(int page, int column)
-{
- /*
- * Convert mtd address to format used by the device, 32 bit packed.
- *
- * Some notes on G4 addressing... The M-Sys documentation on this device
- * claims that pages are 2K in length, and indeed, the format of the
- * address used by the device reflects that. But within each page are
- * four 512 byte "sub-pages", each with its own oob data that is
- * read/written immediately after the 512 bytes of page data. This oob
- * data contains the ecc bytes for the preceeding 512 bytes.
- *
- * Rather than tell the mtd nand infrastructure that page size is 2k,
- * with four sub-pages each, we engage in a little subterfuge and tell
- * the infrastructure code that pages are 512 bytes in size. This is
- * done because during the course of reverse-engineering the device, I
- * never observed an instance where an entire 2K "page" was read or
- * written as a unit. Each "sub-page" is always addressed individually,
- * its data read/written, and ecc handled before the next "sub-page" is
- * addressed.
- *
- * This requires us to convert addresses passed by the mtd nand
- * infrastructure code to those used by the device.
- *
- * The address that is written to the device consists of four bytes: the
- * first two are the 2k page number, and the second is the index into
- * the page. The index is in terms of 16-bit half-words and includes
- * the preceeding oob data, so e.g., the index into the second
- * "sub-page" is 0x108, and the full device address of the start of mtd
- * page 0x201 is 0x00800108.
- */
- int g4_page = page / 4; /* device's 2K page */
- int g4_index = (page % 4) * 0x108 + column/2; /* offset into page */
- return (g4_page << 16) | g4_index; /* pack */
-}
-
-static void docg4_command(struct mtd_info *mtd, unsigned command, int column,
- int page_addr)
-{
- /* handle standard nand commands */
-
- struct nand_chip *nand = mtd->priv;
- struct docg4_priv *doc = nand->priv;
- uint32_t g4_addr = mtd_to_docg4_address(page_addr, column);
-
- MTDDEBUG(MTD_DEBUG_LEVEL3, "%s %x, page_addr=%x, column=%x\n",
- __func__, command, page_addr, column);
-
- /*
- * Save the command and its arguments. This enables emulation of
- * standard flash devices, and also some optimizations.
- */
- doc->last_command.command = command;
- doc->last_command.column = column;
- doc->last_command.page = page_addr;
-
- switch (command) {
- case NAND_CMD_RESET:
- reset(CONFIG_SYS_NAND_BASE);
- break;
-
- case NAND_CMD_READ0:
- read_page_prologue(CONFIG_SYS_NAND_BASE, g4_addr);
- break;
-
- case NAND_CMD_STATUS:
- /* next call to read_byte() will expect a status */
- break;
-
- case NAND_CMD_SEQIN:
- write_page_prologue(CONFIG_SYS_NAND_BASE, g4_addr);
-
- /* hack for deferred write of oob bytes */
- if (doc->oob_page == page_addr)
- memcpy(nand->oob_poi, doc->oob_buf, 16);
- break;
-
- case NAND_CMD_PAGEPROG:
- pageprog(mtd);
- break;
-
- /* we don't expect these, based on review of nand_base.c */
- case NAND_CMD_READOOB:
- case NAND_CMD_READID:
- case NAND_CMD_ERASE1:
- case NAND_CMD_ERASE2:
- printf("docg4_command: unexpected nand command 0x%x\n",
- command);
- break;
- }
-}
-
-static void docg4_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
-{
- int i;
- struct nand_chip *nand = mtd->priv;
- uint16_t *p = (uint16_t *)buf;
- len >>= 1;
-
- for (i = 0; i < len; i++)
- p[i] = readw(nand->IO_ADDR_R);
-}
-
-static int docg4_read_oob(struct mtd_info *mtd, struct nand_chip *nand,
- int page)
-{
- struct docg4_priv *doc = nand->priv;
- void __iomem *docptr = CONFIG_SYS_NAND_BASE;
- uint16_t status;
-
- MTDDEBUG(MTD_DEBUG_LEVEL3, "%s: page %x\n", __func__, page);
-
- /*
- * Oob bytes are read as part of a normal page read. If the previous
- * nand command was a read of the page whose oob is now being read, just
- * copy the oob bytes that we saved in a local buffer and avoid a
- * separate oob read.
- */
- if (doc->last_command.command == NAND_CMD_READ0 &&
- doc->last_command.page == page) {
- memcpy(nand->oob_poi, doc->oob_buf, 16);
- return 0;
- }
-
- /*
- * Separate read of oob data only.
- */
- docg4_command(mtd, NAND_CMD_READ0, nand->ecc.size, page);
-
- writew(DOC_ECCCONF0_READ_MODE | DOCG4_OOB_SIZE, docptr + DOC_ECCCONF0);
- write_nop(docptr);
- write_nop(docptr);
- write_nop(docptr);
- write_nop(docptr);
- write_nop(docptr);
-
- /* the 1st byte from the I/O reg is a status; the rest is oob data */
- status = readw(docptr + DOC_IOSPACE_DATA);
- if (status & DOCG4_READ_ERROR) {
- printf("docg4_read_oob failed: status = 0x%02x\n", status);
- return -EIO;
- }
-
- MTDDEBUG(MTD_DEBUG_LEVEL3, "%s: status = 0x%x\n", __func__, status);
-
- docg4_read_buf(mtd, nand->oob_poi, 16);
-
- write_nop(docptr);
- write_nop(docptr);
- write_nop(docptr);
- writew(0, docptr + DOC_DATAEND);
- write_nop(docptr);
-
- return 0;
-}
-
-static int docg4_write_oob(struct mtd_info *mtd, struct nand_chip *nand,
- int page)
-{
- /*
- * Writing oob-only is not really supported, because MLC nand must write
- * oob bytes at the same time as page data. Nonetheless, we save the
- * oob buffer contents here, and then write it along with the page data
- * if the same page is subsequently written. This allows user space
- * utilities that write the oob data prior to the page data to work
- * (e.g., nandwrite). The disdvantage is that, if the intention was to
- * write oob only, the operation is quietly ignored. Also, oob can get
- * corrupted if two concurrent processes are running nandwrite.
- */
-
- /* note that bytes 7..14 are hw generated hamming/ecc and overwritten */
- struct docg4_priv *doc = nand->priv;
- doc->oob_page = page;
- memcpy(doc->oob_buf, nand->oob_poi, 16);
- return 0;
-}
-
-static int docg4_block_neverbad(struct mtd_info *mtd, loff_t ofs, int getchip)
-{
- /* only called when module_param ignore_badblocks is set */
- return 0;
-}
-
-static void docg4_write_buf16(struct mtd_info *mtd, const uint8_t *buf, int len)
-{
- int i;
- struct nand_chip *nand = mtd->priv;
- uint16_t *p = (uint16_t *)buf;
- len >>= 1;
-
- for (i = 0; i < len; i++)
- writew(p[i], nand->IO_ADDR_W);
-}
-
-static int write_page(struct mtd_info *mtd, struct nand_chip *nand,
- const uint8_t *buf, int use_ecc)
-{
- void __iomem *docptr = CONFIG_SYS_NAND_BASE;
- uint8_t ecc_buf[8];
-
- writew(DOC_ECCCONF0_ECC_ENABLE |
- DOC_ECCCONF0_UNKNOWN |
- DOCG4_BCH_SIZE,
- docptr + DOC_ECCCONF0);
- write_nop(docptr);
-
- /* write the page data */
- docg4_write_buf16(mtd, buf, DOCG4_PAGE_SIZE);
-
- /* oob bytes 0 through 5 are written to I/O reg */
- docg4_write_buf16(mtd, nand->oob_poi, 6);
-
- /* oob byte 6 written to a separate reg */
- writew(nand->oob_poi[6], docptr + DOCG4_OOB_6_7);
-
- write_nop(docptr);
- write_nop(docptr);
-
- /* write hw-generated ecc bytes to oob */
- if (likely(use_ecc)) {
- /* oob byte 7 is hamming code */
- uint8_t hamming = readb(docptr + DOC_HAMMINGPARITY);
- hamming = readb(docptr + DOC_HAMMINGPARITY); /* 2nd read */
- writew(hamming, docptr + DOCG4_OOB_6_7);
- write_nop(docptr);
-
- /* read the 7 bch bytes from ecc regs */
- read_hw_ecc(docptr, ecc_buf);
- ecc_buf[7] = 0; /* clear the "page written" flag */
- }
-
- /* write user-supplied bytes to oob */
- else {
- writew(nand->oob_poi[7], docptr + DOCG4_OOB_6_7);
- write_nop(docptr);
- memcpy(ecc_buf, &nand->oob_poi[8], 8);
- }
-
- docg4_write_buf16(mtd, ecc_buf, 8);
- write_nop(docptr);
- write_nop(docptr);
- writew(0, docptr + DOC_DATAEND);
- write_nop(docptr);
-
- return 0;
-}
-
-static int docg4_write_page_raw(struct mtd_info *mtd, struct nand_chip *nand,
- const uint8_t *buf, int oob_required)
-{
- return write_page(mtd, nand, buf, 0);
-}
-
-static int docg4_write_page(struct mtd_info *mtd, struct nand_chip *nand,
- const uint8_t *buf, int oob_required)
-{
- return write_page(mtd, nand, buf, 1);
-}
-
-static int read_page(struct mtd_info *mtd, struct nand_chip *nand,
- uint8_t *buf, int page, int use_ecc)
-{
- struct docg4_priv *doc = nand->priv;
- void __iomem *docptr = CONFIG_SYS_NAND_BASE;
- uint16_t status, edc_err, *buf16;
-
- writew(DOC_ECCCONF0_READ_MODE |
- DOC_ECCCONF0_ECC_ENABLE |
- DOC_ECCCONF0_UNKNOWN |
- DOCG4_BCH_SIZE,
- docptr + DOC_ECCCONF0);
- write_nop(docptr);
- write_nop(docptr);
- write_nop(docptr);
- write_nop(docptr);
- write_nop(docptr);
-
- /* the 1st byte from the I/O reg is a status; the rest is page data */
- status = readw(docptr + DOC_IOSPACE_DATA);
- if (status & DOCG4_READ_ERROR) {
- printf("docg4_read_page: bad status: 0x%02x\n", status);
- writew(0, docptr + DOC_DATAEND);
- return -EIO;
- }
-
- docg4_read_buf(mtd, buf, DOCG4_PAGE_SIZE); /* read the page data */
-
- /* first 14 oob bytes read from I/O reg */
- docg4_read_buf(mtd, nand->oob_poi, 14);
-
- /* last 2 read from another reg */
- buf16 = (uint16_t *)(nand->oob_poi + 14);
- *buf16 = readw(docptr + DOCG4_MYSTERY_REG);
-
- /*
- * Diskonchips read oob immediately after a page read. Mtd
- * infrastructure issues a separate command for reading oob after the
- * page is read. So we save the oob bytes in a local buffer and just
- * copy it if the next command reads oob from the same page.
- */
- memcpy(doc->oob_buf, nand->oob_poi, 16);
-
- write_nop(docptr);
-
- if (likely(use_ecc)) {
- /* read the register that tells us if bitflip(s) detected */
- edc_err = readw(docptr + DOC_ECCCONF1);
- edc_err = readw(docptr + DOC_ECCCONF1);
-
- /* If bitflips are reported, attempt to correct with ecc */
- if (edc_err & DOC_ECCCONF1_BCH_SYNDROM_ERR) {
- int bits_corrected = correct_data(mtd, buf, page);
- if (bits_corrected == -EBADMSG)
- mtd->ecc_stats.failed++;
- else
- mtd->ecc_stats.corrected += bits_corrected;
- }
- }
-
- writew(0, docptr + DOC_DATAEND);
- return 0;
-}
-
-
-static int docg4_read_page_raw(struct mtd_info *mtd, struct nand_chip *nand,
- uint8_t *buf, int oob_required, int page)
-{
- return read_page(mtd, nand, buf, page, 0);
-}
-
-static int docg4_read_page(struct mtd_info *mtd, struct nand_chip *nand,
- uint8_t *buf, int oob_required, int page)
-{
- return read_page(mtd, nand, buf, page, 1);
-}
-
-static void docg4_erase_block(struct mtd_info *mtd, int page)
-{
- struct nand_chip *nand = mtd->priv;
- struct docg4_priv *doc = nand->priv;
- void __iomem *docptr = CONFIG_SYS_NAND_BASE;
- uint16_t g4_page;
-
- MTDDEBUG(MTD_DEBUG_LEVEL3, "%s: page %04x\n", __func__, page);
-
- sequence_reset(docptr);
-
- writew(DOCG4_SEQ_BLOCKERASE, docptr + DOC_FLASHSEQUENCE);
- writew(DOC_CMD_PROG_BLOCK_ADDR, docptr + DOC_FLASHCOMMAND);
- write_nop(docptr);
-
- /* only 2 bytes of address are written to specify erase block */
- g4_page = (uint16_t)(page / 4); /* to g4's 2k page addressing */
- writeb(g4_page & 0xff, docptr + DOC_FLASHADDRESS);
- g4_page >>= 8;
- writeb(g4_page & 0xff, docptr + DOC_FLASHADDRESS);
- write_nop(docptr);
-
- /* start the erasure */
- writew(DOC_CMD_ERASECYCLE2, docptr + DOC_FLASHCOMMAND);
- write_nop(docptr);
- write_nop(docptr);
-
- poll_status(docptr);
- writew(DOCG4_SEQ_FLUSH, docptr + DOC_FLASHSEQUENCE);
- writew(DOCG4_CMD_FLUSH, docptr + DOC_FLASHCOMMAND);
- writew(DOC_ECCCONF0_READ_MODE | 4, docptr + DOC_ECCCONF0);
- write_nop(docptr);
- write_nop(docptr);
- write_nop(docptr);
- write_nop(docptr);
- write_nop(docptr);
-
- read_progstatus(doc, docptr);
-
- writew(0, docptr + DOC_DATAEND);
- write_nop(docptr);
- poll_status(docptr);
- write_nop(docptr);
-}
-
-static int read_factory_bbt(struct mtd_info *mtd)
-{
- /*
- * The device contains a read-only factory bad block table. Read it and
- * update the memory-based bbt accordingly.
- */
-
- struct nand_chip *nand = mtd->priv;
- uint32_t g4_addr = mtd_to_docg4_address(DOCG4_FACTORY_BBT_PAGE, 0);
- uint8_t *buf;
- int i, block, status;
-
- buf = kzalloc(DOCG4_PAGE_SIZE, GFP_KERNEL);
- if (buf == NULL)
- return -ENOMEM;
-
- read_page_prologue(CONFIG_SYS_NAND_BASE, g4_addr);
- status = docg4_read_page(mtd, nand, buf, 0, DOCG4_FACTORY_BBT_PAGE);
- if (status)
- goto exit;
-
- /*
- * If no memory-based bbt was created, exit. This will happen if module
- * parameter ignore_badblocks is set. Then why even call this function?
- * For an unknown reason, block erase always fails if it's the first
- * operation after device power-up. The above read ensures it never is.
- * Ugly, I know.
- */
- if (nand->bbt == NULL) /* no memory-based bbt */
- goto exit;
-
- /*
- * Parse factory bbt and update memory-based bbt. Factory bbt format is
- * simple: one bit per block, block numbers increase left to right (msb
- * to lsb). Bit clear means bad block.
- */
- for (i = block = 0; block < DOCG4_NUMBLOCKS; block += 8, i++) {
- int bitnum;
- uint8_t mask;
- for (bitnum = 0, mask = 0x80;
- bitnum < 8; bitnum++, mask >>= 1) {
- if (!(buf[i] & mask)) {
- int badblock = block + bitnum;
- nand->bbt[badblock / 4] |=
- 0x03 << ((badblock % 4) * 2);
- mtd->ecc_stats.badblocks++;
- printf("factory-marked bad block: %d\n",
- badblock);
- }
- }
- }
- exit:
- kfree(buf);
- return status;
-}
-
-static int docg4_block_markbad(struct mtd_info *mtd, loff_t ofs)
-{
- /*
- * Mark a block as bad. Bad blocks are marked in the oob area of the
- * first page of the block. The default scan_bbt() in the nand
- * infrastructure code works fine for building the memory-based bbt
- * during initialization, as does the nand infrastructure function that
- * checks if a block is bad by reading the bbt. This function replaces
- * the nand default because writes to oob-only are not supported.
- */
-
- int ret, i;
- uint8_t *buf;
- struct nand_chip *nand = mtd->priv;
- struct nand_bbt_descr *bbtd = nand->badblock_pattern;
- int block = (int)(ofs >> nand->bbt_erase_shift);
- int page = (int)(ofs >> nand->page_shift);
- uint32_t g4_addr = mtd_to_docg4_address(page, 0);
-
- MTDDEBUG(MTD_DEBUG_LEVEL3, "%s: %08llx\n", __func__, ofs);
-
- if (unlikely(ofs & (DOCG4_BLOCK_SIZE - 1)))
- printf("%s: ofs %llx not start of block!\n",
- __func__, ofs);
-
- /* allocate blank buffer for page data */
- buf = kzalloc(DOCG4_PAGE_SIZE, GFP_KERNEL);
- if (buf == NULL)
- return -ENOMEM;
-
- /* update bbt in memory */
- nand->bbt[block / 4] |= 0x01 << ((block & 0x03) * 2);
-
- /* write bit-wise negation of pattern to oob buffer */
- memset(nand->oob_poi, 0xff, mtd->oobsize);
- for (i = 0; i < bbtd->len; i++)
- nand->oob_poi[bbtd->offs + i] = ~bbtd->pattern[i];
-
- /* write first page of block */
- write_page_prologue(CONFIG_SYS_NAND_BASE, g4_addr);
- docg4_write_page(mtd, nand, buf, 1);
- ret = pageprog(mtd);
- if (!ret)
- mtd->ecc_stats.badblocks++;
-
- kfree(buf);
-
- return ret;
-}
-
-static uint8_t docg4_read_byte(struct mtd_info *mtd)
-{
- struct nand_chip *nand = mtd->priv;
- struct docg4_priv *doc = nand->priv;
-
- MTDDEBUG(MTD_DEBUG_LEVEL3, "%s\n", __func__);
-
- if (doc->last_command.command == NAND_CMD_STATUS) {
- int status;
-
- /*
- * Previous nand command was status request, so nand
- * infrastructure code expects to read the status here. If an
- * error occurred in a previous operation, report it.
- */
- doc->last_command.command = 0;
-
- if (doc->status) {
- status = doc->status;
- doc->status = 0;
- }
-
- /* why is NAND_STATUS_WP inverse logic?? */
- else
- status = NAND_STATUS_WP | NAND_STATUS_READY;
-
- return status;
- }
-
- printf("unexpectd call to read_byte()\n");
-
- return 0;
-}
-
-static int docg4_wait(struct mtd_info *mtd, struct nand_chip *nand)
-{
- struct docg4_priv *doc = nand->priv;
- int status = NAND_STATUS_WP; /* inverse logic?? */
- MTDDEBUG(MTD_DEBUG_LEVEL3, "%s...\n", __func__);
-
- /* report any previously unreported error */
- if (doc->status) {
- status |= doc->status;
- doc->status = 0;
- return status;
- }
-
- status |= poll_status(CONFIG_SYS_NAND_BASE);
- return status;
-}
-
-int docg4_nand_init(struct mtd_info *mtd, struct nand_chip *nand, int devnum)
-{
- uint16_t id1, id2;
- struct docg4_priv *docg4;
- int retval;
-
- docg4 = kzalloc(sizeof(*docg4), GFP_KERNEL);
- if (!docg4)
- return -1;
-
- mtd->priv = nand;
- nand->priv = docg4;
-
- /* These must be initialized here because the docg4 is non-standard
- * and doesn't produce an id that the nand code can use to look up
- * these values (nand_scan_ident() not called).
- */
- mtd->size = DOCG4_CHIP_SIZE;
- mtd->name = "Msys_Diskonchip_G4";
- mtd->writesize = DOCG4_PAGE_SIZE;
- mtd->erasesize = DOCG4_BLOCK_SIZE;
- mtd->oobsize = DOCG4_OOB_SIZE;
-
- nand->IO_ADDR_R =
- (void __iomem *)CONFIG_SYS_NAND_BASE + DOC_IOSPACE_DATA;
- nand->IO_ADDR_W = nand->IO_ADDR_R;
- nand->chipsize = DOCG4_CHIP_SIZE;
- nand->chip_shift = DOCG4_CHIP_SHIFT;
- nand->bbt_erase_shift = DOCG4_ERASE_SHIFT;
- nand->phys_erase_shift = DOCG4_ERASE_SHIFT;
- nand->chip_delay = 20;
- nand->page_shift = DOCG4_PAGE_SHIFT;
- nand->pagemask = 0x3ffff;
- nand->badblockpos = NAND_LARGE_BADBLOCK_POS;
- nand->badblockbits = 8;
- nand->ecc.layout = &docg4_oobinfo;
- nand->ecc.mode = NAND_ECC_HW_SYNDROME;
- nand->ecc.size = DOCG4_PAGE_SIZE;
- nand->ecc.prepad = 8;
- nand->ecc.bytes = 8;
- nand->ecc.strength = DOCG4_T;
- nand->options = NAND_BUSWIDTH_16 | NAND_NO_SUBPAGE_WRITE;
- nand->controller = &nand->hwcontrol;
-
- /* methods */
- nand->cmdfunc = docg4_command;
- nand->waitfunc = docg4_wait;
- nand->select_chip = docg4_select_chip;
- nand->read_byte = docg4_read_byte;
- nand->block_markbad = docg4_block_markbad;
- nand->read_buf = docg4_read_buf;
- nand->write_buf = docg4_write_buf16;
- nand->scan_bbt = nand_default_bbt;
- nand->erase_cmd = docg4_erase_block;
- nand->ecc.read_page = docg4_read_page;
- nand->ecc.write_page = docg4_write_page;
- nand->ecc.read_page_raw = docg4_read_page_raw;
- nand->ecc.write_page_raw = docg4_write_page_raw;
- nand->ecc.read_oob = docg4_read_oob;
- nand->ecc.write_oob = docg4_write_oob;
-
- /*
- * The way the nand infrastructure code is written, a memory-based bbt
- * is not created if NAND_SKIP_BBTSCAN is set. With no memory bbt,
- * nand->block_bad() is used. So when ignoring bad blocks, we skip the
- * scan and define a dummy block_bad() which always returns 0.
- */
- if (ignore_badblocks) {
- nand->options |= NAND_SKIP_BBTSCAN;
- nand->block_bad = docg4_block_neverbad;
- }
-
- reset(CONFIG_SYS_NAND_BASE);
-
- /* check for presence of g4 chip by reading id registers */
- id1 = readw(CONFIG_SYS_NAND_BASE + DOC_CHIPID);
- id1 = readw(CONFIG_SYS_NAND_BASE + DOCG4_MYSTERY_REG);
- id2 = readw(CONFIG_SYS_NAND_BASE + DOC_CHIPID_INV);
- id2 = readw(CONFIG_SYS_NAND_BASE + DOCG4_MYSTERY_REG);
- if (id1 != DOCG4_IDREG1_VALUE || id2 != DOCG4_IDREG2_VALUE)
- return -1;
-
- /* initialize bch algorithm */
- docg4->bch = init_bch(DOCG4_M, DOCG4_T, DOCG4_PRIMITIVE_POLY);
- if (docg4->bch == NULL)
- return -1;
-
- retval = nand_scan_tail(mtd);
- if (retval)
- return -1;
-
- /*
- * Scan for bad blocks and create bbt here, then add the factory-marked
- * bad blocks to the bbt.
- */
- nand->scan_bbt(mtd);
- nand->options |= NAND_BBT_SCANNED;
- retval = read_factory_bbt(mtd);
- if (retval)
- return -1;
-
- retval = nand_register(devnum);
- if (retval)
- return -1;
-
- return 0;
-}
diff --git a/qemu/roms/u-boot/drivers/mtd/nand/docg4_spl.c b/qemu/roms/u-boot/drivers/mtd/nand/docg4_spl.c
deleted file mode 100644
index 351b75a09..000000000
--- a/qemu/roms/u-boot/drivers/mtd/nand/docg4_spl.c
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
- * SPL driver for Diskonchip G4 nand flash
- *
- * Copyright (C) 2013 Mike Dunn <mikedunn@newsguy.com>
- *
- * SPDX-License-Identifier: GPL-2.0+
- *
- * This driver basically mimics the load functionality of a typical IPL (initial
- * program loader) resident in the 2k NOR-like region of the docg4 that is
- * mapped to the reset vector. It allows the u-boot SPL to continue loading if
- * the IPL loads a fixed number of flash blocks that is insufficient to contain
- * the entire u-boot image. In this case, a concatenated spl + u-boot image is
- * written at the flash offset from which the IPL loads an image, and when the
- * IPL jumps to the SPL, the SPL resumes loading where the IPL left off. See
- * the palmtreo680 for an example.
- *
- * This driver assumes that the data was written to the flash using the device's
- * "reliable" mode, and also assumes that each 512 byte page is stored
- * redundantly in the subsequent page. This storage format is likely to be used
- * by all boards that boot from the docg4. The format compensates for the lack
- * of ecc in the IPL.
- *
- * Reliable mode reduces the capacity of a block by half, and the redundant
- * pages reduce it by half again. As a result, the normal 256k capacity of a
- * block is reduced to 64k for the purposes of the IPL/SPL.
- */
-
-#include <asm/io.h>
-#include <linux/mtd/docg4.h>
-
-/* forward declarations */
-static inline void write_nop(void __iomem *docptr);
-static int poll_status(void __iomem *docptr);
-static void write_addr(void __iomem *docptr, uint32_t docg4_addr);
-static void address_sequence(unsigned int g4_page, unsigned int g4_index,
- void __iomem *docptr);
-static int docg4_load_block_reliable(uint32_t flash_offset, void *dest_addr);
-
-int nand_spl_load_image(uint32_t offs, unsigned int size, void *dst)
-{
- void *load_addr = dst;
- uint32_t flash_offset = offs;
- const unsigned int block_count =
- (size + DOCG4_BLOCK_CAPACITY_SPL - 1)
- / DOCG4_BLOCK_CAPACITY_SPL;
- int i;
-
- for (i = 0; i < block_count; i++) {
- int ret = docg4_load_block_reliable(flash_offset, load_addr);
- if (ret)
- return ret;
- load_addr += DOCG4_BLOCK_CAPACITY_SPL;
- flash_offset += DOCG4_BLOCK_SIZE;
- }
- return 0;
-}
-
-static inline void write_nop(void __iomem *docptr)
-{
- writew(0, docptr + DOC_NOP);
-}
-
-static int poll_status(void __iomem *docptr)
-{
- /*
- * Busy-wait for the FLASHREADY bit to be set in the FLASHCONTROL
- * register. Operations known to take a long time (e.g., block erase)
- * should sleep for a while before calling this.
- */
-
- uint8_t flash_status;
-
- /* hardware quirk requires reading twice initially */
- flash_status = readb(docptr + DOC_FLASHCONTROL);
-
- do {
- flash_status = readb(docptr + DOC_FLASHCONTROL);
- } while (!(flash_status & DOC_CTRL_FLASHREADY));
-
- return 0;
-}
-
-static void write_addr(void __iomem *docptr, uint32_t docg4_addr)
-{
- /* write the four address bytes packed in docg4_addr to the device */
-
- writeb(docg4_addr & 0xff, docptr + DOC_FLASHADDRESS);
- docg4_addr >>= 8;
- writeb(docg4_addr & 0xff, docptr + DOC_FLASHADDRESS);
- docg4_addr >>= 8;
- writeb(docg4_addr & 0xff, docptr + DOC_FLASHADDRESS);
- docg4_addr >>= 8;
- writeb(docg4_addr & 0xff, docptr + DOC_FLASHADDRESS);
-}
-
-static void address_sequence(unsigned int g4_page, unsigned int g4_index,
- void __iomem *docptr)
-{
- writew(DOCG4_SEQ_PAGE_READ, docptr + DOC_FLASHSEQUENCE);
- writew(DOCG4_CMD_PAGE_READ, docptr + DOC_FLASHCOMMAND);
- write_nop(docptr);
- write_addr(docptr, ((uint32_t)g4_page << 16) | g4_index);
- write_nop(docptr);
-}
-
-static int docg4_load_block_reliable(uint32_t flash_offset, void *dest_addr)
-{
- void __iomem *docptr = (void *)CONFIG_SYS_NAND_BASE;
- unsigned int g4_page = flash_offset >> 11; /* 2k page */
- const unsigned int last_g4_page = g4_page + 0x80; /* last in block */
- int g4_index = 0;
- uint16_t flash_status;
- uint16_t *buf;
-
- /* flash_offset must be aligned to the start of a block */
- if (flash_offset & 0x3ffff)
- return -1;
-
- writew(DOC_SEQ_RESET, docptr + DOC_FLASHSEQUENCE);
- writew(DOC_CMD_RESET, docptr + DOC_FLASHCOMMAND);
- write_nop(docptr);
- write_nop(docptr);
- poll_status(docptr);
- write_nop(docptr);
- writew(0x45, docptr + DOC_FLASHSEQUENCE);
- writew(0xa3, docptr + DOC_FLASHCOMMAND);
- write_nop(docptr);
- writew(0x22, docptr + DOC_FLASHCOMMAND);
- write_nop(docptr);
-
- /* read 1st 4 oob bytes of first subpage of block */
- address_sequence(g4_page, 0x0100, docptr); /* index at oob */
- write_nop(docptr);
- flash_status = readw(docptr + DOC_FLASHCONTROL);
- flash_status = readw(docptr + DOC_FLASHCONTROL);
- if (flash_status & 0x06) /* sequence or protection errors */
- return -1;
- writew(DOCG4_CMD_READ2, docptr + DOC_FLASHCOMMAND);
- write_nop(docptr);
- write_nop(docptr);
- poll_status(docptr);
- writew(DOC_ECCCONF0_READ_MODE | 4, docptr + DOC_ECCCONF0);
- write_nop(docptr);
- write_nop(docptr);
- write_nop(docptr);
- write_nop(docptr);
- write_nop(docptr);
-
- /*
- * Here we read the first four oob bytes of the first page of the block.
- * The IPL on the palmtreo680 requires that this contain a 32 bit magic
- * number, or the load aborts. We'll ignore it.
- */
- readw(docptr + 0x103c); /* hw quirk; 1st read discarded */
- readw(docptr + 0x103c); /* lower 16 bits of magic number */
- readw(docptr + DOCG4_MYSTERY_REG); /* upper 16 bits of magic number */
- writew(0, docptr + DOC_DATAEND);
- write_nop(docptr);
- write_nop(docptr);
-
- /* load contents of block to memory */
- buf = (uint16_t *)dest_addr;
- do {
- int i;
-
- address_sequence(g4_page, g4_index, docptr);
- writew(DOCG4_CMD_READ2,
- docptr + DOC_FLASHCOMMAND);
- write_nop(docptr);
- write_nop(docptr);
- poll_status(docptr);
- writew(DOC_ECCCONF0_READ_MODE |
- DOC_ECCCONF0_ECC_ENABLE |
- DOCG4_BCH_SIZE,
- docptr + DOC_ECCCONF0);
- write_nop(docptr);
- write_nop(docptr);
- write_nop(docptr);
- write_nop(docptr);
- write_nop(docptr);
-
- /* read the 512 bytes of page data, 2 bytes at a time */
- readw(docptr + 0x103c); /* hw quirk */
- for (i = 0; i < 256; i++)
- *buf++ = readw(docptr + 0x103c);
-
- /* read oob, but discard it */
- for (i = 0; i < 7; i++)
- readw(docptr + 0x103c);
- readw(docptr + DOCG4_OOB_6_7);
- readw(docptr + DOCG4_OOB_6_7);
-
- writew(0, docptr + DOC_DATAEND);
- write_nop(docptr);
- write_nop(docptr);
-
- if (!(g4_index & 0x100)) {
- /* not redundant subpage read; check for ecc error */
- write_nop(docptr);
- flash_status = readw(docptr + DOC_ECCCONF1);
- flash_status = readw(docptr + DOC_ECCCONF1);
- if (flash_status & 0x80) { /* ecc error */
- g4_index += 0x108; /* read redundant subpage */
- buf -= 256; /* back up ram ptr */
- continue;
- } else /* no ecc error */
- g4_index += 0x210; /* skip redundant subpage */
- } else /* redundant page was just read; skip ecc error check */
- g4_index += 0x108;
-
- if (g4_index == 0x420) { /* finished with 2k page */
- g4_index = 0;
- g4_page += 2; /* odd-numbered 2k pages skipped */
- }
-
- } while (g4_page != last_g4_page); /* while still on same block */
-
- return 0;
-}
diff --git a/qemu/roms/u-boot/drivers/mtd/nand/fsl_elbc_nand.c b/qemu/roms/u-boot/drivers/mtd/nand/fsl_elbc_nand.c
deleted file mode 100644
index 2f31fc96a..000000000
--- a/qemu/roms/u-boot/drivers/mtd/nand/fsl_elbc_nand.c
+++ /dev/null
@@ -1,829 +0,0 @@
-/* Freescale Enhanced Local Bus Controller FCM NAND driver
- *
- * Copyright (c) 2006-2008 Freescale Semiconductor
- *
- * Authors: Nick Spence <nick.spence@freescale.com>,
- * Scott Wood <scottwood@freescale.com>
- *
- * SPDX-License-Identifier: GPL-2.0+
- */
-
-#include <common.h>
-#include <malloc.h>
-#include <nand.h>
-
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
-#include <linux/mtd/nand_ecc.h>
-
-#include <asm/io.h>
-#include <asm/errno.h>
-
-#ifdef VERBOSE_DEBUG
-#define DEBUG_ELBC
-#define vdbg(format, arg...) printf("DEBUG: " format, ##arg)
-#else
-#define vdbg(format, arg...) do {} while (0)
-#endif
-
-/* Can't use plain old DEBUG because the linux mtd
- * headers define it as a macro.
- */
-#ifdef DEBUG_ELBC
-#define dbg(format, arg...) printf("DEBUG: " format, ##arg)
-#else
-#define dbg(format, arg...) do {} while (0)
-#endif
-
-#define MAX_BANKS 8
-#define ERR_BYTE 0xFF /* Value returned for read bytes when read failed */
-#define FCM_TIMEOUT_MSECS 10 /* Maximum number of mSecs to wait for FCM */
-
-#define LTESR_NAND_MASK (LTESR_FCT | LTESR_PAR | LTESR_CC)
-
-struct fsl_elbc_ctrl;
-
-/* mtd information per set */
-
-struct fsl_elbc_mtd {
- struct nand_chip chip;
- struct fsl_elbc_ctrl *ctrl;
-
- struct device *dev;
- int bank; /* Chip select bank number */
- u8 __iomem *vbase; /* Chip select base virtual address */
- int page_size; /* NAND page size (0=512, 1=2048) */
- unsigned int fmr; /* FCM Flash Mode Register value */
-};
-
-/* overview of the fsl elbc controller */
-
-struct fsl_elbc_ctrl {
- struct nand_hw_control controller;
- struct fsl_elbc_mtd *chips[MAX_BANKS];
-
- /* device info */
- fsl_lbc_t *regs;
- u8 __iomem *addr; /* Address of assigned FCM buffer */
- unsigned int page; /* Last page written to / read from */
- unsigned int read_bytes; /* Number of bytes read during command */
- unsigned int column; /* Saved column from SEQIN */
- unsigned int index; /* Pointer to next byte to 'read' */
- unsigned int status; /* status read from LTESR after last op */
- unsigned int mdr; /* UPM/FCM Data Register value */
- unsigned int use_mdr; /* Non zero if the MDR is to be set */
- unsigned int oob; /* Non zero if operating on OOB data */
-};
-
-/* These map to the positions used by the FCM hardware ECC generator */
-
-/* Small Page FLASH with FMR[ECCM] = 0 */
-static struct nand_ecclayout fsl_elbc_oob_sp_eccm0 = {
- .eccbytes = 3,
- .eccpos = {6, 7, 8},
- .oobfree = { {0, 5}, {9, 7} },
-};
-
-/* Small Page FLASH with FMR[ECCM] = 1 */
-static struct nand_ecclayout fsl_elbc_oob_sp_eccm1 = {
- .eccbytes = 3,
- .eccpos = {8, 9, 10},
- .oobfree = { {0, 5}, {6, 2}, {11, 5} },
-};
-
-/* Large Page FLASH with FMR[ECCM] = 0 */
-static struct nand_ecclayout fsl_elbc_oob_lp_eccm0 = {
- .eccbytes = 12,
- .eccpos = {6, 7, 8, 22, 23, 24, 38, 39, 40, 54, 55, 56},
- .oobfree = { {1, 5}, {9, 13}, {25, 13}, {41, 13}, {57, 7} },
-};
-
-/* Large Page FLASH with FMR[ECCM] = 1 */
-static struct nand_ecclayout fsl_elbc_oob_lp_eccm1 = {
- .eccbytes = 12,
- .eccpos = {8, 9, 10, 24, 25, 26, 40, 41, 42, 56, 57, 58},
- .oobfree = { {1, 7}, {11, 13}, {27, 13}, {43, 13}, {59, 5} },
-};
-
-/*
- * fsl_elbc_oob_lp_eccm* specify that LP NAND's OOB free area starts at offset
- * 1, so we have to adjust bad block pattern. This pattern should be used for
- * x8 chips only. So far hardware does not support x16 chips anyway.
- */
-static u8 scan_ff_pattern[] = { 0xff, };
-
-static struct nand_bbt_descr largepage_memorybased = {
- .options = 0,
- .offs = 0,
- .len = 1,
- .pattern = scan_ff_pattern,
-};
-
-/*
- * ELBC may use HW ECC, so that OOB offsets, that NAND core uses for bbt,
- * interfere with ECC positions, that's why we implement our own descriptors.
- * OOB {11, 5}, works for both SP and LP chips, with ECCM = 1 and ECCM = 0.
- */
-static u8 bbt_pattern[] = {'B', 'b', 't', '0' };
-static u8 mirror_pattern[] = {'1', 't', 'b', 'B' };
-
-static struct nand_bbt_descr bbt_main_descr = {
- .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE |
- NAND_BBT_2BIT | NAND_BBT_VERSION,
- .offs = 11,
- .len = 4,
- .veroffs = 15,
- .maxblocks = 4,
- .pattern = bbt_pattern,
-};
-
-static struct nand_bbt_descr bbt_mirror_descr = {
- .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE |
- NAND_BBT_2BIT | NAND_BBT_VERSION,
- .offs = 11,
- .len = 4,
- .veroffs = 15,
- .maxblocks = 4,
- .pattern = mirror_pattern,
-};
-
-/*=================================*/
-
-/*
- * Set up the FCM hardware block and page address fields, and the fcm
- * structure addr field to point to the correct FCM buffer in memory
- */
-static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob)
-{
- struct nand_chip *chip = mtd->priv;
- struct fsl_elbc_mtd *priv = chip->priv;
- struct fsl_elbc_ctrl *ctrl = priv->ctrl;
- fsl_lbc_t *lbc = ctrl->regs;
- int buf_num;
-
- ctrl->page = page_addr;
-
- if (priv->page_size) {
- out_be32(&lbc->fbar, page_addr >> 6);
- out_be32(&lbc->fpar,
- ((page_addr << FPAR_LP_PI_SHIFT) & FPAR_LP_PI) |
- (oob ? FPAR_LP_MS : 0) | column);
- buf_num = (page_addr & 1) << 2;
- } else {
- out_be32(&lbc->fbar, page_addr >> 5);
- out_be32(&lbc->fpar,
- ((page_addr << FPAR_SP_PI_SHIFT) & FPAR_SP_PI) |
- (oob ? FPAR_SP_MS : 0) | column);
- buf_num = page_addr & 7;
- }
-
- ctrl->addr = priv->vbase + buf_num * 1024;
- ctrl->index = column;
-
- /* for OOB data point to the second half of the buffer */
- if (oob)
- ctrl->index += priv->page_size ? 2048 : 512;
-
- vdbg("set_addr: bank=%d, ctrl->addr=0x%p (0x%p), "
- "index %x, pes %d ps %d\n",
- buf_num, ctrl->addr, priv->vbase, ctrl->index,
- chip->phys_erase_shift, chip->page_shift);
-}
-
-/*
- * execute FCM command and wait for it to complete
- */
-static int fsl_elbc_run_command(struct mtd_info *mtd)
-{
- struct nand_chip *chip = mtd->priv;
- struct fsl_elbc_mtd *priv = chip->priv;
- struct fsl_elbc_ctrl *ctrl = priv->ctrl;
- fsl_lbc_t *lbc = ctrl->regs;
- long long end_tick;
- u32 ltesr;
-
- /* Setup the FMR[OP] to execute without write protection */
- out_be32(&lbc->fmr, priv->fmr | 3);
- if (ctrl->use_mdr)
- out_be32(&lbc->mdr, ctrl->mdr);
-
- vdbg("fsl_elbc_run_command: fmr=%08x fir=%08x fcr=%08x\n",
- in_be32(&lbc->fmr), in_be32(&lbc->fir), in_be32(&lbc->fcr));
- vdbg("fsl_elbc_run_command: fbar=%08x fpar=%08x "
- "fbcr=%08x bank=%d\n",
- in_be32(&lbc->fbar), in_be32(&lbc->fpar),
- in_be32(&lbc->fbcr), priv->bank);
-
- /* execute special operation */
- out_be32(&lbc->lsor, priv->bank);
-
- /* wait for FCM complete flag or timeout */
- end_tick = usec2ticks(FCM_TIMEOUT_MSECS * 1000) + get_ticks();
-
- ltesr = 0;
- while (end_tick > get_ticks()) {
- ltesr = in_be32(&lbc->ltesr);
- if (ltesr & LTESR_CC)
- break;
- }
-
- ctrl->status = ltesr & LTESR_NAND_MASK;
- out_be32(&lbc->ltesr, ctrl->status);
- out_be32(&lbc->lteatr, 0);
-
- /* store mdr value in case it was needed */
- if (ctrl->use_mdr)
- ctrl->mdr = in_be32(&lbc->mdr);
-
- ctrl->use_mdr = 0;
-
- vdbg("fsl_elbc_run_command: stat=%08x mdr=%08x fmr=%08x\n",
- ctrl->status, ctrl->mdr, in_be32(&lbc->fmr));
-
- /* returns 0 on success otherwise non-zero) */
- return ctrl->status == LTESR_CC ? 0 : -EIO;
-}
-
-static void fsl_elbc_do_read(struct nand_chip *chip, int oob)
-{
- struct fsl_elbc_mtd *priv = chip->priv;
- struct fsl_elbc_ctrl *ctrl = priv->ctrl;
- fsl_lbc_t *lbc = ctrl->regs;
-
- if (priv->page_size) {
- out_be32(&lbc->fir,
- (FIR_OP_CW0 << FIR_OP0_SHIFT) |
- (FIR_OP_CA << FIR_OP1_SHIFT) |
- (FIR_OP_PA << FIR_OP2_SHIFT) |
- (FIR_OP_CW1 << FIR_OP3_SHIFT) |
- (FIR_OP_RBW << FIR_OP4_SHIFT));
-
- out_be32(&lbc->fcr, (NAND_CMD_READ0 << FCR_CMD0_SHIFT) |
- (NAND_CMD_READSTART << FCR_CMD1_SHIFT));
- } else {
- out_be32(&lbc->fir,
- (FIR_OP_CW0 << FIR_OP0_SHIFT) |
- (FIR_OP_CA << FIR_OP1_SHIFT) |
- (FIR_OP_PA << FIR_OP2_SHIFT) |
- (FIR_OP_RBW << FIR_OP3_SHIFT));
-
- if (oob)
- out_be32(&lbc->fcr,
- NAND_CMD_READOOB << FCR_CMD0_SHIFT);
- else
- out_be32(&lbc->fcr, NAND_CMD_READ0 << FCR_CMD0_SHIFT);
- }
-}
-
-/* cmdfunc send commands to the FCM */
-static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
- int column, int page_addr)
-{
- struct nand_chip *chip = mtd->priv;
- struct fsl_elbc_mtd *priv = chip->priv;
- struct fsl_elbc_ctrl *ctrl = priv->ctrl;
- fsl_lbc_t *lbc = ctrl->regs;
-
- ctrl->use_mdr = 0;
-
- /* clear the read buffer */
- ctrl->read_bytes = 0;
- if (command != NAND_CMD_PAGEPROG)
- ctrl->index = 0;
-
- switch (command) {
- /* READ0 and READ1 read the entire buffer to use hardware ECC. */
- case NAND_CMD_READ1:
- column += 256;
-
- /* fall-through */
- case NAND_CMD_READ0:
- vdbg("fsl_elbc_cmdfunc: NAND_CMD_READ0, page_addr:"
- " 0x%x, column: 0x%x.\n", page_addr, column);
-
- out_be32(&lbc->fbcr, 0); /* read entire page to enable ECC */
- set_addr(mtd, 0, page_addr, 0);
-
- ctrl->read_bytes = mtd->writesize + mtd->oobsize;
- ctrl->index += column;
-
- fsl_elbc_do_read(chip, 0);
- fsl_elbc_run_command(mtd);
- return;
-
- /* READOOB reads only the OOB because no ECC is performed. */
- case NAND_CMD_READOOB:
- vdbg("fsl_elbc_cmdfunc: NAND_CMD_READOOB, page_addr:"
- " 0x%x, column: 0x%x.\n", page_addr, column);
-
- out_be32(&lbc->fbcr, mtd->oobsize - column);
- set_addr(mtd, column, page_addr, 1);
-
- ctrl->read_bytes = mtd->writesize + mtd->oobsize;
-
- fsl_elbc_do_read(chip, 1);
- fsl_elbc_run_command(mtd);
-
- return;
-
- /* READID must read all 5 possible bytes while CEB is active */
- case NAND_CMD_READID:
- case NAND_CMD_PARAM:
- vdbg("fsl_elbc_cmdfunc: NAND_CMD 0x%x.\n", command);
-
- out_be32(&lbc->fir, (FIR_OP_CW0 << FIR_OP0_SHIFT) |
- (FIR_OP_UA << FIR_OP1_SHIFT) |
- (FIR_OP_RBW << FIR_OP2_SHIFT));
- out_be32(&lbc->fcr, command << FCR_CMD0_SHIFT);
- /*
- * although currently it's 8 bytes for READID, we always read
- * the maximum 256 bytes(for PARAM)
- */
- out_be32(&lbc->fbcr, 256);
- ctrl->read_bytes = 256;
- ctrl->use_mdr = 1;
- ctrl->mdr = column;
- set_addr(mtd, 0, 0, 0);
- fsl_elbc_run_command(mtd);
- return;
-
- /* ERASE1 stores the block and page address */
- case NAND_CMD_ERASE1:
- vdbg("fsl_elbc_cmdfunc: NAND_CMD_ERASE1, "
- "page_addr: 0x%x.\n", page_addr);
- set_addr(mtd, 0, page_addr, 0);
- return;
-
- /* ERASE2 uses the block and page address from ERASE1 */
- case NAND_CMD_ERASE2:
- vdbg("fsl_elbc_cmdfunc: NAND_CMD_ERASE2.\n");
-
- out_be32(&lbc->fir,
- (FIR_OP_CW0 << FIR_OP0_SHIFT) |
- (FIR_OP_PA << FIR_OP1_SHIFT) |
- (FIR_OP_CM1 << FIR_OP2_SHIFT));
-
- out_be32(&lbc->fcr,
- (NAND_CMD_ERASE1 << FCR_CMD0_SHIFT) |
- (NAND_CMD_ERASE2 << FCR_CMD1_SHIFT));
-
- out_be32(&lbc->fbcr, 0);
- ctrl->read_bytes = 0;
-
- fsl_elbc_run_command(mtd);
- return;
-
- /* SEQIN sets up the addr buffer and all registers except the length */
- case NAND_CMD_SEQIN: {
- u32 fcr;
- vdbg("fsl_elbc_cmdfunc: NAND_CMD_SEQIN/PAGE_PROG, "
- "page_addr: 0x%x, column: 0x%x.\n",
- page_addr, column);
-
- ctrl->column = column;
- ctrl->oob = 0;
-
- if (priv->page_size) {
- fcr = (NAND_CMD_SEQIN << FCR_CMD0_SHIFT) |
- (NAND_CMD_PAGEPROG << FCR_CMD1_SHIFT);
-
- out_be32(&lbc->fir,
- (FIR_OP_CW0 << FIR_OP0_SHIFT) |
- (FIR_OP_CA << FIR_OP1_SHIFT) |
- (FIR_OP_PA << FIR_OP2_SHIFT) |
- (FIR_OP_WB << FIR_OP3_SHIFT) |
- (FIR_OP_CW1 << FIR_OP4_SHIFT));
- } else {
- fcr = (NAND_CMD_PAGEPROG << FCR_CMD1_SHIFT) |
- (NAND_CMD_SEQIN << FCR_CMD2_SHIFT);
-
- out_be32(&lbc->fir,
- (FIR_OP_CW0 << FIR_OP0_SHIFT) |
- (FIR_OP_CM2 << FIR_OP1_SHIFT) |
- (FIR_OP_CA << FIR_OP2_SHIFT) |
- (FIR_OP_PA << FIR_OP3_SHIFT) |
- (FIR_OP_WB << FIR_OP4_SHIFT) |
- (FIR_OP_CW1 << FIR_OP5_SHIFT));
-
- if (column >= mtd->writesize) {
- /* OOB area --> READOOB */
- column -= mtd->writesize;
- fcr |= NAND_CMD_READOOB << FCR_CMD0_SHIFT;
- ctrl->oob = 1;
- } else if (column < 256) {
- /* First 256 bytes --> READ0 */
- fcr |= NAND_CMD_READ0 << FCR_CMD0_SHIFT;
- } else {
- /* Second 256 bytes --> READ1 */
- fcr |= NAND_CMD_READ1 << FCR_CMD0_SHIFT;
- }
- }
-
- out_be32(&lbc->fcr, fcr);
- set_addr(mtd, column, page_addr, ctrl->oob);
- return;
- }
-
- /* PAGEPROG reuses all of the setup from SEQIN and adds the length */
- case NAND_CMD_PAGEPROG: {
- vdbg("fsl_elbc_cmdfunc: NAND_CMD_PAGEPROG "
- "writing %d bytes.\n", ctrl->index);
-
- /* if the write did not start at 0 or is not a full page
- * then set the exact length, otherwise use a full page
- * write so the HW generates the ECC.
- */
- if (ctrl->oob || ctrl->column != 0 ||
- ctrl->index != mtd->writesize + mtd->oobsize)
- out_be32(&lbc->fbcr, ctrl->index);
- else
- out_be32(&lbc->fbcr, 0);
-
- fsl_elbc_run_command(mtd);
-
- return;
- }
-
- /* CMD_STATUS must read the status byte while CEB is active */
- /* Note - it does not wait for the ready line */
- case NAND_CMD_STATUS:
- out_be32(&lbc->fir,
- (FIR_OP_CM0 << FIR_OP0_SHIFT) |
- (FIR_OP_RBW << FIR_OP1_SHIFT));
- out_be32(&lbc->fcr, NAND_CMD_STATUS << FCR_CMD0_SHIFT);
- out_be32(&lbc->fbcr, 1);
- set_addr(mtd, 0, 0, 0);
- ctrl->read_bytes = 1;
-
- fsl_elbc_run_command(mtd);
-
- /* The chip always seems to report that it is
- * write-protected, even when it is not.
- */
- out_8(ctrl->addr, in_8(ctrl->addr) | NAND_STATUS_WP);
- return;
-
- /* RESET without waiting for the ready line */
- case NAND_CMD_RESET:
- dbg("fsl_elbc_cmdfunc: NAND_CMD_RESET.\n");
- out_be32(&lbc->fir, FIR_OP_CM0 << FIR_OP0_SHIFT);
- out_be32(&lbc->fcr, NAND_CMD_RESET << FCR_CMD0_SHIFT);
- fsl_elbc_run_command(mtd);
- return;
-
- default:
- printf("fsl_elbc_cmdfunc: error, unsupported command 0x%x.\n",
- command);
- }
-}
-
-static void fsl_elbc_select_chip(struct mtd_info *mtd, int chip)
-{
- /* The hardware does not seem to support multiple
- * chips per bank.
- */
-}
-
-/*
- * Write buf to the FCM Controller Data Buffer
- */
-static void fsl_elbc_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
-{
- struct nand_chip *chip = mtd->priv;
- struct fsl_elbc_mtd *priv = chip->priv;
- struct fsl_elbc_ctrl *ctrl = priv->ctrl;
- unsigned int bufsize = mtd->writesize + mtd->oobsize;
-
- if (len <= 0) {
- printf("write_buf of %d bytes", len);
- ctrl->status = 0;
- return;
- }
-
- if ((unsigned int)len > bufsize - ctrl->index) {
- printf("write_buf beyond end of buffer "
- "(%d requested, %u available)\n",
- len, bufsize - ctrl->index);
- len = bufsize - ctrl->index;
- }
-
- memcpy_toio(&ctrl->addr[ctrl->index], buf, len);
- /*
- * This is workaround for the weird elbc hangs during nand write,
- * Scott Wood says: "...perhaps difference in how long it takes a
- * write to make it through the localbus compared to a write to IMMR
- * is causing problems, and sync isn't helping for some reason."
- * Reading back the last byte helps though.
- */
- in_8(&ctrl->addr[ctrl->index] + len - 1);
-
- ctrl->index += len;
-}
-
-/*
- * read a byte from either the FCM hardware buffer if it has any data left
- * otherwise issue a command to read a single byte.
- */
-static u8 fsl_elbc_read_byte(struct mtd_info *mtd)
-{
- struct nand_chip *chip = mtd->priv;
- struct fsl_elbc_mtd *priv = chip->priv;
- struct fsl_elbc_ctrl *ctrl = priv->ctrl;
-
- /* If there are still bytes in the FCM, then use the next byte. */
- if (ctrl->index < ctrl->read_bytes)
- return in_8(&ctrl->addr[ctrl->index++]);
-
- printf("read_byte beyond end of buffer\n");
- return ERR_BYTE;
-}
-
-/*
- * Read from the FCM Controller Data Buffer
- */
-static void fsl_elbc_read_buf(struct mtd_info *mtd, u8 *buf, int len)
-{
- struct nand_chip *chip = mtd->priv;
- struct fsl_elbc_mtd *priv = chip->priv;
- struct fsl_elbc_ctrl *ctrl = priv->ctrl;
- int avail;
-
- if (len < 0)
- return;
-
- avail = min((unsigned int)len, ctrl->read_bytes - ctrl->index);
- memcpy_fromio(buf, &ctrl->addr[ctrl->index], avail);
- ctrl->index += avail;
-
- if (len > avail)
- printf("read_buf beyond end of buffer "
- "(%d requested, %d available)\n",
- len, avail);
-}
-
-/*
- * Verify buffer against the FCM Controller Data Buffer
- */
-static int fsl_elbc_verify_buf(struct mtd_info *mtd,
- const u_char *buf, int len)
-{
- struct nand_chip *chip = mtd->priv;
- struct fsl_elbc_mtd *priv = chip->priv;
- struct fsl_elbc_ctrl *ctrl = priv->ctrl;
- int i;
-
- if (len < 0) {
- printf("write_buf of %d bytes", len);
- return -EINVAL;
- }
-
- if ((unsigned int)len > ctrl->read_bytes - ctrl->index) {
- printf("verify_buf beyond end of buffer "
- "(%d requested, %u available)\n",
- len, ctrl->read_bytes - ctrl->index);
-
- ctrl->index = ctrl->read_bytes;
- return -EINVAL;
- }
-
- for (i = 0; i < len; i++)
- if (in_8(&ctrl->addr[ctrl->index + i]) != buf[i])
- break;
-
- ctrl->index += len;
- return i == len && ctrl->status == LTESR_CC ? 0 : -EIO;
-}
-
-/* This function is called after Program and Erase Operations to
- * check for success or failure.
- */
-static int fsl_elbc_wait(struct mtd_info *mtd, struct nand_chip *chip)
-{
- struct fsl_elbc_mtd *priv = chip->priv;
- struct fsl_elbc_ctrl *ctrl = priv->ctrl;
- fsl_lbc_t *lbc = ctrl->regs;
-
- if (ctrl->status != LTESR_CC)
- return NAND_STATUS_FAIL;
-
- /* Use READ_STATUS command, but wait for the device to be ready */
- ctrl->use_mdr = 0;
- out_be32(&lbc->fir,
- (FIR_OP_CW0 << FIR_OP0_SHIFT) |
- (FIR_OP_RBW << FIR_OP1_SHIFT));
- out_be32(&lbc->fcr, NAND_CMD_STATUS << FCR_CMD0_SHIFT);
- out_be32(&lbc->fbcr, 1);
- set_addr(mtd, 0, 0, 0);
- ctrl->read_bytes = 1;
-
- fsl_elbc_run_command(mtd);
-
- if (ctrl->status != LTESR_CC)
- return NAND_STATUS_FAIL;
-
- /* The chip always seems to report that it is
- * write-protected, even when it is not.
- */
- out_8(ctrl->addr, in_8(ctrl->addr) | NAND_STATUS_WP);
- return fsl_elbc_read_byte(mtd);
-}
-
-static int fsl_elbc_read_page(struct mtd_info *mtd, struct nand_chip *chip,
- uint8_t *buf, int oob_required, int page)
-{
- fsl_elbc_read_buf(mtd, buf, mtd->writesize);
- fsl_elbc_read_buf(mtd, chip->oob_poi, mtd->oobsize);
-
- if (fsl_elbc_wait(mtd, chip) & NAND_STATUS_FAIL)
- mtd->ecc_stats.failed++;
-
- return 0;
-}
-
-/* ECC will be calculated automatically, and errors will be detected in
- * waitfunc.
- */
-static int fsl_elbc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
- const uint8_t *buf, int oob_required)
-{
- fsl_elbc_write_buf(mtd, buf, mtd->writesize);
- fsl_elbc_write_buf(mtd, chip->oob_poi, mtd->oobsize);
-
- return 0;
-}
-
-static struct fsl_elbc_ctrl *elbc_ctrl;
-
-static void fsl_elbc_ctrl_init(void)
-{
- elbc_ctrl = kzalloc(sizeof(*elbc_ctrl), GFP_KERNEL);
- if (!elbc_ctrl)
- return;
-
- elbc_ctrl->regs = LBC_BASE_ADDR;
-
- /* clear event registers */
- out_be32(&elbc_ctrl->regs->ltesr, LTESR_NAND_MASK);
- out_be32(&elbc_ctrl->regs->lteatr, 0);
-
- /* Enable interrupts for any detected events */
- out_be32(&elbc_ctrl->regs->lteir, LTESR_NAND_MASK);
-
- elbc_ctrl->read_bytes = 0;
- elbc_ctrl->index = 0;
- elbc_ctrl->addr = NULL;
-}
-
-static int fsl_elbc_chip_init(int devnum, u8 *addr)
-{
- struct mtd_info *mtd = &nand_info[devnum];
- struct nand_chip *nand;
- struct fsl_elbc_mtd *priv;
- uint32_t br = 0, or = 0;
- int ret;
-
- if (!elbc_ctrl) {
- fsl_elbc_ctrl_init();
- if (!elbc_ctrl)
- return -1;
- }
-
- priv = kzalloc(sizeof(*priv), GFP_KERNEL);
- if (!priv)
- return -ENOMEM;
-
- priv->ctrl = elbc_ctrl;
- priv->vbase = addr;
-
- /* Find which chip select it is connected to. It'd be nice
- * if we could pass more than one datum to the NAND driver...
- */
- for (priv->bank = 0; priv->bank < MAX_BANKS; priv->bank++) {
- phys_addr_t phys_addr = virt_to_phys(addr);
-
- br = in_be32(&elbc_ctrl->regs->bank[priv->bank].br);
- or = in_be32(&elbc_ctrl->regs->bank[priv->bank].or);
-
- if ((br & BR_V) && (br & BR_MSEL) == BR_MS_FCM &&
- (br & or & BR_BA) == BR_PHYS_ADDR(phys_addr))
- break;
- }
-
- if (priv->bank >= MAX_BANKS) {
- printf("fsl_elbc_nand: address did not match any "
- "chip selects\n");
- return -ENODEV;
- }
-
- nand = &priv->chip;
- mtd->priv = nand;
-
- elbc_ctrl->chips[priv->bank] = priv;
-
- /* fill in nand_chip structure */
- /* set up function call table */
- nand->read_byte = fsl_elbc_read_byte;
- nand->write_buf = fsl_elbc_write_buf;
- nand->read_buf = fsl_elbc_read_buf;
- nand->verify_buf = fsl_elbc_verify_buf;
- nand->select_chip = fsl_elbc_select_chip;
- nand->cmdfunc = fsl_elbc_cmdfunc;
- nand->waitfunc = fsl_elbc_wait;
-
- /* set up nand options */
- nand->bbt_td = &bbt_main_descr;
- nand->bbt_md = &bbt_mirror_descr;
-
- /* set up nand options */
- nand->options = NAND_NO_SUBPAGE_WRITE;
- nand->bbt_options = NAND_BBT_USE_FLASH;
-
- nand->controller = &elbc_ctrl->controller;
- nand->priv = priv;
-
- nand->ecc.read_page = fsl_elbc_read_page;
- nand->ecc.write_page = fsl_elbc_write_page;
-
- priv->fmr = (15 << FMR_CWTO_SHIFT) | (2 << FMR_AL_SHIFT);
-
- /* If CS Base Register selects full hardware ECC then use it */
- if ((br & BR_DECC) == BR_DECC_CHK_GEN) {
- nand->ecc.mode = NAND_ECC_HW;
-
- nand->ecc.layout = (priv->fmr & FMR_ECCM) ?
- &fsl_elbc_oob_sp_eccm1 :
- &fsl_elbc_oob_sp_eccm0;
-
- nand->ecc.size = 512;
- nand->ecc.bytes = 3;
- nand->ecc.steps = 1;
- nand->ecc.strength = 1;
- } else {
- /* otherwise fall back to software ECC */
-#if defined(CONFIG_NAND_ECC_BCH)
- nand->ecc.mode = NAND_ECC_SOFT_BCH;
-#else
- nand->ecc.mode = NAND_ECC_SOFT;
-#endif
- }
-
- ret = nand_scan_ident(mtd, 1, NULL);
- if (ret)
- return ret;
-
- /* Large-page-specific setup */
- if (mtd->writesize == 2048) {
- setbits_be32(&elbc_ctrl->regs->bank[priv->bank].or,
- OR_FCM_PGS);
- in_be32(&elbc_ctrl->regs->bank[priv->bank].or);
-
- priv->page_size = 1;
- nand->badblock_pattern = &largepage_memorybased;
-
- /*
- * Hardware expects small page has ECCM0, large page has
- * ECCM1 when booting from NAND, and we follow that even
- * when not booting from NAND.
- */
- priv->fmr |= FMR_ECCM;
-
- /* adjust ecc setup if needed */
- if ((br & BR_DECC) == BR_DECC_CHK_GEN) {
- nand->ecc.steps = 4;
- nand->ecc.layout = (priv->fmr & FMR_ECCM) ?
- &fsl_elbc_oob_lp_eccm1 :
- &fsl_elbc_oob_lp_eccm0;
- }
- } else if (mtd->writesize == 512) {
- clrbits_be32(&elbc_ctrl->regs->bank[priv->bank].or,
- OR_FCM_PGS);
- in_be32(&elbc_ctrl->regs->bank[priv->bank].or);
- } else {
- return -ENODEV;
- }
-
- ret = nand_scan_tail(mtd);
- if (ret)
- return ret;
-
- ret = nand_register(devnum);
- if (ret)
- return ret;
-
- return 0;
-}
-
-#ifndef CONFIG_SYS_NAND_BASE_LIST
-#define CONFIG_SYS_NAND_BASE_LIST { CONFIG_SYS_NAND_BASE }
-#endif
-
-static unsigned long base_address[CONFIG_SYS_MAX_NAND_DEVICE] =
- CONFIG_SYS_NAND_BASE_LIST;
-
-void board_nand_init(void)
-{
- int i;
-
- for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++)
- fsl_elbc_chip_init(i, (u8 *)base_address[i]);
-}
diff --git a/qemu/roms/u-boot/drivers/mtd/nand/fsl_elbc_spl.c b/qemu/roms/u-boot/drivers/mtd/nand/fsl_elbc_spl.c
deleted file mode 100644
index 29521359a..000000000
--- a/qemu/roms/u-boot/drivers/mtd/nand/fsl_elbc_spl.c
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * NAND boot for Freescale Enhanced Local Bus Controller, Flash Control Machine
- *
- * (C) Copyright 2006-2008
- * Stefan Roese, DENX Software Engineering, sr@denx.de.
- *
- * Copyright (c) 2008 Freescale Semiconductor, Inc.
- * Author: Scott Wood <scottwood@freescale.com>
- *
- * SPDX-License-Identifier: GPL-2.0+
- */
-
-#include <common.h>
-#include <asm/io.h>
-#include <asm/fsl_lbc.h>
-#include <nand.h>
-
-#define WINDOW_SIZE 8192
-
-static void nand_wait(void)
-{
- fsl_lbc_t *regs = LBC_BASE_ADDR;
-
- for (;;) {
- uint32_t status = in_be32(&regs->ltesr);
-
- if (status == 1)
- return;
-
- if (status & 1) {
- puts("read failed (ltesr)\n");
- for (;;);
- }
- }
-}
-
-#ifdef CONFIG_TPL_BUILD
-int nand_spl_load_image(uint32_t offs, unsigned int uboot_size, void *vdst)
-#else
-static int nand_load_image(uint32_t offs, unsigned int uboot_size, void *vdst)
-#endif
-{
- fsl_lbc_t *regs = LBC_BASE_ADDR;
- uchar *buf = (uchar *)CONFIG_SYS_NAND_BASE;
- const int large = CONFIG_SYS_NAND_OR_PRELIM & OR_FCM_PGS;
- const int block_shift = large ? 17 : 14;
- const int block_size = 1 << block_shift;
- const int page_size = large ? 2048 : 512;
- const int bad_marker = large ? page_size + 0 : page_size + 5;
- int fmr = (15 << FMR_CWTO_SHIFT) | (2 << FMR_AL_SHIFT) | 2;
- int pos = 0;
- char *dst = vdst;
-
- if (offs & (block_size - 1)) {
- puts("bad offset\n");
- for (;;);
- }
-
- if (large) {
- fmr |= FMR_ECCM;
- out_be32(&regs->fcr, (NAND_CMD_READ0 << FCR_CMD0_SHIFT) |
- (NAND_CMD_READSTART << FCR_CMD1_SHIFT));
- out_be32(&regs->fir,
- (FIR_OP_CW0 << FIR_OP0_SHIFT) |
- (FIR_OP_CA << FIR_OP1_SHIFT) |
- (FIR_OP_PA << FIR_OP2_SHIFT) |
- (FIR_OP_CW1 << FIR_OP3_SHIFT) |
- (FIR_OP_RBW << FIR_OP4_SHIFT));
- } else {
- out_be32(&regs->fcr, NAND_CMD_READ0 << FCR_CMD0_SHIFT);
- out_be32(&regs->fir,
- (FIR_OP_CW0 << FIR_OP0_SHIFT) |
- (FIR_OP_CA << FIR_OP1_SHIFT) |
- (FIR_OP_PA << FIR_OP2_SHIFT) |
- (FIR_OP_RBW << FIR_OP3_SHIFT));
- }
-
- out_be32(&regs->fbcr, 0);
- clrsetbits_be32(&regs->bank[0].br, BR_DECC, BR_DECC_CHK_GEN);
-
- while (pos < uboot_size) {
- int i = 0;
- out_be32(&regs->fbar, offs >> block_shift);
-
- do {
- int j;
- unsigned int page_offs = (offs & (block_size - 1)) << 1;
-
- out_be32(&regs->ltesr, ~0);
- out_be32(&regs->lteatr, 0);
- out_be32(&regs->fpar, page_offs);
- out_be32(&regs->fmr, fmr);
- out_be32(&regs->lsor, 0);
- nand_wait();
-
- page_offs %= WINDOW_SIZE;
-
- /*
- * If either of the first two pages are marked bad,
- * continue to the next block.
- */
- if (i++ < 2 && buf[page_offs + bad_marker] != 0xff) {
- puts("skipping\n");
- offs = (offs + block_size) & ~(block_size - 1);
- pos &= ~(block_size - 1);
- break;
- }
-
- for (j = 0; j < page_size; j++)
- dst[pos + j] = buf[page_offs + j];
-
- pos += page_size;
- offs += page_size;
- } while ((offs & (block_size - 1)) && (pos < uboot_size));
- }
-
- return 0;
-}
-
-/*
- * Defines a static function nand_load_image() here, because non-static makes
- * the code too large for certain SPLs(minimal SPL, maximum size <= 4Kbytes)
- */
-#ifndef CONFIG_TPL_BUILD
-#define nand_spl_load_image(offs, uboot_size, vdst) \
- nand_load_image(offs, uboot_size, vdst)
-#endif
-
-/*
- * The main entry for NAND booting. It's necessary that SDRAM is already
- * configured and available since this code loads the main U-Boot image
- * from NAND into SDRAM and starts it from there.
- */
-void nand_boot(void)
-{
- __attribute__((noreturn)) void (*uboot)(void);
- /*
- * Load U-Boot image from NAND into RAM
- */
- nand_spl_load_image(CONFIG_SYS_NAND_U_BOOT_OFFS,
- CONFIG_SYS_NAND_U_BOOT_SIZE,
- (void *)CONFIG_SYS_NAND_U_BOOT_DST);
-
-#ifdef CONFIG_NAND_ENV_DST
- nand_spl_load_image(CONFIG_ENV_OFFSET, CONFIG_ENV_SIZE,
- (void *)CONFIG_NAND_ENV_DST);
-
-#ifdef CONFIG_ENV_OFFSET_REDUND
- nand_spl_load_image(CONFIG_ENV_OFFSET_REDUND, CONFIG_ENV_SIZE,
- (void *)CONFIG_NAND_ENV_DST + CONFIG_ENV_SIZE);
-#endif
-#endif
-
-#ifdef CONFIG_SPL_FLUSH_IMAGE
- /*
- * Clean d-cache and invalidate i-cache, to
- * make sure that no stale data is executed.
- */
- flush_cache(CONFIG_SYS_NAND_U_BOOT_DST, CONFIG_SYS_NAND_U_BOOT_SIZE);
-#endif
-
- puts("transfering control\n");
- /*
- * Jump to U-Boot image
- */
- uboot = (void *)CONFIG_SYS_NAND_U_BOOT_START;
- (*uboot)();
-}
diff --git a/qemu/roms/u-boot/drivers/mtd/nand/fsl_ifc_nand.c b/qemu/roms/u-boot/drivers/mtd/nand/fsl_ifc_nand.c
deleted file mode 100644
index be5a16a1b..000000000
--- a/qemu/roms/u-boot/drivers/mtd/nand/fsl_ifc_nand.c
+++ /dev/null
@@ -1,1039 +0,0 @@
-/* Integrated Flash Controller NAND Machine Driver
- *
- * Copyright (c) 2012 Freescale Semiconductor, Inc
- *
- * Authors: Dipen Dudhat <Dipen.Dudhat@freescale.com>
- *
- * SPDX-License-Identifier: GPL-2.0+
- */
-
-#include <common.h>
-#include <malloc.h>
-#include <nand.h>
-
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
-#include <linux/mtd/nand_ecc.h>
-
-#include <asm/io.h>
-#include <asm/errno.h>
-#include <fsl_ifc.h>
-
-#define FSL_IFC_V1_1_0 0x01010000
-#define MAX_BANKS 4
-#define ERR_BYTE 0xFF /* Value returned for read bytes
- when read failed */
-#define IFC_TIMEOUT_MSECS 10 /* Maximum number of mSecs to wait for IFC
- NAND Machine */
-
-struct fsl_ifc_ctrl;
-
-/* mtd information per set */
-struct fsl_ifc_mtd {
- struct nand_chip chip;
- struct fsl_ifc_ctrl *ctrl;
-
- struct device *dev;
- int bank; /* Chip select bank number */
- unsigned int bufnum_mask; /* bufnum = page & bufnum_mask */
- u8 __iomem *vbase; /* Chip select base virtual address */
-};
-
-/* overview of the fsl ifc controller */
-struct fsl_ifc_ctrl {
- struct nand_hw_control controller;
- struct fsl_ifc_mtd *chips[MAX_BANKS];
-
- /* device info */
- struct fsl_ifc *regs;
- uint8_t __iomem *addr; /* Address of assigned IFC buffer */
- unsigned int cs_nand; /* On which chipsel NAND is connected */
- unsigned int page; /* Last page written to / read from */
- unsigned int read_bytes; /* Number of bytes read during command */
- unsigned int column; /* Saved column from SEQIN */
- unsigned int index; /* Pointer to next byte to 'read' */
- unsigned int status; /* status read from NEESR after last op */
- unsigned int oob; /* Non zero if operating on OOB data */
- unsigned int eccread; /* Non zero for a full-page ECC read */
-};
-
-static struct fsl_ifc_ctrl *ifc_ctrl;
-
-/* 512-byte page with 4-bit ECC, 8-bit */
-static struct nand_ecclayout oob_512_8bit_ecc4 = {
- .eccbytes = 8,
- .eccpos = {8, 9, 10, 11, 12, 13, 14, 15},
- .oobfree = { {0, 5}, {6, 2} },
-};
-
-/* 512-byte page with 4-bit ECC, 16-bit */
-static struct nand_ecclayout oob_512_16bit_ecc4 = {
- .eccbytes = 8,
- .eccpos = {8, 9, 10, 11, 12, 13, 14, 15},
- .oobfree = { {2, 6}, },
-};
-
-/* 2048-byte page size with 4-bit ECC */
-static struct nand_ecclayout oob_2048_ecc4 = {
- .eccbytes = 32,
- .eccpos = {
- 8, 9, 10, 11, 12, 13, 14, 15,
- 16, 17, 18, 19, 20, 21, 22, 23,
- 24, 25, 26, 27, 28, 29, 30, 31,
- 32, 33, 34, 35, 36, 37, 38, 39,
- },
- .oobfree = { {2, 6}, {40, 24} },
-};
-
-/* 4096-byte page size with 4-bit ECC */
-static struct nand_ecclayout oob_4096_ecc4 = {
- .eccbytes = 64,
- .eccpos = {
- 8, 9, 10, 11, 12, 13, 14, 15,
- 16, 17, 18, 19, 20, 21, 22, 23,
- 24, 25, 26, 27, 28, 29, 30, 31,
- 32, 33, 34, 35, 36, 37, 38, 39,
- 40, 41, 42, 43, 44, 45, 46, 47,
- 48, 49, 50, 51, 52, 53, 54, 55,
- 56, 57, 58, 59, 60, 61, 62, 63,
- 64, 65, 66, 67, 68, 69, 70, 71,
- },
- .oobfree = { {2, 6}, {72, 56} },
-};
-
-/* 4096-byte page size with 8-bit ECC -- requires 218-byte OOB */
-static struct nand_ecclayout oob_4096_ecc8 = {
- .eccbytes = 128,
- .eccpos = {
- 8, 9, 10, 11, 12, 13, 14, 15,
- 16, 17, 18, 19, 20, 21, 22, 23,
- 24, 25, 26, 27, 28, 29, 30, 31,
- 32, 33, 34, 35, 36, 37, 38, 39,
- 40, 41, 42, 43, 44, 45, 46, 47,
- 48, 49, 50, 51, 52, 53, 54, 55,
- 56, 57, 58, 59, 60, 61, 62, 63,
- 64, 65, 66, 67, 68, 69, 70, 71,
- 72, 73, 74, 75, 76, 77, 78, 79,
- 80, 81, 82, 83, 84, 85, 86, 87,
- 88, 89, 90, 91, 92, 93, 94, 95,
- 96, 97, 98, 99, 100, 101, 102, 103,
- 104, 105, 106, 107, 108, 109, 110, 111,
- 112, 113, 114, 115, 116, 117, 118, 119,
- 120, 121, 122, 123, 124, 125, 126, 127,
- 128, 129, 130, 131, 132, 133, 134, 135,
- },
- .oobfree = { {2, 6}, {136, 82} },
-};
-
-/* 8192-byte page size with 4-bit ECC */
-static struct nand_ecclayout oob_8192_ecc4 = {
- .eccbytes = 128,
- .eccpos = {
- 8, 9, 10, 11, 12, 13, 14, 15,
- 16, 17, 18, 19, 20, 21, 22, 23,
- 24, 25, 26, 27, 28, 29, 30, 31,
- 32, 33, 34, 35, 36, 37, 38, 39,
- 40, 41, 42, 43, 44, 45, 46, 47,
- 48, 49, 50, 51, 52, 53, 54, 55,
- 56, 57, 58, 59, 60, 61, 62, 63,
- 64, 65, 66, 67, 68, 69, 70, 71,
- 72, 73, 74, 75, 76, 77, 78, 79,
- 80, 81, 82, 83, 84, 85, 86, 87,
- 88, 89, 90, 91, 92, 93, 94, 95,
- 96, 97, 98, 99, 100, 101, 102, 103,
- 104, 105, 106, 107, 108, 109, 110, 111,
- 112, 113, 114, 115, 116, 117, 118, 119,
- 120, 121, 122, 123, 124, 125, 126, 127,
- 128, 129, 130, 131, 132, 133, 134, 135,
- },
- .oobfree = { {2, 6}, {136, 208} },
-};
-
-/* 8192-byte page size with 8-bit ECC -- requires 218-byte OOB */
-static struct nand_ecclayout oob_8192_ecc8 = {
- .eccbytes = 256,
- .eccpos = {
- 8, 9, 10, 11, 12, 13, 14, 15,
- 16, 17, 18, 19, 20, 21, 22, 23,
- 24, 25, 26, 27, 28, 29, 30, 31,
- 32, 33, 34, 35, 36, 37, 38, 39,
- 40, 41, 42, 43, 44, 45, 46, 47,
- 48, 49, 50, 51, 52, 53, 54, 55,
- 56, 57, 58, 59, 60, 61, 62, 63,
- 64, 65, 66, 67, 68, 69, 70, 71,
- 72, 73, 74, 75, 76, 77, 78, 79,
- 80, 81, 82, 83, 84, 85, 86, 87,
- 88, 89, 90, 91, 92, 93, 94, 95,
- 96, 97, 98, 99, 100, 101, 102, 103,
- 104, 105, 106, 107, 108, 109, 110, 111,
- 112, 113, 114, 115, 116, 117, 118, 119,
- 120, 121, 122, 123, 124, 125, 126, 127,
- 128, 129, 130, 131, 132, 133, 134, 135,
- 136, 137, 138, 139, 140, 141, 142, 143,
- 144, 145, 146, 147, 148, 149, 150, 151,
- 152, 153, 154, 155, 156, 157, 158, 159,
- 160, 161, 162, 163, 164, 165, 166, 167,
- 168, 169, 170, 171, 172, 173, 174, 175,
- 176, 177, 178, 179, 180, 181, 182, 183,
- 184, 185, 186, 187, 188, 189, 190, 191,
- 192, 193, 194, 195, 196, 197, 198, 199,
- 200, 201, 202, 203, 204, 205, 206, 207,
- 208, 209, 210, 211, 212, 213, 214, 215,
- 216, 217, 218, 219, 220, 221, 222, 223,
- 224, 225, 226, 227, 228, 229, 230, 231,
- 232, 233, 234, 235, 236, 237, 238, 239,
- 240, 241, 242, 243, 244, 245, 246, 247,
- 248, 249, 250, 251, 252, 253, 254, 255,
- 256, 257, 258, 259, 260, 261, 262, 263,
- },
- .oobfree = { {2, 6}, {264, 80} },
-};
-
-/*
- * Generic flash bbt descriptors
- */
-static u8 bbt_pattern[] = {'B', 'b', 't', '0' };
-static u8 mirror_pattern[] = {'1', 't', 'b', 'B' };
-
-static struct nand_bbt_descr bbt_main_descr = {
- .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE |
- NAND_BBT_2BIT | NAND_BBT_VERSION,
- .offs = 2, /* 0 on 8-bit small page */
- .len = 4,
- .veroffs = 6,
- .maxblocks = 4,
- .pattern = bbt_pattern,
-};
-
-static struct nand_bbt_descr bbt_mirror_descr = {
- .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE |
- NAND_BBT_2BIT | NAND_BBT_VERSION,
- .offs = 2, /* 0 on 8-bit small page */
- .len = 4,
- .veroffs = 6,
- .maxblocks = 4,
- .pattern = mirror_pattern,
-};
-
-/*
- * Set up the IFC hardware block and page address fields, and the ifc nand
- * structure addr field to point to the correct IFC buffer in memory
- */
-static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob)
-{
- struct nand_chip *chip = mtd->priv;
- struct fsl_ifc_mtd *priv = chip->priv;
- struct fsl_ifc_ctrl *ctrl = priv->ctrl;
- struct fsl_ifc *ifc = ctrl->regs;
- int buf_num;
-
- ctrl->page = page_addr;
-
- /* Program ROW0/COL0 */
- ifc_out32(&ifc->ifc_nand.row0, page_addr);
- ifc_out32(&ifc->ifc_nand.col0, (oob ? IFC_NAND_COL_MS : 0) | column);
-
- buf_num = page_addr & priv->bufnum_mask;
-
- ctrl->addr = priv->vbase + buf_num * (mtd->writesize * 2);
- ctrl->index = column;
-
- /* for OOB data point to the second half of the buffer */
- if (oob)
- ctrl->index += mtd->writesize;
-}
-
-static int is_blank(struct mtd_info *mtd, struct fsl_ifc_ctrl *ctrl,
- unsigned int bufnum)
-{
- struct nand_chip *chip = mtd->priv;
- struct fsl_ifc_mtd *priv = chip->priv;
- u8 __iomem *addr = priv->vbase + bufnum * (mtd->writesize * 2);
- u32 __iomem *main = (u32 *)addr;
- u8 __iomem *oob = addr + mtd->writesize;
- int i;
-
- for (i = 0; i < mtd->writesize / 4; i++) {
- if (__raw_readl(&main[i]) != 0xffffffff)
- return 0;
- }
-
- for (i = 0; i < chip->ecc.layout->eccbytes; i++) {
- int pos = chip->ecc.layout->eccpos[i];
-
- if (__raw_readb(&oob[pos]) != 0xff)
- return 0;
- }
-
- return 1;
-}
-
-/* returns nonzero if entire page is blank */
-static int check_read_ecc(struct mtd_info *mtd, struct fsl_ifc_ctrl *ctrl,
- u32 *eccstat, unsigned int bufnum)
-{
- u32 reg = eccstat[bufnum / 4];
- int errors;
-
- errors = (reg >> ((3 - bufnum % 4) * 8)) & 15;
-
- return errors;
-}
-
-/*
- * execute IFC NAND command and wait for it to complete
- */
-static int fsl_ifc_run_command(struct mtd_info *mtd)
-{
- struct nand_chip *chip = mtd->priv;
- struct fsl_ifc_mtd *priv = chip->priv;
- struct fsl_ifc_ctrl *ctrl = priv->ctrl;
- struct fsl_ifc *ifc = ctrl->regs;
- long long end_tick;
- u32 eccstat[4];
- int i;
-
- /* set the chip select for NAND Transaction */
- ifc_out32(&ifc->ifc_nand.nand_csel, ifc_ctrl->cs_nand);
-
- /* start read/write seq */
- ifc_out32(&ifc->ifc_nand.nandseq_strt,
- IFC_NAND_SEQ_STRT_FIR_STRT);
-
- /* wait for NAND Machine complete flag or timeout */
- end_tick = usec2ticks(IFC_TIMEOUT_MSECS * 1000) + get_ticks();
-
- while (end_tick > get_ticks()) {
- ctrl->status = ifc_in32(&ifc->ifc_nand.nand_evter_stat);
-
- if (ctrl->status & IFC_NAND_EVTER_STAT_OPC)
- break;
- }
-
- ifc_out32(&ifc->ifc_nand.nand_evter_stat, ctrl->status);
-
- if (ctrl->status & IFC_NAND_EVTER_STAT_FTOER)
- printf("%s: Flash Time Out Error\n", __func__);
- if (ctrl->status & IFC_NAND_EVTER_STAT_WPER)
- printf("%s: Write Protect Error\n", __func__);
-
- if (ctrl->eccread) {
- int errors;
- int bufnum = ctrl->page & priv->bufnum_mask;
- int sector = bufnum * chip->ecc.steps;
- int sector_end = sector + chip->ecc.steps - 1;
-
- for (i = sector / 4; i <= sector_end / 4; i++)
- eccstat[i] = ifc_in32(&ifc->ifc_nand.nand_eccstat[i]);
-
- for (i = sector; i <= sector_end; i++) {
- errors = check_read_ecc(mtd, ctrl, eccstat, i);
-
- if (errors == 15) {
- /*
- * Uncorrectable error.
- * OK only if the whole page is blank.
- *
- * We disable ECCER reporting due to erratum
- * IFC-A002770 -- so report it now if we
- * see an uncorrectable error in ECCSTAT.
- */
- if (!is_blank(mtd, ctrl, bufnum))
- ctrl->status |=
- IFC_NAND_EVTER_STAT_ECCER;
- break;
- }
-
- mtd->ecc_stats.corrected += errors;
- }
-
- ctrl->eccread = 0;
- }
-
- /* returns 0 on success otherwise non-zero) */
- return ctrl->status == IFC_NAND_EVTER_STAT_OPC ? 0 : -EIO;
-}
-
-static void fsl_ifc_do_read(struct nand_chip *chip,
- int oob,
- struct mtd_info *mtd)
-{
- struct fsl_ifc_mtd *priv = chip->priv;
- struct fsl_ifc_ctrl *ctrl = priv->ctrl;
- struct fsl_ifc *ifc = ctrl->regs;
-
- /* Program FIR/IFC_NAND_FCR0 for Small/Large page */
- if (mtd->writesize > 512) {
- ifc_out32(&ifc->ifc_nand.nand_fir0,
- (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
- (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP1_SHIFT) |
- (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP2_SHIFT) |
- (IFC_FIR_OP_CMD1 << IFC_NAND_FIR0_OP3_SHIFT) |
- (IFC_FIR_OP_RBCD << IFC_NAND_FIR0_OP4_SHIFT));
- ifc_out32(&ifc->ifc_nand.nand_fir1, 0x0);
-
- ifc_out32(&ifc->ifc_nand.nand_fcr0,
- (NAND_CMD_READ0 << IFC_NAND_FCR0_CMD0_SHIFT) |
- (NAND_CMD_READSTART << IFC_NAND_FCR0_CMD1_SHIFT));
- } else {
- ifc_out32(&ifc->ifc_nand.nand_fir0,
- (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
- (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP1_SHIFT) |
- (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP2_SHIFT) |
- (IFC_FIR_OP_RBCD << IFC_NAND_FIR0_OP3_SHIFT));
-
- if (oob)
- ifc_out32(&ifc->ifc_nand.nand_fcr0,
- NAND_CMD_READOOB << IFC_NAND_FCR0_CMD0_SHIFT);
- else
- ifc_out32(&ifc->ifc_nand.nand_fcr0,
- NAND_CMD_READ0 << IFC_NAND_FCR0_CMD0_SHIFT);
- }
-}
-
-/* cmdfunc send commands to the IFC NAND Machine */
-static void fsl_ifc_cmdfunc(struct mtd_info *mtd, unsigned int command,
- int column, int page_addr)
-{
- struct nand_chip *chip = mtd->priv;
- struct fsl_ifc_mtd *priv = chip->priv;
- struct fsl_ifc_ctrl *ctrl = priv->ctrl;
- struct fsl_ifc *ifc = ctrl->regs;
-
- /* clear the read buffer */
- ctrl->read_bytes = 0;
- if (command != NAND_CMD_PAGEPROG)
- ctrl->index = 0;
-
- switch (command) {
- /* READ0 read the entire buffer to use hardware ECC. */
- case NAND_CMD_READ0: {
- ifc_out32(&ifc->ifc_nand.nand_fbcr, 0);
- set_addr(mtd, 0, page_addr, 0);
-
- ctrl->read_bytes = mtd->writesize + mtd->oobsize;
- ctrl->index += column;
-
- if (chip->ecc.mode == NAND_ECC_HW)
- ctrl->eccread = 1;
-
- fsl_ifc_do_read(chip, 0, mtd);
- fsl_ifc_run_command(mtd);
- return;
- }
-
- /* READOOB reads only the OOB because no ECC is performed. */
- case NAND_CMD_READOOB:
- ifc_out32(&ifc->ifc_nand.nand_fbcr, mtd->oobsize - column);
- set_addr(mtd, column, page_addr, 1);
-
- ctrl->read_bytes = mtd->writesize + mtd->oobsize;
-
- fsl_ifc_do_read(chip, 1, mtd);
- fsl_ifc_run_command(mtd);
-
- return;
-
- /* READID must read all possible bytes while CEB is active */
- case NAND_CMD_READID:
- case NAND_CMD_PARAM: {
- int timing = IFC_FIR_OP_RB;
- if (command == NAND_CMD_PARAM)
- timing = IFC_FIR_OP_RBCD;
-
- ifc_out32(&ifc->ifc_nand.nand_fir0,
- (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
- (IFC_FIR_OP_UA << IFC_NAND_FIR0_OP1_SHIFT) |
- (timing << IFC_NAND_FIR0_OP2_SHIFT));
- ifc_out32(&ifc->ifc_nand.nand_fcr0,
- command << IFC_NAND_FCR0_CMD0_SHIFT);
- ifc_out32(&ifc->ifc_nand.row3, column);
-
- /*
- * although currently it's 8 bytes for READID, we always read
- * the maximum 256 bytes(for PARAM)
- */
- ifc_out32(&ifc->ifc_nand.nand_fbcr, 256);
- ctrl->read_bytes = 256;
-
- set_addr(mtd, 0, 0, 0);
- fsl_ifc_run_command(mtd);
- return;
- }
-
- /* ERASE1 stores the block and page address */
- case NAND_CMD_ERASE1:
- set_addr(mtd, 0, page_addr, 0);
- return;
-
- /* ERASE2 uses the block and page address from ERASE1 */
- case NAND_CMD_ERASE2:
- ifc_out32(&ifc->ifc_nand.nand_fir0,
- (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
- (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP1_SHIFT) |
- (IFC_FIR_OP_CMD1 << IFC_NAND_FIR0_OP2_SHIFT));
-
- ifc_out32(&ifc->ifc_nand.nand_fcr0,
- (NAND_CMD_ERASE1 << IFC_NAND_FCR0_CMD0_SHIFT) |
- (NAND_CMD_ERASE2 << IFC_NAND_FCR0_CMD1_SHIFT));
-
- ifc_out32(&ifc->ifc_nand.nand_fbcr, 0);
- ctrl->read_bytes = 0;
- fsl_ifc_run_command(mtd);
- return;
-
- /* SEQIN sets up the addr buffer and all registers except the length */
- case NAND_CMD_SEQIN: {
- u32 nand_fcr0;
- ctrl->column = column;
- ctrl->oob = 0;
-
- if (mtd->writesize > 512) {
- nand_fcr0 =
- (NAND_CMD_SEQIN << IFC_NAND_FCR0_CMD0_SHIFT) |
- (NAND_CMD_STATUS << IFC_NAND_FCR0_CMD1_SHIFT) |
- (NAND_CMD_PAGEPROG << IFC_NAND_FCR0_CMD2_SHIFT);
-
- ifc_out32(&ifc->ifc_nand.nand_fir0,
- (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
- (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP1_SHIFT) |
- (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP2_SHIFT) |
- (IFC_FIR_OP_WBCD <<
- IFC_NAND_FIR0_OP3_SHIFT) |
- (IFC_FIR_OP_CMD2 << IFC_NAND_FIR0_OP4_SHIFT));
- ifc_out32(&ifc->ifc_nand.nand_fir1,
- (IFC_FIR_OP_CW1 << IFC_NAND_FIR1_OP5_SHIFT) |
- (IFC_FIR_OP_RDSTAT <<
- IFC_NAND_FIR1_OP6_SHIFT) |
- (IFC_FIR_OP_NOP << IFC_NAND_FIR1_OP7_SHIFT));
- } else {
- nand_fcr0 = ((NAND_CMD_PAGEPROG <<
- IFC_NAND_FCR0_CMD1_SHIFT) |
- (NAND_CMD_SEQIN <<
- IFC_NAND_FCR0_CMD2_SHIFT) |
- (NAND_CMD_STATUS <<
- IFC_NAND_FCR0_CMD3_SHIFT));
-
- ifc_out32(&ifc->ifc_nand.nand_fir0,
- (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
- (IFC_FIR_OP_CMD2 << IFC_NAND_FIR0_OP1_SHIFT) |
- (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP2_SHIFT) |
- (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP3_SHIFT) |
- (IFC_FIR_OP_WBCD << IFC_NAND_FIR0_OP4_SHIFT));
- ifc_out32(&ifc->ifc_nand.nand_fir1,
- (IFC_FIR_OP_CMD1 << IFC_NAND_FIR1_OP5_SHIFT) |
- (IFC_FIR_OP_CW3 << IFC_NAND_FIR1_OP6_SHIFT) |
- (IFC_FIR_OP_RDSTAT <<
- IFC_NAND_FIR1_OP7_SHIFT) |
- (IFC_FIR_OP_NOP << IFC_NAND_FIR1_OP8_SHIFT));
-
- if (column >= mtd->writesize)
- nand_fcr0 |=
- NAND_CMD_READOOB << IFC_NAND_FCR0_CMD0_SHIFT;
- else
- nand_fcr0 |=
- NAND_CMD_READ0 << IFC_NAND_FCR0_CMD0_SHIFT;
- }
-
- if (column >= mtd->writesize) {
- /* OOB area --> READOOB */
- column -= mtd->writesize;
- ctrl->oob = 1;
- }
- ifc_out32(&ifc->ifc_nand.nand_fcr0, nand_fcr0);
- set_addr(mtd, column, page_addr, ctrl->oob);
- return;
- }
-
- /* PAGEPROG reuses all of the setup from SEQIN and adds the length */
- case NAND_CMD_PAGEPROG:
- if (ctrl->oob)
- ifc_out32(&ifc->ifc_nand.nand_fbcr,
- ctrl->index - ctrl->column);
- else
- ifc_out32(&ifc->ifc_nand.nand_fbcr, 0);
-
- fsl_ifc_run_command(mtd);
- return;
-
- case NAND_CMD_STATUS:
- ifc_out32(&ifc->ifc_nand.nand_fir0,
- (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
- (IFC_FIR_OP_RB << IFC_NAND_FIR0_OP1_SHIFT));
- ifc_out32(&ifc->ifc_nand.nand_fcr0,
- NAND_CMD_STATUS << IFC_NAND_FCR0_CMD0_SHIFT);
- ifc_out32(&ifc->ifc_nand.nand_fbcr, 1);
- set_addr(mtd, 0, 0, 0);
- ctrl->read_bytes = 1;
-
- fsl_ifc_run_command(mtd);
-
- /* Chip sometimes reporting write protect even when it's not */
- out_8(ctrl->addr, in_8(ctrl->addr) | NAND_STATUS_WP);
- return;
-
- case NAND_CMD_RESET:
- ifc_out32(&ifc->ifc_nand.nand_fir0,
- IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT);
- ifc_out32(&ifc->ifc_nand.nand_fcr0,
- NAND_CMD_RESET << IFC_NAND_FCR0_CMD0_SHIFT);
- fsl_ifc_run_command(mtd);
- return;
-
- default:
- printf("%s: error, unsupported command 0x%x.\n",
- __func__, command);
- }
-}
-
-/*
- * Write buf to the IFC NAND Controller Data Buffer
- */
-static void fsl_ifc_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
-{
- struct nand_chip *chip = mtd->priv;
- struct fsl_ifc_mtd *priv = chip->priv;
- struct fsl_ifc_ctrl *ctrl = priv->ctrl;
- unsigned int bufsize = mtd->writesize + mtd->oobsize;
-
- if (len <= 0) {
- printf("%s of %d bytes", __func__, len);
- ctrl->status = 0;
- return;
- }
-
- if ((unsigned int)len > bufsize - ctrl->index) {
- printf("%s beyond end of buffer "
- "(%d requested, %u available)\n",
- __func__, len, bufsize - ctrl->index);
- len = bufsize - ctrl->index;
- }
-
- memcpy_toio(&ctrl->addr[ctrl->index], buf, len);
- ctrl->index += len;
-}
-
-/*
- * read a byte from either the IFC hardware buffer if it has any data left
- * otherwise issue a command to read a single byte.
- */
-static u8 fsl_ifc_read_byte(struct mtd_info *mtd)
-{
- struct nand_chip *chip = mtd->priv;
- struct fsl_ifc_mtd *priv = chip->priv;
- struct fsl_ifc_ctrl *ctrl = priv->ctrl;
-
- /* If there are still bytes in the IFC buffer, then use the
- * next byte. */
- if (ctrl->index < ctrl->read_bytes)
- return in_8(&ctrl->addr[ctrl->index++]);
-
- printf("%s beyond end of buffer\n", __func__);
- return ERR_BYTE;
-}
-
-/*
- * Read two bytes from the IFC hardware buffer
- * read function for 16-bit buswith
- */
-static uint8_t fsl_ifc_read_byte16(struct mtd_info *mtd)
-{
- struct nand_chip *chip = mtd->priv;
- struct fsl_ifc_mtd *priv = chip->priv;
- struct fsl_ifc_ctrl *ctrl = priv->ctrl;
- uint16_t data;
-
- /*
- * If there are still bytes in the IFC buffer, then use the
- * next byte.
- */
- if (ctrl->index < ctrl->read_bytes) {
- data = ifc_in16((uint16_t *)&ctrl->
- addr[ctrl->index]);
- ctrl->index += 2;
- return (uint8_t)data;
- }
-
- printf("%s beyond end of buffer\n", __func__);
- return ERR_BYTE;
-}
-
-/*
- * Read from the IFC Controller Data Buffer
- */
-static void fsl_ifc_read_buf(struct mtd_info *mtd, u8 *buf, int len)
-{
- struct nand_chip *chip = mtd->priv;
- struct fsl_ifc_mtd *priv = chip->priv;
- struct fsl_ifc_ctrl *ctrl = priv->ctrl;
- int avail;
-
- if (len < 0)
- return;
-
- avail = min((unsigned int)len, ctrl->read_bytes - ctrl->index);
- memcpy_fromio(buf, &ctrl->addr[ctrl->index], avail);
- ctrl->index += avail;
-
- if (len > avail)
- printf("%s beyond end of buffer "
- "(%d requested, %d available)\n",
- __func__, len, avail);
-}
-
-/*
- * Verify buffer against the IFC Controller Data Buffer
- */
-static int fsl_ifc_verify_buf(struct mtd_info *mtd,
- const u_char *buf, int len)
-{
- struct nand_chip *chip = mtd->priv;
- struct fsl_ifc_mtd *priv = chip->priv;
- struct fsl_ifc_ctrl *ctrl = priv->ctrl;
- int i;
-
- if (len < 0) {
- printf("%s of %d bytes", __func__, len);
- return -EINVAL;
- }
-
- if ((unsigned int)len > ctrl->read_bytes - ctrl->index) {
- printf("%s beyond end of buffer "
- "(%d requested, %u available)\n",
- __func__, len, ctrl->read_bytes - ctrl->index);
-
- ctrl->index = ctrl->read_bytes;
- return -EINVAL;
- }
-
- for (i = 0; i < len; i++)
- if (in_8(&ctrl->addr[ctrl->index + i]) != buf[i])
- break;
-
- ctrl->index += len;
- return i == len && ctrl->status == IFC_NAND_EVTER_STAT_OPC ? 0 : -EIO;
-}
-
-/* This function is called after Program and Erase Operations to
- * check for success or failure.
- */
-static int fsl_ifc_wait(struct mtd_info *mtd, struct nand_chip *chip)
-{
- struct fsl_ifc_mtd *priv = chip->priv;
- struct fsl_ifc_ctrl *ctrl = priv->ctrl;
- struct fsl_ifc *ifc = ctrl->regs;
- u32 nand_fsr;
-
- if (ctrl->status != IFC_NAND_EVTER_STAT_OPC)
- return NAND_STATUS_FAIL;
-
- /* Use READ_STATUS command, but wait for the device to be ready */
- ifc_out32(&ifc->ifc_nand.nand_fir0,
- (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
- (IFC_FIR_OP_RDSTAT << IFC_NAND_FIR0_OP1_SHIFT));
- ifc_out32(&ifc->ifc_nand.nand_fcr0, NAND_CMD_STATUS <<
- IFC_NAND_FCR0_CMD0_SHIFT);
- ifc_out32(&ifc->ifc_nand.nand_fbcr, 1);
- set_addr(mtd, 0, 0, 0);
- ctrl->read_bytes = 1;
-
- fsl_ifc_run_command(mtd);
-
- if (ctrl->status != IFC_NAND_EVTER_STAT_OPC)
- return NAND_STATUS_FAIL;
-
- nand_fsr = ifc_in32(&ifc->ifc_nand.nand_fsr);
-
- /* Chip sometimes reporting write protect even when it's not */
- nand_fsr = nand_fsr | NAND_STATUS_WP;
- return nand_fsr;
-}
-
-static int fsl_ifc_read_page(struct mtd_info *mtd, struct nand_chip *chip,
- uint8_t *buf, int oob_required, int page)
-{
- struct fsl_ifc_mtd *priv = chip->priv;
- struct fsl_ifc_ctrl *ctrl = priv->ctrl;
-
- fsl_ifc_read_buf(mtd, buf, mtd->writesize);
- fsl_ifc_read_buf(mtd, chip->oob_poi, mtd->oobsize);
-
- if (ctrl->status != IFC_NAND_EVTER_STAT_OPC)
- mtd->ecc_stats.failed++;
-
- return 0;
-}
-
-/* ECC will be calculated automatically, and errors will be detected in
- * waitfunc.
- */
-static int fsl_ifc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
- const uint8_t *buf, int oob_required)
-{
- fsl_ifc_write_buf(mtd, buf, mtd->writesize);
- fsl_ifc_write_buf(mtd, chip->oob_poi, mtd->oobsize);
-
- return 0;
-}
-
-static void fsl_ifc_ctrl_init(void)
-{
- ifc_ctrl = kzalloc(sizeof(*ifc_ctrl), GFP_KERNEL);
- if (!ifc_ctrl)
- return;
-
- ifc_ctrl->regs = IFC_BASE_ADDR;
-
- /* clear event registers */
- ifc_out32(&ifc_ctrl->regs->ifc_nand.nand_evter_stat, ~0U);
- ifc_out32(&ifc_ctrl->regs->ifc_nand.pgrdcmpl_evt_stat, ~0U);
-
- /* Enable error and event for any detected errors */
- ifc_out32(&ifc_ctrl->regs->ifc_nand.nand_evter_en,
- IFC_NAND_EVTER_EN_OPC_EN |
- IFC_NAND_EVTER_EN_PGRDCMPL_EN |
- IFC_NAND_EVTER_EN_FTOER_EN |
- IFC_NAND_EVTER_EN_WPER_EN);
-
- ifc_out32(&ifc_ctrl->regs->ifc_nand.ncfgr, 0x0);
-}
-
-static void fsl_ifc_select_chip(struct mtd_info *mtd, int chip)
-{
-}
-
-static void fsl_ifc_sram_init(void)
-{
- struct fsl_ifc *ifc = ifc_ctrl->regs;
- uint32_t cs = 0, csor = 0, csor_8k = 0, csor_ext = 0;
- long long end_tick;
-
- cs = ifc_ctrl->cs_nand >> IFC_NAND_CSEL_SHIFT;
-
- /* Save CSOR and CSOR_ext */
- csor = ifc_in32(&ifc_ctrl->regs->csor_cs[cs].csor);
- csor_ext = ifc_in32(&ifc_ctrl->regs->csor_cs[cs].csor_ext);
-
- /* chage PageSize 8K and SpareSize 1K*/
- csor_8k = (csor & ~(CSOR_NAND_PGS_MASK)) | 0x0018C000;
- ifc_out32(&ifc_ctrl->regs->csor_cs[cs].csor, csor_8k);
- ifc_out32(&ifc_ctrl->regs->csor_cs[cs].csor_ext, 0x0000400);
-
- /* READID */
- ifc_out32(&ifc->ifc_nand.nand_fir0,
- (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
- (IFC_FIR_OP_UA << IFC_NAND_FIR0_OP1_SHIFT) |
- (IFC_FIR_OP_RB << IFC_NAND_FIR0_OP2_SHIFT));
- ifc_out32(&ifc->ifc_nand.nand_fcr0,
- NAND_CMD_READID << IFC_NAND_FCR0_CMD0_SHIFT);
- ifc_out32(&ifc->ifc_nand.row3, 0x0);
-
- ifc_out32(&ifc->ifc_nand.nand_fbcr, 0x0);
-
- /* Program ROW0/COL0 */
- ifc_out32(&ifc->ifc_nand.row0, 0x0);
- ifc_out32(&ifc->ifc_nand.col0, 0x0);
-
- /* set the chip select for NAND Transaction */
- ifc_out32(&ifc->ifc_nand.nand_csel, ifc_ctrl->cs_nand);
-
- /* start read seq */
- ifc_out32(&ifc->ifc_nand.nandseq_strt, IFC_NAND_SEQ_STRT_FIR_STRT);
-
- /* wait for NAND Machine complete flag or timeout */
- end_tick = usec2ticks(IFC_TIMEOUT_MSECS * 1000) + get_ticks();
-
- while (end_tick > get_ticks()) {
- ifc_ctrl->status = ifc_in32(&ifc->ifc_nand.nand_evter_stat);
-
- if (ifc_ctrl->status & IFC_NAND_EVTER_STAT_OPC)
- break;
- }
-
- ifc_out32(&ifc->ifc_nand.nand_evter_stat, ifc_ctrl->status);
-
- /* Restore CSOR and CSOR_ext */
- ifc_out32(&ifc_ctrl->regs->csor_cs[cs].csor, csor);
- ifc_out32(&ifc_ctrl->regs->csor_cs[cs].csor_ext, csor_ext);
-}
-
-static int fsl_ifc_chip_init(int devnum, u8 *addr)
-{
- struct mtd_info *mtd = &nand_info[devnum];
- struct nand_chip *nand;
- struct fsl_ifc_mtd *priv;
- struct nand_ecclayout *layout;
- uint32_t cspr = 0, csor = 0, ver = 0;
- int ret;
-
- if (!ifc_ctrl) {
- fsl_ifc_ctrl_init();
- if (!ifc_ctrl)
- return -1;
- }
-
- priv = kzalloc(sizeof(*priv), GFP_KERNEL);
- if (!priv)
- return -ENOMEM;
-
- priv->ctrl = ifc_ctrl;
- priv->vbase = addr;
-
- /* Find which chip select it is connected to.
- */
- for (priv->bank = 0; priv->bank < MAX_BANKS; priv->bank++) {
- phys_addr_t phys_addr = virt_to_phys(addr);
-
- cspr = ifc_in32(&ifc_ctrl->regs->cspr_cs[priv->bank].cspr);
- csor = ifc_in32(&ifc_ctrl->regs->csor_cs[priv->bank].csor);
-
- if ((cspr & CSPR_V) && (cspr & CSPR_MSEL) == CSPR_MSEL_NAND &&
- (cspr & CSPR_BA) == CSPR_PHYS_ADDR(phys_addr)) {
- ifc_ctrl->cs_nand = priv->bank << IFC_NAND_CSEL_SHIFT;
- break;
- }
- }
-
- if (priv->bank >= MAX_BANKS) {
- printf("%s: address did not match any "
- "chip selects\n", __func__);
- kfree(priv);
- return -ENODEV;
- }
-
- nand = &priv->chip;
- mtd->priv = nand;
-
- ifc_ctrl->chips[priv->bank] = priv;
-
- /* fill in nand_chip structure */
- /* set up function call table */
-
- nand->write_buf = fsl_ifc_write_buf;
- nand->read_buf = fsl_ifc_read_buf;
- nand->verify_buf = fsl_ifc_verify_buf;
- nand->select_chip = fsl_ifc_select_chip;
- nand->cmdfunc = fsl_ifc_cmdfunc;
- nand->waitfunc = fsl_ifc_wait;
-
- /* set up nand options */
- nand->bbt_td = &bbt_main_descr;
- nand->bbt_md = &bbt_mirror_descr;
-
- /* set up nand options */
- nand->options = NAND_NO_SUBPAGE_WRITE;
- nand->bbt_options = NAND_BBT_USE_FLASH;
-
- if (cspr & CSPR_PORT_SIZE_16) {
- nand->read_byte = fsl_ifc_read_byte16;
- nand->options |= NAND_BUSWIDTH_16;
- } else {
- nand->read_byte = fsl_ifc_read_byte;
- }
-
- nand->controller = &ifc_ctrl->controller;
- nand->priv = priv;
-
- nand->ecc.read_page = fsl_ifc_read_page;
- nand->ecc.write_page = fsl_ifc_write_page;
-
- /* Hardware generates ECC per 512 Bytes */
- nand->ecc.size = 512;
- nand->ecc.bytes = 8;
-
- switch (csor & CSOR_NAND_PGS_MASK) {
- case CSOR_NAND_PGS_512:
- if (nand->options & NAND_BUSWIDTH_16) {
- layout = &oob_512_16bit_ecc4;
- } else {
- layout = &oob_512_8bit_ecc4;
-
- /* Avoid conflict with bad block marker */
- bbt_main_descr.offs = 0;
- bbt_mirror_descr.offs = 0;
- }
-
- nand->ecc.strength = 4;
- priv->bufnum_mask = 15;
- break;
-
- case CSOR_NAND_PGS_2K:
- layout = &oob_2048_ecc4;
- nand->ecc.strength = 4;
- priv->bufnum_mask = 3;
- break;
-
- case CSOR_NAND_PGS_4K:
- if ((csor & CSOR_NAND_ECC_MODE_MASK) ==
- CSOR_NAND_ECC_MODE_4) {
- layout = &oob_4096_ecc4;
- nand->ecc.strength = 4;
- } else {
- layout = &oob_4096_ecc8;
- nand->ecc.strength = 8;
- nand->ecc.bytes = 16;
- }
-
- priv->bufnum_mask = 1;
- break;
-
- case CSOR_NAND_PGS_8K:
- if ((csor & CSOR_NAND_ECC_MODE_MASK) ==
- CSOR_NAND_ECC_MODE_4) {
- layout = &oob_8192_ecc4;
- nand->ecc.strength = 4;
- } else {
- layout = &oob_8192_ecc8;
- nand->ecc.strength = 8;
- nand->ecc.bytes = 16;
- }
-
- priv->bufnum_mask = 0;
- break;
-
-
- default:
- printf("ifc nand: bad csor %#x: bad page size\n", csor);
- return -ENODEV;
- }
-
- /* Must also set CSOR_NAND_ECC_ENC_EN if DEC_EN set */
- if (csor & CSOR_NAND_ECC_DEC_EN) {
- nand->ecc.mode = NAND_ECC_HW;
- nand->ecc.layout = layout;
- } else {
- nand->ecc.mode = NAND_ECC_SOFT;
- }
-
- ver = ifc_in32(&ifc_ctrl->regs->ifc_rev);
- if (ver == FSL_IFC_V1_1_0)
- fsl_ifc_sram_init();
-
- ret = nand_scan_ident(mtd, 1, NULL);
- if (ret)
- return ret;
-
- ret = nand_scan_tail(mtd);
- if (ret)
- return ret;
-
- ret = nand_register(devnum);
- if (ret)
- return ret;
- return 0;
-}
-
-#ifndef CONFIG_SYS_NAND_BASE_LIST
-#define CONFIG_SYS_NAND_BASE_LIST { CONFIG_SYS_NAND_BASE }
-#endif
-
-static unsigned long base_address[CONFIG_SYS_MAX_NAND_DEVICE] =
- CONFIG_SYS_NAND_BASE_LIST;
-
-void board_nand_init(void)
-{
- int i;
-
- for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++)
- fsl_ifc_chip_init(i, (u8 *)base_address[i]);
-}
diff --git a/qemu/roms/u-boot/drivers/mtd/nand/fsl_ifc_spl.c b/qemu/roms/u-boot/drivers/mtd/nand/fsl_ifc_spl.c
deleted file mode 100644
index 510077282..000000000
--- a/qemu/roms/u-boot/drivers/mtd/nand/fsl_ifc_spl.c
+++ /dev/null
@@ -1,252 +0,0 @@
-/*
- * NAND boot for Freescale Integrated Flash Controller, NAND FCM
- *
- * Copyright 2011 Freescale Semiconductor, Inc.
- * Author: Dipen Dudhat <dipen.dudhat@freescale.com>
- *
- * SPDX-License-Identifier: GPL-2.0+
- */
-
-#include <common.h>
-#include <asm/io.h>
-#include <fsl_ifc.h>
-#include <linux/mtd/nand.h>
-
-static inline int is_blank(uchar *addr, int page_size)
-{
- int i;
-
- for (i = 0; i < page_size; i++) {
- if (__raw_readb(&addr[i]) != 0xff)
- return 0;
- }
-
- /*
- * For the SPL, don't worry about uncorrectable errors
- * where the main area is all FFs but shouldn't be.
- */
- return 1;
-}
-
-/* returns nonzero if entire page is blank */
-static inline int check_read_ecc(uchar *buf, u32 *eccstat,
- unsigned int bufnum, int page_size)
-{
- u32 reg = eccstat[bufnum / 4];
- int errors = (reg >> ((3 - bufnum % 4) * 8)) & 0xf;
-
- if (errors == 0xf) { /* uncorrectable */
- /* Blank pages fail hw ECC checks */
- if (is_blank(buf, page_size))
- return 1;
-
- puts("ecc error\n");
- for (;;)
- ;
- }
-
- return 0;
-}
-
-static inline void nand_wait(uchar *buf, int bufnum, int page_size)
-{
- struct fsl_ifc *ifc = IFC_BASE_ADDR;
- u32 status;
- u32 eccstat[4];
- int bufperpage = page_size / 512;
- int bufnum_end, i;
-
- bufnum *= bufperpage;
- bufnum_end = bufnum + bufperpage - 1;
-
- do {
- status = ifc_in32(&ifc->ifc_nand.nand_evter_stat);
- } while (!(status & IFC_NAND_EVTER_STAT_OPC));
-
- if (status & IFC_NAND_EVTER_STAT_FTOER) {
- puts("flash time out error\n");
- for (;;)
- ;
- }
-
- for (i = bufnum / 4; i <= bufnum_end / 4; i++)
- eccstat[i] = ifc_in32(&ifc->ifc_nand.nand_eccstat[i]);
-
- for (i = bufnum; i <= bufnum_end; i++) {
- if (check_read_ecc(buf, eccstat, i, page_size))
- break;
- }
-
- ifc_out32(&ifc->ifc_nand.nand_evter_stat, status);
-}
-
-static inline int bad_block(uchar *marker, int port_size)
-{
- if (port_size == 8)
- return __raw_readb(marker) != 0xff;
- else
- return __raw_readw((u16 *)marker) != 0xffff;
-}
-
-int nand_spl_load_image(uint32_t offs, unsigned int uboot_size, void *vdst)
-{
- struct fsl_ifc *ifc = IFC_BASE_ADDR;
- uchar *buf = (uchar *)CONFIG_SYS_NAND_BASE;
- int page_size;
- int port_size;
- int pages_per_blk;
- int blk_size;
- int bad_marker = 0;
- int bufnum_mask, bufnum;
-
- int csor, cspr;
- int pos = 0;
- int j = 0;
-
- int sram_addr;
- int pg_no;
- uchar *dst = vdst;
-
- /* Get NAND Flash configuration */
- csor = CONFIG_SYS_NAND_CSOR;
- cspr = CONFIG_SYS_NAND_CSPR;
-
- port_size = (cspr & CSPR_PORT_SIZE_16) ? 16 : 8;
-
- if ((csor & CSOR_NAND_PGS_MASK) == CSOR_NAND_PGS_8K) {
- page_size = 8192;
- bufnum_mask = 0x0;
- } else if ((csor & CSOR_NAND_PGS_MASK) == CSOR_NAND_PGS_4K) {
- page_size = 4096;
- bufnum_mask = 0x1;
- } else if ((csor & CSOR_NAND_PGS_MASK) == CSOR_NAND_PGS_2K) {
- page_size = 2048;
- bufnum_mask = 0x3;
- } else {
- page_size = 512;
- bufnum_mask = 0xf;
-
- if (port_size == 8)
- bad_marker = 5;
- }
-
- pages_per_blk =
- 32 << ((csor & CSOR_NAND_PB_MASK) >> CSOR_NAND_PB_SHIFT);
-
- blk_size = pages_per_blk * page_size;
-
- /* Open Full SRAM mapping for spare are access */
- ifc_out32(&ifc->ifc_nand.ncfgr, 0x0);
-
- /* Clear Boot events */
- ifc_out32(&ifc->ifc_nand.nand_evter_stat, 0xffffffff);
-
- /* Program FIR/FCR for Large/Small page */
- if (page_size > 512) {
- ifc_out32(&ifc->ifc_nand.nand_fir0,
- (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
- (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP1_SHIFT) |
- (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP2_SHIFT) |
- (IFC_FIR_OP_CMD1 << IFC_NAND_FIR0_OP3_SHIFT) |
- (IFC_FIR_OP_BTRD << IFC_NAND_FIR0_OP4_SHIFT));
- ifc_out32(&ifc->ifc_nand.nand_fir1, 0x0);
-
- ifc_out32(&ifc->ifc_nand.nand_fcr0,
- (NAND_CMD_READ0 << IFC_NAND_FCR0_CMD0_SHIFT) |
- (NAND_CMD_READSTART << IFC_NAND_FCR0_CMD1_SHIFT));
- } else {
- ifc_out32(&ifc->ifc_nand.nand_fir0,
- (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
- (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP1_SHIFT) |
- (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP2_SHIFT) |
- (IFC_FIR_OP_BTRD << IFC_NAND_FIR0_OP3_SHIFT));
- ifc_out32(&ifc->ifc_nand.nand_fir1, 0x0);
-
- ifc_out32(&ifc->ifc_nand.nand_fcr0,
- NAND_CMD_READ0 << IFC_NAND_FCR0_CMD0_SHIFT);
- }
-
- /* Program FBCR = 0 for full page read */
- ifc_out32(&ifc->ifc_nand.nand_fbcr, 0);
-
- /* Read and copy u-boot on SDRAM from NAND device, In parallel
- * check for Bad block if found skip it and read continue to
- * next Block
- */
- while (pos < uboot_size) {
- int i = 0;
- do {
- pg_no = offs / page_size;
- bufnum = pg_no & bufnum_mask;
- sram_addr = bufnum * page_size * 2;
-
- ifc_out32(&ifc->ifc_nand.row0, pg_no);
- ifc_out32(&ifc->ifc_nand.col0, 0);
- /* start read */
- ifc_out32(&ifc->ifc_nand.nandseq_strt,
- IFC_NAND_SEQ_STRT_FIR_STRT);
-
- /* wait for read to complete */
- nand_wait(&buf[sram_addr], bufnum, page_size);
-
- /*
- * If either of the first two pages are marked bad,
- * continue to the next block.
- */
- if (i++ < 2 &&
- bad_block(&buf[sram_addr + page_size + bad_marker],
- port_size)) {
- puts("skipping\n");
- offs = (offs + blk_size) & ~(blk_size - 1);
- pos &= ~(blk_size - 1);
- break;
- }
-
- for (j = 0; j < page_size; j++)
- dst[pos + j] = __raw_readb(&buf[sram_addr + j]);
-
- pos += page_size;
- offs += page_size;
- } while ((offs & (blk_size - 1)) && (pos < uboot_size));
- }
-
- return 0;
-}
-
-/*
- * Main entrypoint for NAND Boot. It's necessary that SDRAM is already
- * configured and available since this code loads the main U-boot image
- * from NAND into SDRAM and starts from there.
- */
-void nand_boot(void)
-{
- __attribute__((noreturn)) void (*uboot)(void);
- /*
- * Load U-Boot image from NAND into RAM
- */
- nand_spl_load_image(CONFIG_SYS_NAND_U_BOOT_OFFS,
- CONFIG_SYS_NAND_U_BOOT_SIZE,
- (uchar *)CONFIG_SYS_NAND_U_BOOT_DST);
-
-#ifdef CONFIG_NAND_ENV_DST
- nand_spl_load_image(CONFIG_ENV_OFFSET, CONFIG_ENV_SIZE,
- (uchar *)CONFIG_NAND_ENV_DST);
-
-#ifdef CONFIG_ENV_OFFSET_REDUND
- nand_spl_load_image(CONFIG_ENV_OFFSET_REDUND, CONFIG_ENV_SIZE,
- (uchar *)CONFIG_NAND_ENV_DST + CONFIG_ENV_SIZE);
-#endif
-#endif
- /*
- * Jump to U-Boot image
- */
-#ifdef CONFIG_SPL_FLUSH_IMAGE
- /*
- * Clean d-cache and invalidate i-cache, to
- * make sure that no stale data is executed.
- */
- flush_cache(CONFIG_SYS_NAND_U_BOOT_DST, CONFIG_SYS_NAND_U_BOOT_SIZE);
-#endif
- uboot = (void *)CONFIG_SYS_NAND_U_BOOT_START;
- uboot();
-}
diff --git a/qemu/roms/u-boot/drivers/mtd/nand/fsl_upm.c b/qemu/roms/u-boot/drivers/mtd/nand/fsl_upm.c
deleted file mode 100644
index 3ae0044f2..000000000
--- a/qemu/roms/u-boot/drivers/mtd/nand/fsl_upm.c
+++ /dev/null
@@ -1,199 +0,0 @@
-/*
- * FSL UPM NAND driver
- *
- * Copyright (C) 2007 MontaVista Software, Inc.
- * Anton Vorontsov <avorontsov@ru.mvista.com>
- *
- * SPDX-License-Identifier: GPL-2.0+
- */
-
-#include <config.h>
-#include <common.h>
-#include <asm/io.h>
-#include <asm/errno.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/fsl_upm.h>
-#include <nand.h>
-
-static void fsl_upm_start_pattern(struct fsl_upm *upm, u32 pat_offset)
-{
- clrsetbits_be32(upm->mxmr, MxMR_MAD_MSK, MxMR_OP_RUNP | pat_offset);
- (void)in_be32(upm->mxmr);
-}
-
-static void fsl_upm_end_pattern(struct fsl_upm *upm)
-{
- clrbits_be32(upm->mxmr, MxMR_OP_RUNP);
-
- while (in_be32(upm->mxmr) & MxMR_OP_RUNP)
- eieio();
-}
-
-static void fsl_upm_run_pattern(struct fsl_upm *upm, int width,
- void __iomem *io_addr, u32 mar)
-{
- out_be32(upm->mar, mar);
- (void)in_be32(upm->mar);
- switch (width) {
- case 8:
- out_8(io_addr, 0x0);
- break;
- case 16:
- out_be16(io_addr, 0x0);
- break;
- case 32:
- out_be32(io_addr, 0x0);
- break;
- }
-}
-
-static void fun_wait(struct fsl_upm_nand *fun)
-{
- if (fun->dev_ready) {
- while (!fun->dev_ready(fun->chip_nr))
- debug("unexpected busy state\n");
- } else {
- /*
- * If the R/B pin is not connected,
- * a short delay is necessary.
- */
- udelay(1);
- }
-}
-
-#if CONFIG_SYS_NAND_MAX_CHIPS > 1
-static void fun_select_chip(struct mtd_info *mtd, int chip_nr)
-{
- struct nand_chip *chip = mtd->priv;
- struct fsl_upm_nand *fun = chip->priv;
-
- if (chip_nr >= 0) {
- fun->chip_nr = chip_nr;
- chip->IO_ADDR_R = chip->IO_ADDR_W =
- fun->upm.io_addr + fun->chip_offset * chip_nr;
- } else if (chip_nr == -1) {
- chip->cmd_ctrl(mtd, NAND_CMD_NONE, 0 | NAND_CTRL_CHANGE);
- }
-}
-#endif
-
-static void fun_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
-{
- struct nand_chip *chip = mtd->priv;
- struct fsl_upm_nand *fun = chip->priv;
- void __iomem *io_addr;
- u32 mar;
-
- if (!(ctrl & fun->last_ctrl)) {
- fsl_upm_end_pattern(&fun->upm);
-
- if (cmd == NAND_CMD_NONE)
- return;
-
- fun->last_ctrl = ctrl & (NAND_ALE | NAND_CLE);
- }
-
- if (ctrl & NAND_CTRL_CHANGE) {
- if (ctrl & NAND_ALE)
- fsl_upm_start_pattern(&fun->upm, fun->upm_addr_offset);
- else if (ctrl & NAND_CLE)
- fsl_upm_start_pattern(&fun->upm, fun->upm_cmd_offset);
- }
-
- mar = cmd << (32 - fun->width);
- io_addr = fun->upm.io_addr;
-#if CONFIG_SYS_NAND_MAX_CHIPS > 1
- if (fun->chip_nr > 0) {
- io_addr += fun->chip_offset * fun->chip_nr;
- if (fun->upm_mar_chip_offset)
- mar |= fun->upm_mar_chip_offset * fun->chip_nr;
- }
-#endif
- fsl_upm_run_pattern(&fun->upm, fun->width, io_addr, mar);
-
- /*
- * Some boards/chips needs this. At least the MPC8360E-RDK
- * needs it. Probably weird chip, because I don't see any
- * need for this on MPC8555E + Samsung K9F1G08U0A. Usually
- * here are 0-2 unexpected busy states per block read.
- */
- if (fun->wait_flags & FSL_UPM_WAIT_RUN_PATTERN)
- fun_wait(fun);
-}
-
-static u8 upm_nand_read_byte(struct mtd_info *mtd)
-{
- struct nand_chip *chip = mtd->priv;
-
- return in_8(chip->IO_ADDR_R);
-}
-
-static void upm_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
-{
- int i;
- struct nand_chip *chip = mtd->priv;
- struct fsl_upm_nand *fun = chip->priv;
-
- for (i = 0; i < len; i++) {
- out_8(chip->IO_ADDR_W, buf[i]);
- if (fun->wait_flags & FSL_UPM_WAIT_WRITE_BYTE)
- fun_wait(fun);
- }
-
- if (fun->wait_flags & FSL_UPM_WAIT_WRITE_BUFFER)
- fun_wait(fun);
-}
-
-static void upm_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
-{
- int i;
- struct nand_chip *chip = mtd->priv;
-
- for (i = 0; i < len; i++)
- buf[i] = in_8(chip->IO_ADDR_R);
-}
-
-static int upm_nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len)
-{
- int i;
- struct nand_chip *chip = mtd->priv;
-
- for (i = 0; i < len; i++) {
- if (buf[i] != in_8(chip->IO_ADDR_R))
- return -EFAULT;
- }
-
- return 0;
-}
-
-static int nand_dev_ready(struct mtd_info *mtd)
-{
- struct nand_chip *chip = mtd->priv;
- struct fsl_upm_nand *fun = chip->priv;
-
- return fun->dev_ready(fun->chip_nr);
-}
-
-int fsl_upm_nand_init(struct nand_chip *chip, struct fsl_upm_nand *fun)
-{
- if (fun->width != 8 && fun->width != 16 && fun->width != 32)
- return -ENOSYS;
-
- fun->last_ctrl = NAND_CLE;
-
- chip->priv = fun;
- chip->chip_delay = fun->chip_delay;
- chip->ecc.mode = NAND_ECC_SOFT;
- chip->cmd_ctrl = fun_cmd_ctrl;
-#if CONFIG_SYS_NAND_MAX_CHIPS > 1
- chip->select_chip = fun_select_chip;
-#endif
- chip->read_byte = upm_nand_read_byte;
- chip->read_buf = upm_nand_read_buf;
- chip->write_buf = upm_nand_write_buf;
- chip->verify_buf = upm_nand_verify_buf;
- if (fun->dev_ready)
- chip->dev_ready = nand_dev_ready;
-
- return 0;
-}
diff --git a/qemu/roms/u-boot/drivers/mtd/nand/fsmc_nand.c b/qemu/roms/u-boot/drivers/mtd/nand/fsmc_nand.c
deleted file mode 100644
index 567eff091..000000000
--- a/qemu/roms/u-boot/drivers/mtd/nand/fsmc_nand.c
+++ /dev/null
@@ -1,473 +0,0 @@
-/*
- * (C) Copyright 2010
- * Vipin Kumar, ST Microelectronics, vipin.kumar@st.com.
- *
- * (C) Copyright 2012
- * Amit Virdi, ST Microelectronics, amit.virdi@st.com.
- *
- * SPDX-License-Identifier: GPL-2.0+
- */
-
-#include <common.h>
-#include <nand.h>
-#include <asm/io.h>
-#include <linux/bitops.h>
-#include <linux/err.h>
-#include <linux/mtd/nand_ecc.h>
-#include <linux/mtd/fsmc_nand.h>
-#include <asm/arch/hardware.h>
-
-static u32 fsmc_version;
-static struct fsmc_regs *const fsmc_regs_p = (struct fsmc_regs *)
- CONFIG_SYS_FSMC_BASE;
-
-/*
- * ECC4 and ECC1 have 13 bytes and 3 bytes of ecc respectively for 512 bytes of
- * data. ECC4 can correct up to 8 bits in 512 bytes of data while ECC1 can
- * correct 1 bit in 512 bytes
- */
-
-static struct nand_ecclayout fsmc_ecc4_lp_layout = {
- .eccbytes = 104,
- .eccpos = { 2, 3, 4, 5, 6, 7, 8,
- 9, 10, 11, 12, 13, 14,
- 18, 19, 20, 21, 22, 23, 24,
- 25, 26, 27, 28, 29, 30,
- 34, 35, 36, 37, 38, 39, 40,
- 41, 42, 43, 44, 45, 46,
- 50, 51, 52, 53, 54, 55, 56,
- 57, 58, 59, 60, 61, 62,
- 66, 67, 68, 69, 70, 71, 72,
- 73, 74, 75, 76, 77, 78,
- 82, 83, 84, 85, 86, 87, 88,
- 89, 90, 91, 92, 93, 94,
- 98, 99, 100, 101, 102, 103, 104,
- 105, 106, 107, 108, 109, 110,
- 114, 115, 116, 117, 118, 119, 120,
- 121, 122, 123, 124, 125, 126
- },
- .oobfree = {
- {.offset = 15, .length = 3},
- {.offset = 31, .length = 3},
- {.offset = 47, .length = 3},
- {.offset = 63, .length = 3},
- {.offset = 79, .length = 3},
- {.offset = 95, .length = 3},
- {.offset = 111, .length = 3},
- {.offset = 127, .length = 1}
- }
-};
-
-/*
- * ECC4 layout for NAND of pagesize 4096 bytes & OOBsize 224 bytes. 13*8 bytes
- * of OOB size is reserved for ECC, Byte no. 0 & 1 reserved for bad block & 118
- * bytes are free for use.
- */
-static struct nand_ecclayout fsmc_ecc4_224_layout = {
- .eccbytes = 104,
- .eccpos = { 2, 3, 4, 5, 6, 7, 8,
- 9, 10, 11, 12, 13, 14,
- 18, 19, 20, 21, 22, 23, 24,
- 25, 26, 27, 28, 29, 30,
- 34, 35, 36, 37, 38, 39, 40,
- 41, 42, 43, 44, 45, 46,
- 50, 51, 52, 53, 54, 55, 56,
- 57, 58, 59, 60, 61, 62,
- 66, 67, 68, 69, 70, 71, 72,
- 73, 74, 75, 76, 77, 78,
- 82, 83, 84, 85, 86, 87, 88,
- 89, 90, 91, 92, 93, 94,
- 98, 99, 100, 101, 102, 103, 104,
- 105, 106, 107, 108, 109, 110,
- 114, 115, 116, 117, 118, 119, 120,
- 121, 122, 123, 124, 125, 126
- },
- .oobfree = {
- {.offset = 15, .length = 3},
- {.offset = 31, .length = 3},
- {.offset = 47, .length = 3},
- {.offset = 63, .length = 3},
- {.offset = 79, .length = 3},
- {.offset = 95, .length = 3},
- {.offset = 111, .length = 3},
- {.offset = 127, .length = 97}
- }
-};
-
-/*
- * ECC placement definitions in oobfree type format
- * There are 13 bytes of ecc for every 512 byte block and it has to be read
- * consecutively and immediately after the 512 byte data block for hardware to
- * generate the error bit offsets in 512 byte data
- * Managing the ecc bytes in the following way makes it easier for software to
- * read ecc bytes consecutive to data bytes. This way is similar to
- * oobfree structure maintained already in u-boot nand driver
- */
-static struct fsmc_eccplace fsmc_eccpl_lp = {
- .eccplace = {
- {.offset = 2, .length = 13},
- {.offset = 18, .length = 13},
- {.offset = 34, .length = 13},
- {.offset = 50, .length = 13},
- {.offset = 66, .length = 13},
- {.offset = 82, .length = 13},
- {.offset = 98, .length = 13},
- {.offset = 114, .length = 13}
- }
-};
-
-static struct nand_ecclayout fsmc_ecc4_sp_layout = {
- .eccbytes = 13,
- .eccpos = { 0, 1, 2, 3, 6, 7, 8,
- 9, 10, 11, 12, 13, 14
- },
- .oobfree = {
- {.offset = 15, .length = 1},
- }
-};
-
-static struct fsmc_eccplace fsmc_eccpl_sp = {
- .eccplace = {
- {.offset = 0, .length = 4},
- {.offset = 6, .length = 9}
- }
-};
-
-static struct nand_ecclayout fsmc_ecc1_layout = {
- .eccbytes = 24,
- .eccpos = {2, 3, 4, 18, 19, 20, 34, 35, 36, 50, 51, 52,
- 66, 67, 68, 82, 83, 84, 98, 99, 100, 114, 115, 116},
- .oobfree = {
- {.offset = 8, .length = 8},
- {.offset = 24, .length = 8},
- {.offset = 40, .length = 8},
- {.offset = 56, .length = 8},
- {.offset = 72, .length = 8},
- {.offset = 88, .length = 8},
- {.offset = 104, .length = 8},
- {.offset = 120, .length = 8}
- }
-};
-
-/* Count the number of 0's in buff upto a max of max_bits */
-static int count_written_bits(uint8_t *buff, int size, int max_bits)
-{
- int k, written_bits = 0;
-
- for (k = 0; k < size; k++) {
- written_bits += hweight8(~buff[k]);
- if (written_bits > max_bits)
- break;
- }
-
- return written_bits;
-}
-
-static void fsmc_nand_hwcontrol(struct mtd_info *mtd, int cmd, uint ctrl)
-{
- struct nand_chip *this = mtd->priv;
- ulong IO_ADDR_W;
-
- if (ctrl & NAND_CTRL_CHANGE) {
- IO_ADDR_W = (ulong)this->IO_ADDR_W;
-
- IO_ADDR_W &= ~(CONFIG_SYS_NAND_CLE | CONFIG_SYS_NAND_ALE);
- if (ctrl & NAND_CLE)
- IO_ADDR_W |= CONFIG_SYS_NAND_CLE;
- if (ctrl & NAND_ALE)
- IO_ADDR_W |= CONFIG_SYS_NAND_ALE;
-
- if (ctrl & NAND_NCE) {
- writel(readl(&fsmc_regs_p->pc) |
- FSMC_ENABLE, &fsmc_regs_p->pc);
- } else {
- writel(readl(&fsmc_regs_p->pc) &
- ~FSMC_ENABLE, &fsmc_regs_p->pc);
- }
- this->IO_ADDR_W = (void *)IO_ADDR_W;
- }
-
- if (cmd != NAND_CMD_NONE)
- writeb(cmd, this->IO_ADDR_W);
-}
-
-static int fsmc_bch8_correct_data(struct mtd_info *mtd, u_char *dat,
- u_char *read_ecc, u_char *calc_ecc)
-{
- /* The calculated ecc is actually the correction index in data */
- u32 err_idx[8];
- u32 num_err, i;
- u32 ecc1, ecc2, ecc3, ecc4;
-
- num_err = (readl(&fsmc_regs_p->sts) >> 10) & 0xF;
-
- if (likely(num_err == 0))
- return 0;
-
- if (unlikely(num_err > 8)) {
- /*
- * This is a temporary erase check. A newly erased page read
- * would result in an ecc error because the oob data is also
- * erased to FF and the calculated ecc for an FF data is not
- * FF..FF.
- * This is a workaround to skip performing correction in case
- * data is FF..FF
- *
- * Logic:
- * For every page, each bit written as 0 is counted until these
- * number of bits are greater than 8 (the maximum correction
- * capability of FSMC for each 512 + 13 bytes)
- */
-
- int bits_ecc = count_written_bits(read_ecc, 13, 8);
- int bits_data = count_written_bits(dat, 512, 8);
-
- if ((bits_ecc + bits_data) <= 8) {
- if (bits_data)
- memset(dat, 0xff, 512);
- return bits_data + bits_ecc;
- }
-
- return -EBADMSG;
- }
-
- ecc1 = readl(&fsmc_regs_p->ecc1);
- ecc2 = readl(&fsmc_regs_p->ecc2);
- ecc3 = readl(&fsmc_regs_p->ecc3);
- ecc4 = readl(&fsmc_regs_p->sts);
-
- err_idx[0] = (ecc1 >> 0) & 0x1FFF;
- err_idx[1] = (ecc1 >> 13) & 0x1FFF;
- err_idx[2] = (((ecc2 >> 0) & 0x7F) << 6) | ((ecc1 >> 26) & 0x3F);
- err_idx[3] = (ecc2 >> 7) & 0x1FFF;
- err_idx[4] = (((ecc3 >> 0) & 0x1) << 12) | ((ecc2 >> 20) & 0xFFF);
- err_idx[5] = (ecc3 >> 1) & 0x1FFF;
- err_idx[6] = (ecc3 >> 14) & 0x1FFF;
- err_idx[7] = (((ecc4 >> 16) & 0xFF) << 5) | ((ecc3 >> 27) & 0x1F);
-
- i = 0;
- while (i < num_err) {
- err_idx[i] ^= 3;
-
- if (err_idx[i] < 512 * 8)
- __change_bit(err_idx[i], dat);
-
- i++;
- }
-
- return num_err;
-}
-
-static int fsmc_read_hwecc(struct mtd_info *mtd,
- const u_char *data, u_char *ecc)
-{
- u_int ecc_tmp;
- int timeout = CONFIG_SYS_HZ;
- ulong start;
-
- switch (fsmc_version) {
- case FSMC_VER8:
- start = get_timer(0);
- while (get_timer(start) < timeout) {
- /*
- * Busy waiting for ecc computation
- * to finish for 512 bytes
- */
- if (readl(&fsmc_regs_p->sts) & FSMC_CODE_RDY)
- break;
- }
-
- ecc_tmp = readl(&fsmc_regs_p->ecc1);
- ecc[0] = (u_char) (ecc_tmp >> 0);
- ecc[1] = (u_char) (ecc_tmp >> 8);
- ecc[2] = (u_char) (ecc_tmp >> 16);
- ecc[3] = (u_char) (ecc_tmp >> 24);
-
- ecc_tmp = readl(&fsmc_regs_p->ecc2);
- ecc[4] = (u_char) (ecc_tmp >> 0);
- ecc[5] = (u_char) (ecc_tmp >> 8);
- ecc[6] = (u_char) (ecc_tmp >> 16);
- ecc[7] = (u_char) (ecc_tmp >> 24);
-
- ecc_tmp = readl(&fsmc_regs_p->ecc3);
- ecc[8] = (u_char) (ecc_tmp >> 0);
- ecc[9] = (u_char) (ecc_tmp >> 8);
- ecc[10] = (u_char) (ecc_tmp >> 16);
- ecc[11] = (u_char) (ecc_tmp >> 24);
-
- ecc_tmp = readl(&fsmc_regs_p->sts);
- ecc[12] = (u_char) (ecc_tmp >> 16);
- break;
-
- default:
- ecc_tmp = readl(&fsmc_regs_p->ecc1);
- ecc[0] = (u_char) (ecc_tmp >> 0);
- ecc[1] = (u_char) (ecc_tmp >> 8);
- ecc[2] = (u_char) (ecc_tmp >> 16);
- break;
- }
-
- return 0;
-}
-
-void fsmc_enable_hwecc(struct mtd_info *mtd, int mode)
-{
- writel(readl(&fsmc_regs_p->pc) & ~FSMC_ECCPLEN_256,
- &fsmc_regs_p->pc);
- writel(readl(&fsmc_regs_p->pc) & ~FSMC_ECCEN,
- &fsmc_regs_p->pc);
- writel(readl(&fsmc_regs_p->pc) | FSMC_ECCEN,
- &fsmc_regs_p->pc);
-}
-
-/*
- * fsmc_read_page_hwecc
- * @mtd: mtd info structure
- * @chip: nand chip info structure
- * @buf: buffer to store read data
- * @oob_required: caller expects OOB data read to chip->oob_poi
- * @page: page number to read
- *
- * This routine is needed for fsmc verison 8 as reading from NAND chip has to be
- * performed in a strict sequence as follows:
- * data(512 byte) -> ecc(13 byte)
- * After this read, fsmc hardware generates and reports error data bits(upto a
- * max of 8 bits)
- */
-static int fsmc_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
- uint8_t *buf, int oob_required, int page)
-{
- struct fsmc_eccplace *fsmc_eccpl;
- int i, j, s, stat, eccsize = chip->ecc.size;
- int eccbytes = chip->ecc.bytes;
- int eccsteps = chip->ecc.steps;
- uint8_t *p = buf;
- uint8_t *ecc_calc = chip->buffers->ecccalc;
- uint8_t *ecc_code = chip->buffers->ecccode;
- int off, len, group = 0;
- uint8_t oob[13] __attribute__ ((aligned (2)));
-
- /* Differentiate between small and large page ecc place definitions */
- if (mtd->writesize == 512)
- fsmc_eccpl = &fsmc_eccpl_sp;
- else
- fsmc_eccpl = &fsmc_eccpl_lp;
-
- for (i = 0, s = 0; s < eccsteps; s++, i += eccbytes, p += eccsize) {
-
- chip->cmdfunc(mtd, NAND_CMD_READ0, s * eccsize, page);
- chip->ecc.hwctl(mtd, NAND_ECC_READ);
- chip->read_buf(mtd, p, eccsize);
-
- for (j = 0; j < eccbytes;) {
- off = fsmc_eccpl->eccplace[group].offset;
- len = fsmc_eccpl->eccplace[group].length;
- group++;
-
- /*
- * length is intentionally kept a higher multiple of 2
- * to read at least 13 bytes even in case of 16 bit NAND
- * devices
- */
- if (chip->options & NAND_BUSWIDTH_16)
- len = roundup(len, 2);
- chip->cmdfunc(mtd, NAND_CMD_READOOB, off, page);
- chip->read_buf(mtd, oob + j, len);
- j += len;
- }
-
- memcpy(&ecc_code[i], oob, 13);
- chip->ecc.calculate(mtd, p, &ecc_calc[i]);
-
- stat = chip->ecc.correct(mtd, p, &ecc_code[i],
- &ecc_calc[i]);
- if (stat < 0)
- mtd->ecc_stats.failed++;
- else
- mtd->ecc_stats.corrected += stat;
- }
-
- return 0;
-}
-
-int fsmc_nand_init(struct nand_chip *nand)
-{
- static int chip_nr;
- struct mtd_info *mtd;
- int i;
- u32 peripid2 = readl(&fsmc_regs_p->peripid2);
-
- fsmc_version = (peripid2 >> FSMC_REVISION_SHFT) &
- FSMC_REVISION_MSK;
-
- writel(readl(&fsmc_regs_p->ctrl) | FSMC_WP, &fsmc_regs_p->ctrl);
-
-#if defined(CONFIG_SYS_FSMC_NAND_16BIT)
- writel(FSMC_DEVWID_16 | FSMC_DEVTYPE_NAND | FSMC_ENABLE | FSMC_WAITON,
- &fsmc_regs_p->pc);
-#elif defined(CONFIG_SYS_FSMC_NAND_8BIT)
- writel(FSMC_DEVWID_8 | FSMC_DEVTYPE_NAND | FSMC_ENABLE | FSMC_WAITON,
- &fsmc_regs_p->pc);
-#else
-#error Please define CONFIG_SYS_FSMC_NAND_16BIT or CONFIG_SYS_FSMC_NAND_8BIT
-#endif
- writel(readl(&fsmc_regs_p->pc) | FSMC_TCLR_1 | FSMC_TAR_1,
- &fsmc_regs_p->pc);
- writel(FSMC_THIZ_1 | FSMC_THOLD_4 | FSMC_TWAIT_6 | FSMC_TSET_0,
- &fsmc_regs_p->comm);
- writel(FSMC_THIZ_1 | FSMC_THOLD_4 | FSMC_TWAIT_6 | FSMC_TSET_0,
- &fsmc_regs_p->attrib);
-
- nand->options = 0;
-#if defined(CONFIG_SYS_FSMC_NAND_16BIT)
- nand->options |= NAND_BUSWIDTH_16;
-#endif
- nand->ecc.mode = NAND_ECC_HW;
- nand->ecc.size = 512;
- nand->ecc.calculate = fsmc_read_hwecc;
- nand->ecc.hwctl = fsmc_enable_hwecc;
- nand->cmd_ctrl = fsmc_nand_hwcontrol;
- nand->IO_ADDR_R = nand->IO_ADDR_W =
- (void __iomem *)CONFIG_SYS_NAND_BASE;
- nand->badblockbits = 7;
-
- mtd = &nand_info[chip_nr++];
- mtd->priv = nand;
-
- switch (fsmc_version) {
- case FSMC_VER8:
- nand->ecc.bytes = 13;
- nand->ecc.strength = 8;
- nand->ecc.correct = fsmc_bch8_correct_data;
- nand->ecc.read_page = fsmc_read_page_hwecc;
- if (mtd->writesize == 512)
- nand->ecc.layout = &fsmc_ecc4_sp_layout;
- else {
- if (mtd->oobsize == 224)
- nand->ecc.layout = &fsmc_ecc4_224_layout;
- else
- nand->ecc.layout = &fsmc_ecc4_lp_layout;
- }
-
- break;
- default:
- nand->ecc.bytes = 3;
- nand->ecc.strength = 1;
- nand->ecc.layout = &fsmc_ecc1_layout;
- nand->ecc.correct = nand_correct_data;
- break;
- }
-
- /* Detect NAND chips */
- if (nand_scan_ident(mtd, CONFIG_SYS_MAX_NAND_DEVICE, NULL))
- return -ENXIO;
-
- if (nand_scan_tail(mtd))
- return -ENXIO;
-
- for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++)
- if (nand_register(i))
- return -ENXIO;
-
- return 0;
-}
diff --git a/qemu/roms/u-boot/drivers/mtd/nand/jz4740_nand.c b/qemu/roms/u-boot/drivers/mtd/nand/jz4740_nand.c
deleted file mode 100644
index 7a62cc336..000000000
--- a/qemu/roms/u-boot/drivers/mtd/nand/jz4740_nand.c
+++ /dev/null
@@ -1,259 +0,0 @@
-/*
- * Platform independend driver for JZ4740.
- *
- * Copyright (c) 2007 Ingenic Semiconductor Inc.
- * Author: <jlwei@ingenic.cn>
- *
- * SPDX-License-Identifier: GPL-2.0+
- */
-#include <common.h>
-
-#include <nand.h>
-#include <asm/io.h>
-#include <asm/jz4740.h>
-
-#define JZ_NAND_DATA_ADDR ((void __iomem *)0xB8000000)
-#define JZ_NAND_CMD_ADDR (JZ_NAND_DATA_ADDR + 0x8000)
-#define JZ_NAND_ADDR_ADDR (JZ_NAND_DATA_ADDR + 0x10000)
-
-#define BIT(x) (1 << (x))
-#define JZ_NAND_ECC_CTRL_ENCODING BIT(3)
-#define JZ_NAND_ECC_CTRL_RS BIT(2)
-#define JZ_NAND_ECC_CTRL_RESET BIT(1)
-#define JZ_NAND_ECC_CTRL_ENABLE BIT(0)
-
-#define EMC_SMCR1_OPT_NAND 0x094c4400
-/* Optimize the timing of nand */
-
-static struct jz4740_emc * emc = (struct jz4740_emc *)JZ4740_EMC_BASE;
-
-static struct nand_ecclayout qi_lb60_ecclayout_2gb = {
- .eccbytes = 72,
- .eccpos = {
- 12, 13, 14, 15, 16, 17, 18, 19,
- 20, 21, 22, 23, 24, 25, 26, 27,
- 28, 29, 30, 31, 32, 33, 34, 35,
- 36, 37, 38, 39, 40, 41, 42, 43,
- 44, 45, 46, 47, 48, 49, 50, 51,
- 52, 53, 54, 55, 56, 57, 58, 59,
- 60, 61, 62, 63, 64, 65, 66, 67,
- 68, 69, 70, 71, 72, 73, 74, 75,
- 76, 77, 78, 79, 80, 81, 82, 83 },
- .oobfree = {
- {.offset = 2,
- .length = 10 },
- {.offset = 84,
- .length = 44 } }
-};
-
-static int is_reading;
-
-static void jz_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
-{
- struct nand_chip *this = mtd->priv;
- uint32_t reg;
-
- if (ctrl & NAND_CTRL_CHANGE) {
- if (ctrl & NAND_ALE)
- this->IO_ADDR_W = JZ_NAND_ADDR_ADDR;
- else if (ctrl & NAND_CLE)
- this->IO_ADDR_W = JZ_NAND_CMD_ADDR;
- else
- this->IO_ADDR_W = JZ_NAND_DATA_ADDR;
-
- reg = readl(&emc->nfcsr);
- if (ctrl & NAND_NCE)
- reg |= EMC_NFCSR_NFCE1;
- else
- reg &= ~EMC_NFCSR_NFCE1;
- writel(reg, &emc->nfcsr);
- }
-
- if (cmd != NAND_CMD_NONE)
- writeb(cmd, this->IO_ADDR_W);
-}
-
-static int jz_nand_device_ready(struct mtd_info *mtd)
-{
- return (readl(GPIO_PXPIN(2)) & 0x40000000) ? 1 : 0;
-}
-
-void board_nand_select_device(struct nand_chip *nand, int chip)
-{
- /*
- * Don't use "chip" to address the NAND device,
- * generate the cs from the address where it is encoded.
- */
-}
-
-static int jz_nand_rs_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
- u_char *ecc_code)
-{
- uint32_t status;
- int i;
-
- if (is_reading)
- return 0;
-
- do {
- status = readl(&emc->nfints);
- } while (!(status & EMC_NFINTS_ENCF));
-
- /* disable ecc */
- writel(readl(&emc->nfecr) & ~EMC_NFECR_ECCE, &emc->nfecr);
-
- for (i = 0; i < 9; i++)
- ecc_code[i] = readb(&emc->nfpar[i]);
-
- return 0;
-}
-
-static void jz_nand_hwctl(struct mtd_info *mtd, int mode)
-{
- uint32_t reg;
-
- writel(0, &emc->nfints);
- reg = readl(&emc->nfecr);
- reg |= JZ_NAND_ECC_CTRL_RESET;
- reg |= JZ_NAND_ECC_CTRL_ENABLE;
- reg |= JZ_NAND_ECC_CTRL_RS;
-
- switch (mode) {
- case NAND_ECC_READ:
- reg &= ~JZ_NAND_ECC_CTRL_ENCODING;
- is_reading = 1;
- break;
- case NAND_ECC_WRITE:
- reg |= JZ_NAND_ECC_CTRL_ENCODING;
- is_reading = 0;
- break;
- default:
- break;
- }
-
- writel(reg, &emc->nfecr);
-}
-
-/* Correct 1~9-bit errors in 512-bytes data */
-static void jz_rs_correct(unsigned char *dat, int idx, int mask)
-{
- int i;
-
- idx--;
-
- i = idx + (idx >> 3);
- if (i >= 512)
- return;
-
- mask <<= (idx & 0x7);
-
- dat[i] ^= mask & 0xff;
- if (i < 511)
- dat[i + 1] ^= (mask >> 8) & 0xff;
-}
-
-static int jz_nand_rs_correct_data(struct mtd_info *mtd, u_char *dat,
- u_char *read_ecc, u_char *calc_ecc)
-{
- int k;
- uint32_t errcnt, index, mask, status;
-
- /* Set PAR values */
- const uint8_t all_ff_ecc[] = {
- 0xcd, 0x9d, 0x90, 0x58, 0xf4, 0x8b, 0xff, 0xb7, 0x6f };
-
- if (read_ecc[0] == 0xff && read_ecc[1] == 0xff &&
- read_ecc[2] == 0xff && read_ecc[3] == 0xff &&
- read_ecc[4] == 0xff && read_ecc[5] == 0xff &&
- read_ecc[6] == 0xff && read_ecc[7] == 0xff &&
- read_ecc[8] == 0xff) {
- for (k = 0; k < 9; k++)
- writeb(all_ff_ecc[k], &emc->nfpar[k]);
- } else {
- for (k = 0; k < 9; k++)
- writeb(read_ecc[k], &emc->nfpar[k]);
- }
- /* Set PRDY */
- writel(readl(&emc->nfecr) | EMC_NFECR_PRDY, &emc->nfecr);
-
- /* Wait for completion */
- do {
- status = readl(&emc->nfints);
- } while (!(status & EMC_NFINTS_DECF));
-
- /* disable ecc */
- writel(readl(&emc->nfecr) & ~EMC_NFECR_ECCE, &emc->nfecr);
-
- /* Check decoding */
- if (!(status & EMC_NFINTS_ERR))
- return 0;
-
- if (status & EMC_NFINTS_UNCOR) {
- printf("uncorrectable ecc\n");
- return -1;
- }
-
- errcnt = (status & EMC_NFINTS_ERRCNT_MASK) >> EMC_NFINTS_ERRCNT_BIT;
-
- switch (errcnt) {
- case 4:
- index = (readl(&emc->nferr[3]) & EMC_NFERR_INDEX_MASK) >>
- EMC_NFERR_INDEX_BIT;
- mask = (readl(&emc->nferr[3]) & EMC_NFERR_MASK_MASK) >>
- EMC_NFERR_MASK_BIT;
- jz_rs_correct(dat, index, mask);
- case 3:
- index = (readl(&emc->nferr[2]) & EMC_NFERR_INDEX_MASK) >>
- EMC_NFERR_INDEX_BIT;
- mask = (readl(&emc->nferr[2]) & EMC_NFERR_MASK_MASK) >>
- EMC_NFERR_MASK_BIT;
- jz_rs_correct(dat, index, mask);
- case 2:
- index = (readl(&emc->nferr[1]) & EMC_NFERR_INDEX_MASK) >>
- EMC_NFERR_INDEX_BIT;
- mask = (readl(&emc->nferr[1]) & EMC_NFERR_MASK_MASK) >>
- EMC_NFERR_MASK_BIT;
- jz_rs_correct(dat, index, mask);
- case 1:
- index = (readl(&emc->nferr[0]) & EMC_NFERR_INDEX_MASK) >>
- EMC_NFERR_INDEX_BIT;
- mask = (readl(&emc->nferr[0]) & EMC_NFERR_MASK_MASK) >>
- EMC_NFERR_MASK_BIT;
- jz_rs_correct(dat, index, mask);
- default:
- break;
- }
-
- return errcnt;
-}
-
-/*
- * Main initialization routine
- */
-int board_nand_init(struct nand_chip *nand)
-{
- uint32_t reg;
-
- reg = readl(&emc->nfcsr);
- reg |= EMC_NFCSR_NFE1; /* EMC setup, Set NFE bit */
- writel(reg, &emc->nfcsr);
-
- writel(EMC_SMCR1_OPT_NAND, &emc->smcr[1]);
-
- nand->IO_ADDR_R = JZ_NAND_DATA_ADDR;
- nand->IO_ADDR_W = JZ_NAND_DATA_ADDR;
- nand->cmd_ctrl = jz_nand_cmd_ctrl;
- nand->dev_ready = jz_nand_device_ready;
- nand->ecc.hwctl = jz_nand_hwctl;
- nand->ecc.correct = jz_nand_rs_correct_data;
- nand->ecc.calculate = jz_nand_rs_calculate_ecc;
- nand->ecc.mode = NAND_ECC_HW_OOB_FIRST;
- nand->ecc.size = CONFIG_SYS_NAND_ECCSIZE;
- nand->ecc.bytes = CONFIG_SYS_NAND_ECCBYTES;
- nand->ecc.strength = 4;
- nand->ecc.layout = &qi_lb60_ecclayout_2gb;
- nand->chip_delay = 50;
- nand->bbt_options |= NAND_BBT_USE_FLASH;
-
- return 0;
-}
diff --git a/qemu/roms/u-boot/drivers/mtd/nand/kb9202_nand.c b/qemu/roms/u-boot/drivers/mtd/nand/kb9202_nand.c
deleted file mode 100644
index 22c562540..000000000
--- a/qemu/roms/u-boot/drivers/mtd/nand/kb9202_nand.c
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * (C) Copyright 2006
- * KwikByte <kb9200_dev@kwikbyte.com>
- *
- * (C) Copyright 2009
- * Matthias Kaehlcke <matthias@kaehlcke.net>
- *
- * SPDX-License-Identifier: GPL-2.0+
- */
-
-#include <common.h>
-#include <asm/io.h>
-#include <asm/arch/AT91RM9200.h>
-#include <asm/arch/hardware.h>
-
-#include <nand.h>
-
-/*
- * hardware specific access to control-lines
- */
-
-#define MASK_ALE (1 << 22) /* our ALE is A22 */
-#define MASK_CLE (1 << 21) /* our CLE is A21 */
-
-#define KB9202_NAND_NCE (1 << 28) /* EN* on D28 */
-#define KB9202_NAND_BUSY (1 << 29) /* RB* on D29 */
-
-#define KB9202_SMC2_NWS (1 << 2)
-#define KB9202_SMC2_TDF (1 << 8)
-#define KB9202_SMC2_RWSETUP (1 << 24)
-#define KB9202_SMC2_RWHOLD (1 << 29)
-
-/*
- * Board-specific function to access device control signals
- */
-static void kb9202_nand_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
-{
- struct nand_chip *this = mtd->priv;
-
- if (ctrl & NAND_CTRL_CHANGE) {
- ulong IO_ADDR_W = (ulong) this->IO_ADDR_W;
-
- /* clear ALE and CLE bits */
- IO_ADDR_W &= ~(MASK_ALE | MASK_CLE);
-
- if (ctrl & NAND_CLE)
- IO_ADDR_W |= MASK_CLE;
-
- if (ctrl & NAND_ALE)
- IO_ADDR_W |= MASK_ALE;
-
- this->IO_ADDR_W = (void *) IO_ADDR_W;
-
- if (ctrl & NAND_NCE)
- writel(KB9202_NAND_NCE, AT91C_PIOC_CODR);
- else
- writel(KB9202_NAND_NCE, AT91C_PIOC_SODR);
- }
-
- if (cmd != NAND_CMD_NONE)
- writeb(cmd, this->IO_ADDR_W);
-}
-
-
-/*
- * Board-specific function to access the device ready signal.
- */
-static int kb9202_nand_ready(struct mtd_info *mtd)
-{
- return readl(AT91C_PIOC_PDSR) & KB9202_NAND_BUSY;
-}
-
-
-/*
- * Board-specific NAND init. Copied from include/linux/mtd/nand.h for reference.
- *
- * struct nand_chip - NAND Private Flash Chip Data
- * @IO_ADDR_R: [BOARDSPECIFIC] address to read the 8 I/O lines of the flash device
- * @IO_ADDR_W: [BOARDSPECIFIC] address to write the 8 I/O lines of the flash device
- * @hwcontrol: [BOARDSPECIFIC] hardwarespecific function for accesing control-lines
- * @dev_ready: [BOARDSPECIFIC] hardwarespecific function for accesing device ready/busy line
- * If set to NULL no access to ready/busy is available and the ready/busy information
- * is read from the chip status register
- * @enable_hwecc: [BOARDSPECIFIC] function to enable (reset) hardware ecc generator. Must only
- * be provided if a hardware ECC is available
- * @eccmode: [BOARDSPECIFIC] mode of ecc, see defines
- * @chip_delay: [BOARDSPECIFIC] chip dependent delay for transfering data from array to read regs (tR)
- * @options: [BOARDSPECIFIC] various chip options. They can partly be set to inform nand_scan about
- * special functionality. See the defines for further explanation
-*/
-/*
- * This routine initializes controller and GPIOs.
- */
-int board_nand_init(struct nand_chip *nand)
-{
- unsigned int value;
-
- nand->ecc.mode = NAND_ECC_SOFT;
- nand->cmd_ctrl = kb9202_nand_hwcontrol;
- nand->dev_ready = kb9202_nand_ready;
-
- /* in case running outside of bootloader */
- writel(1 << AT91C_ID_PIOC, AT91C_PMC_PCER);
-
- /* setup nand flash access (allow ample margin) */
- /* 4 wait states, 1 setup, 1 hold, 1 float for 8-bit device */
- writel(AT91C_SMC2_WSEN | KB9202_SMC2_NWS | KB9202_SMC2_TDF |
- AT91C_SMC2_DBW_8 | KB9202_SMC2_RWSETUP | KB9202_SMC2_RWHOLD,
- AT91C_SMC_CSR3);
-
- /* enable internal NAND controller */
- value = readl(AT91C_EBI_CSA);
- value |= AT91C_EBI_CS3A_SMC_SmartMedia;
- writel(value, AT91C_EBI_CSA);
-
- /* enable SMOE/SMWE */
- writel(AT91C_PC1_BFRDY_SMOE | AT91C_PC3_BFBAA_SMWE, AT91C_PIOC_ASR);
- writel(AT91C_PC1_BFRDY_SMOE | AT91C_PC3_BFBAA_SMWE, AT91C_PIOC_PDR);
- writel(AT91C_PC1_BFRDY_SMOE | AT91C_PC3_BFBAA_SMWE, AT91C_PIOC_OER);
-
- /* set NCE to high */
- writel(KB9202_NAND_NCE, AT91C_PIOC_SODR);
-
- /* disable output on pin connected to the busy line of the NAND */
- writel(KB9202_NAND_BUSY, AT91C_PIOC_ODR);
-
- /* enable the PIO to control NCE and BUSY */
- writel(KB9202_NAND_NCE | KB9202_NAND_BUSY, AT91C_PIOC_PER);
-
- /* enable output for NCE */
- writel(KB9202_NAND_NCE, AT91C_PIOC_OER);
-
- return (0);
-}
diff --git a/qemu/roms/u-boot/drivers/mtd/nand/kirkwood_nand.c b/qemu/roms/u-boot/drivers/mtd/nand/kirkwood_nand.c
deleted file mode 100644
index 72687a1da..000000000
--- a/qemu/roms/u-boot/drivers/mtd/nand/kirkwood_nand.c
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * (C) Copyright 2009
- * Marvell Semiconductor <www.marvell.com>
- * Written-by: Prafulla Wadaskar <prafulla@marvell.com>
- *
- * SPDX-License-Identifier: GPL-2.0+
- */
-
-#include <common.h>
-#include <asm/io.h>
-#include <asm/arch/kirkwood.h>
-#include <nand.h>
-
-/* NAND Flash Soc registers */
-struct kwnandf_registers {
- u32 rd_params; /* 0x10418 */
- u32 wr_param; /* 0x1041c */
- u8 pad[0x10470 - 0x1041c - 4];
- u32 ctrl; /* 0x10470 */
-};
-
-static struct kwnandf_registers *nf_reg =
- (struct kwnandf_registers *)KW_NANDF_BASE;
-
-/*
- * hardware specific access to control-lines/bits
- */
-#define NAND_ACTCEBOOT_BIT 0x02
-
-static void kw_nand_hwcontrol(struct mtd_info *mtd, int cmd,
- unsigned int ctrl)
-{
- struct nand_chip *nc = mtd->priv;
- u32 offs;
-
- if (cmd == NAND_CMD_NONE)
- return;
-
- if (ctrl & NAND_CLE)
- offs = (1 << 0); /* Commands with A[1:0] == 01 */
- else if (ctrl & NAND_ALE)
- offs = (1 << 1); /* Addresses with A[1:0] == 10 */
- else
- return;
-
- writeb(cmd, nc->IO_ADDR_W + offs);
-}
-
-void kw_nand_select_chip(struct mtd_info *mtd, int chip)
-{
- u32 data;
-
- data = readl(&nf_reg->ctrl);
- data |= NAND_ACTCEBOOT_BIT;
- writel(data, &nf_reg->ctrl);
-}
-
-int board_nand_init(struct nand_chip *nand)
-{
- nand->options = NAND_COPYBACK | NAND_CACHEPRG | NAND_NO_PADDING;
-#if defined(CONFIG_NAND_ECC_BCH)
- nand->ecc.mode = NAND_ECC_SOFT_BCH;
-#else
- nand->ecc.mode = NAND_ECC_SOFT;
-#endif
- nand->cmd_ctrl = kw_nand_hwcontrol;
- nand->chip_delay = 40;
- nand->select_chip = kw_nand_select_chip;
- return 0;
-}
diff --git a/qemu/roms/u-boot/drivers/mtd/nand/kmeter1_nand.c b/qemu/roms/u-boot/drivers/mtd/nand/kmeter1_nand.c
deleted file mode 100644
index df0bde579..000000000
--- a/qemu/roms/u-boot/drivers/mtd/nand/kmeter1_nand.c
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * (C) Copyright 2009
- * Heiko Schocher, DENX Software Engineering, hs@denx.de
- *
- * SPDX-License-Identifier: GPL-2.0+
- */
-
-#include <common.h>
-#include <nand.h>
-#include <asm/io.h>
-
-#define CONFIG_NAND_MODE_REG (void *)(CONFIG_SYS_NAND_BASE + 0x20000)
-#define CONFIG_NAND_DATA_REG (void *)(CONFIG_SYS_NAND_BASE + 0x30000)
-
-#define read_mode() in_8(CONFIG_NAND_MODE_REG)
-#define write_mode(val) out_8(CONFIG_NAND_MODE_REG, val)
-#define read_data() in_8(CONFIG_NAND_DATA_REG)
-#define write_data(val) out_8(CONFIG_NAND_DATA_REG, val)
-
-#define KPN_RDY2 (1 << 7)
-#define KPN_RDY1 (1 << 6)
-#define KPN_WPN (1 << 4)
-#define KPN_CE2N (1 << 3)
-#define KPN_CE1N (1 << 2)
-#define KPN_ALE (1 << 1)
-#define KPN_CLE (1 << 0)
-
-#define KPN_DEFAULT_CHIP_DELAY 50
-
-static int kpn_chip_ready(void)
-{
- if (read_mode() & KPN_RDY1)
- return 1;
-
- return 0;
-}
-
-static void kpn_wait_rdy(void)
-{
- int cnt = 1000000;
-
- while (--cnt && !kpn_chip_ready())
- udelay(1);
-
- if (!cnt)
- printf ("timeout while waiting for RDY\n");
-}
-
-static void kpn_nand_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
-{
- u8 reg_val = read_mode();
-
- if (ctrl & NAND_CTRL_CHANGE) {
- reg_val = reg_val & ~(KPN_ALE + KPN_CLE);
-
- if (ctrl & NAND_CLE)
- reg_val = reg_val | KPN_CLE;
- if (ctrl & NAND_ALE)
- reg_val = reg_val | KPN_ALE;
- if (ctrl & NAND_NCE)
- reg_val = reg_val & ~KPN_CE1N;
- else
- reg_val = reg_val | KPN_CE1N;
-
- write_mode(reg_val);
- }
- if (cmd != NAND_CMD_NONE)
- write_data(cmd);
-
- /* wait until flash is ready */
- kpn_wait_rdy();
-}
-
-static u_char kpn_nand_read_byte(struct mtd_info *mtd)
-{
- return read_data();
-}
-
-static void kpn_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
-{
- int i;
-
- for (i = 0; i < len; i++) {
- write_data(buf[i]);
- kpn_wait_rdy();
- }
-}
-
-static void kpn_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
-{
- int i;
-
- for (i = 0; i < len; i++)
- buf[i] = read_data();
-}
-
-static int kpn_nand_dev_ready(struct mtd_info *mtd)
-{
- kpn_wait_rdy();
-
- return 1;
-}
-
-int board_nand_init(struct nand_chip *nand)
-{
-#if defined(CONFIG_NAND_ECC_BCH)
- nand->ecc.mode = NAND_ECC_SOFT_BCH;
-#else
- nand->ecc.mode = NAND_ECC_SOFT;
-#endif
-
- /* Reference hardware control function */
- nand->cmd_ctrl = kpn_nand_hwcontrol;
- nand->read_byte = kpn_nand_read_byte;
- nand->write_buf = kpn_nand_write_buf;
- nand->read_buf = kpn_nand_read_buf;
- nand->dev_ready = kpn_nand_dev_ready;
- nand->chip_delay = KPN_DEFAULT_CHIP_DELAY;
-
- /* reset mode register */
- write_mode(KPN_CE1N + KPN_CE2N + KPN_WPN);
- return 0;
-}
diff --git a/qemu/roms/u-boot/drivers/mtd/nand/mpc5121_nfc.c b/qemu/roms/u-boot/drivers/mtd/nand/mpc5121_nfc.c
deleted file mode 100644
index d0f3a3532..000000000
--- a/qemu/roms/u-boot/drivers/mtd/nand/mpc5121_nfc.c
+++ /dev/null
@@ -1,681 +0,0 @@
-/*
- * Copyright 2004-2008 Freescale Semiconductor, Inc.
- * Copyright 2009 Semihalf.
- * (C) Copyright 2009 Stefan Roese <sr@denx.de>
- *
- * Based on original driver from Freescale Semiconductor
- * written by John Rigby <jrigby@freescale.com> on basis
- * of drivers/mtd/nand/mxc_nand.c. Reworked and extended
- * Piotr Ziecik <kosmo@semihalf.com>.
- *
- * SPDX-License-Identifier: GPL-2.0+
- */
-
-#include <common.h>
-#include <malloc.h>
-
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
-#include <linux/mtd/nand_ecc.h>
-#include <linux/compat.h>
-
-#include <asm/errno.h>
-#include <asm/io.h>
-#include <asm/processor.h>
-#include <nand.h>
-
-#define DRV_NAME "mpc5121_nfc"
-
-/* Timeouts */
-#define NFC_RESET_TIMEOUT 1000 /* 1 ms */
-#define NFC_TIMEOUT 2000 /* 2000 us */
-
-/* Addresses for NFC MAIN RAM BUFFER areas */
-#define NFC_MAIN_AREA(n) ((n) * 0x200)
-
-/* Addresses for NFC SPARE BUFFER areas */
-#define NFC_SPARE_BUFFERS 8
-#define NFC_SPARE_LEN 0x40
-#define NFC_SPARE_AREA(n) (0x1000 + ((n) * NFC_SPARE_LEN))
-
-/* MPC5121 NFC registers */
-#define NFC_BUF_ADDR 0x1E04
-#define NFC_FLASH_ADDR 0x1E06
-#define NFC_FLASH_CMD 0x1E08
-#define NFC_CONFIG 0x1E0A
-#define NFC_ECC_STATUS1 0x1E0C
-#define NFC_ECC_STATUS2 0x1E0E
-#define NFC_SPAS 0x1E10
-#define NFC_WRPROT 0x1E12
-#define NFC_NF_WRPRST 0x1E18
-#define NFC_CONFIG1 0x1E1A
-#define NFC_CONFIG2 0x1E1C
-#define NFC_UNLOCKSTART_BLK0 0x1E20
-#define NFC_UNLOCKEND_BLK0 0x1E22
-#define NFC_UNLOCKSTART_BLK1 0x1E24
-#define NFC_UNLOCKEND_BLK1 0x1E26
-#define NFC_UNLOCKSTART_BLK2 0x1E28
-#define NFC_UNLOCKEND_BLK2 0x1E2A
-#define NFC_UNLOCKSTART_BLK3 0x1E2C
-#define NFC_UNLOCKEND_BLK3 0x1E2E
-
-/* Bit Definitions: NFC_BUF_ADDR */
-#define NFC_RBA_MASK (7 << 0)
-#define NFC_ACTIVE_CS_SHIFT 5
-#define NFC_ACTIVE_CS_MASK (3 << NFC_ACTIVE_CS_SHIFT)
-
-/* Bit Definitions: NFC_CONFIG */
-#define NFC_BLS_UNLOCKED (1 << 1)
-
-/* Bit Definitions: NFC_CONFIG1 */
-#define NFC_ECC_4BIT (1 << 0)
-#define NFC_FULL_PAGE_DMA (1 << 1)
-#define NFC_SPARE_ONLY (1 << 2)
-#define NFC_ECC_ENABLE (1 << 3)
-#define NFC_INT_MASK (1 << 4)
-#define NFC_BIG_ENDIAN (1 << 5)
-#define NFC_RESET (1 << 6)
-#define NFC_CE (1 << 7)
-#define NFC_ONE_CYCLE (1 << 8)
-#define NFC_PPB_32 (0 << 9)
-#define NFC_PPB_64 (1 << 9)
-#define NFC_PPB_128 (2 << 9)
-#define NFC_PPB_256 (3 << 9)
-#define NFC_PPB_MASK (3 << 9)
-#define NFC_FULL_PAGE_INT (1 << 11)
-
-/* Bit Definitions: NFC_CONFIG2 */
-#define NFC_COMMAND (1 << 0)
-#define NFC_ADDRESS (1 << 1)
-#define NFC_INPUT (1 << 2)
-#define NFC_OUTPUT (1 << 3)
-#define NFC_ID (1 << 4)
-#define NFC_STATUS (1 << 5)
-#define NFC_CMD_FAIL (1 << 15)
-#define NFC_INT (1 << 15)
-
-/* Bit Definitions: NFC_WRPROT */
-#define NFC_WPC_LOCK_TIGHT (1 << 0)
-#define NFC_WPC_LOCK (1 << 1)
-#define NFC_WPC_UNLOCK (1 << 2)
-
-struct mpc5121_nfc_prv {
- struct mtd_info mtd;
- struct nand_chip chip;
- int irq;
- void __iomem *regs;
- struct clk *clk;
- uint column;
- int spareonly;
- int chipsel;
-};
-
-int mpc5121_nfc_chip = 0;
-
-static void mpc5121_nfc_done(struct mtd_info *mtd);
-
-/* Read NFC register */
-static inline u16 nfc_read(struct mtd_info *mtd, uint reg)
-{
- struct nand_chip *chip = mtd->priv;
- struct mpc5121_nfc_prv *prv = chip->priv;
-
- return in_be16(prv->regs + reg);
-}
-
-/* Write NFC register */
-static inline void nfc_write(struct mtd_info *mtd, uint reg, u16 val)
-{
- struct nand_chip *chip = mtd->priv;
- struct mpc5121_nfc_prv *prv = chip->priv;
-
- out_be16(prv->regs + reg, val);
-}
-
-/* Set bits in NFC register */
-static inline void nfc_set(struct mtd_info *mtd, uint reg, u16 bits)
-{
- nfc_write(mtd, reg, nfc_read(mtd, reg) | bits);
-}
-
-/* Clear bits in NFC register */
-static inline void nfc_clear(struct mtd_info *mtd, uint reg, u16 bits)
-{
- nfc_write(mtd, reg, nfc_read(mtd, reg) & ~bits);
-}
-
-/* Invoke address cycle */
-static inline void mpc5121_nfc_send_addr(struct mtd_info *mtd, u16 addr)
-{
- nfc_write(mtd, NFC_FLASH_ADDR, addr);
- nfc_write(mtd, NFC_CONFIG2, NFC_ADDRESS);
- mpc5121_nfc_done(mtd);
-}
-
-/* Invoke command cycle */
-static inline void mpc5121_nfc_send_cmd(struct mtd_info *mtd, u16 cmd)
-{
- nfc_write(mtd, NFC_FLASH_CMD, cmd);
- nfc_write(mtd, NFC_CONFIG2, NFC_COMMAND);
- mpc5121_nfc_done(mtd);
-}
-
-/* Send data from NFC buffers to NAND flash */
-static inline void mpc5121_nfc_send_prog_page(struct mtd_info *mtd)
-{
- nfc_clear(mtd, NFC_BUF_ADDR, NFC_RBA_MASK);
- nfc_write(mtd, NFC_CONFIG2, NFC_INPUT);
- mpc5121_nfc_done(mtd);
-}
-
-/* Receive data from NAND flash */
-static inline void mpc5121_nfc_send_read_page(struct mtd_info *mtd)
-{
- nfc_clear(mtd, NFC_BUF_ADDR, NFC_RBA_MASK);
- nfc_write(mtd, NFC_CONFIG2, NFC_OUTPUT);
- mpc5121_nfc_done(mtd);
-}
-
-/* Receive ID from NAND flash */
-static inline void mpc5121_nfc_send_read_id(struct mtd_info *mtd)
-{
- nfc_clear(mtd, NFC_BUF_ADDR, NFC_RBA_MASK);
- nfc_write(mtd, NFC_CONFIG2, NFC_ID);
- mpc5121_nfc_done(mtd);
-}
-
-/* Receive status from NAND flash */
-static inline void mpc5121_nfc_send_read_status(struct mtd_info *mtd)
-{
- nfc_clear(mtd, NFC_BUF_ADDR, NFC_RBA_MASK);
- nfc_write(mtd, NFC_CONFIG2, NFC_STATUS);
- mpc5121_nfc_done(mtd);
-}
-
-static void mpc5121_nfc_done(struct mtd_info *mtd)
-{
- int max_retries = NFC_TIMEOUT;
-
- while (1) {
- max_retries--;
- if (nfc_read(mtd, NFC_CONFIG2) & NFC_INT)
- break;
- udelay(1);
- }
-
- if (max_retries <= 0)
- printk(KERN_WARNING DRV_NAME
- ": Timeout while waiting for completion.\n");
-}
-
-/* Do address cycle(s) */
-static void mpc5121_nfc_addr_cycle(struct mtd_info *mtd, int column, int page)
-{
- struct nand_chip *chip = mtd->priv;
- u32 pagemask = chip->pagemask;
-
- if (column != -1) {
- mpc5121_nfc_send_addr(mtd, column);
- if (mtd->writesize > 512)
- mpc5121_nfc_send_addr(mtd, column >> 8);
- }
-
- if (page != -1) {
- do {
- mpc5121_nfc_send_addr(mtd, page & 0xFF);
- page >>= 8;
- pagemask >>= 8;
- } while (pagemask);
- }
-}
-
-/* Control chip select signals */
-
-/*
- * Selecting the active device:
- *
- * This is different than the linux version. Switching between chips
- * is done via board_nand_select_device(). The Linux select_chip
- * function used here in U-Boot has only 2 valid chip numbers:
- * 0 select
- * -1 deselect
- */
-
-/*
- * Implement it as a weak default, so that boards with a specific
- * chip-select routine can use their own function.
- */
-void __mpc5121_nfc_select_chip(struct mtd_info *mtd, int chip)
-{
- if (chip < 0) {
- nfc_clear(mtd, NFC_CONFIG1, NFC_CE);
- return;
- }
-
- nfc_clear(mtd, NFC_BUF_ADDR, NFC_ACTIVE_CS_MASK);
- nfc_set(mtd, NFC_BUF_ADDR, (chip << NFC_ACTIVE_CS_SHIFT) &
- NFC_ACTIVE_CS_MASK);
- nfc_set(mtd, NFC_CONFIG1, NFC_CE);
-}
-void mpc5121_nfc_select_chip(struct mtd_info *mtd, int chip)
- __attribute__((weak, alias("__mpc5121_nfc_select_chip")));
-
-void board_nand_select_device(struct nand_chip *nand, int chip)
-{
- /*
- * Only save this chip number in global variable here. This
- * will be used later in mpc5121_nfc_select_chip().
- */
- mpc5121_nfc_chip = chip;
-}
-
-/* Read NAND Ready/Busy signal */
-static int mpc5121_nfc_dev_ready(struct mtd_info *mtd)
-{
- /*
- * NFC handles ready/busy signal internally. Therefore, this function
- * always returns status as ready.
- */
- return 1;
-}
-
-/* Write command to NAND flash */
-static void mpc5121_nfc_command(struct mtd_info *mtd, unsigned command,
- int column, int page)
-{
- struct nand_chip *chip = mtd->priv;
- struct mpc5121_nfc_prv *prv = chip->priv;
-
- prv->column = (column >= 0) ? column : 0;
- prv->spareonly = 0;
-
- switch (command) {
- case NAND_CMD_PAGEPROG:
- mpc5121_nfc_send_prog_page(mtd);
- break;
- /*
- * NFC does not support sub-page reads and writes,
- * so emulate them using full page transfers.
- */
- case NAND_CMD_READ0:
- column = 0;
- break;
-
- case NAND_CMD_READ1:
- prv->column += 256;
- command = NAND_CMD_READ0;
- column = 0;
- break;
-
- case NAND_CMD_READOOB:
- prv->spareonly = 1;
- command = NAND_CMD_READ0;
- column = 0;
- break;
-
- case NAND_CMD_SEQIN:
- mpc5121_nfc_command(mtd, NAND_CMD_READ0, column, page);
- column = 0;
- break;
-
- case NAND_CMD_ERASE1:
- case NAND_CMD_ERASE2:
- case NAND_CMD_READID:
- case NAND_CMD_STATUS:
- case NAND_CMD_RESET:
- break;
-
- default:
- return;
- }
-
- mpc5121_nfc_send_cmd(mtd, command);
- mpc5121_nfc_addr_cycle(mtd, column, page);
-
- switch (command) {
- case NAND_CMD_READ0:
- if (mtd->writesize > 512)
- mpc5121_nfc_send_cmd(mtd, NAND_CMD_READSTART);
- mpc5121_nfc_send_read_page(mtd);
- break;
-
- case NAND_CMD_READID:
- mpc5121_nfc_send_read_id(mtd);
- break;
-
- case NAND_CMD_STATUS:
- mpc5121_nfc_send_read_status(mtd);
- if (chip->options & NAND_BUSWIDTH_16)
- prv->column = 1;
- else
- prv->column = 0;
- break;
- }
-}
-
-/* Copy data from/to NFC spare buffers. */
-static void mpc5121_nfc_copy_spare(struct mtd_info *mtd, uint offset,
- u8 * buffer, uint size, int wr)
-{
- struct nand_chip *nand = mtd->priv;
- struct mpc5121_nfc_prv *prv = nand->priv;
- uint o, s, sbsize, blksize;
-
- /*
- * NAND spare area is available through NFC spare buffers.
- * The NFC divides spare area into (page_size / 512) chunks.
- * Each chunk is placed into separate spare memory area, using
- * first (spare_size / num_of_chunks) bytes of the buffer.
- *
- * For NAND device in which the spare area is not divided fully
- * by the number of chunks, number of used bytes in each spare
- * buffer is rounded down to the nearest even number of bytes,
- * and all remaining bytes are added to the last used spare area.
- *
- * For more information read section 26.6.10 of MPC5121e
- * Microcontroller Reference Manual, Rev. 3.
- */
-
- /* Calculate number of valid bytes in each spare buffer */
- sbsize = (mtd->oobsize / (mtd->writesize / 512)) & ~1;
-
- while (size) {
- /* Calculate spare buffer number */
- s = offset / sbsize;
- if (s > NFC_SPARE_BUFFERS - 1)
- s = NFC_SPARE_BUFFERS - 1;
-
- /*
- * Calculate offset to requested data block in selected spare
- * buffer and its size.
- */
- o = offset - (s * sbsize);
- blksize = min(sbsize - o, size);
-
- if (wr)
- memcpy_toio(prv->regs + NFC_SPARE_AREA(s) + o,
- buffer, blksize);
- else
- memcpy_fromio(buffer,
- prv->regs + NFC_SPARE_AREA(s) + o,
- blksize);
-
- buffer += blksize;
- offset += blksize;
- size -= blksize;
- };
-}
-
-/* Copy data from/to NFC main and spare buffers */
-static void mpc5121_nfc_buf_copy(struct mtd_info *mtd, u_char * buf, int len,
- int wr)
-{
- struct nand_chip *chip = mtd->priv;
- struct mpc5121_nfc_prv *prv = chip->priv;
- uint c = prv->column;
- uint l;
-
- /* Handle spare area access */
- if (prv->spareonly || c >= mtd->writesize) {
- /* Calculate offset from beginning of spare area */
- if (c >= mtd->writesize)
- c -= mtd->writesize;
-
- prv->column += len;
- mpc5121_nfc_copy_spare(mtd, c, buf, len, wr);
- return;
- }
-
- /*
- * Handle main area access - limit copy length to prevent
- * crossing main/spare boundary.
- */
- l = min((uint) len, mtd->writesize - c);
- prv->column += l;
-
- if (wr)
- memcpy_toio(prv->regs + NFC_MAIN_AREA(0) + c, buf, l);
- else
- memcpy_fromio(buf, prv->regs + NFC_MAIN_AREA(0) + c, l);
-
- /* Handle crossing main/spare boundary */
- if (l != len) {
- buf += l;
- len -= l;
- mpc5121_nfc_buf_copy(mtd, buf, len, wr);
- }
-}
-
-/* Read data from NFC buffers */
-static void mpc5121_nfc_read_buf(struct mtd_info *mtd, u_char * buf, int len)
-{
- mpc5121_nfc_buf_copy(mtd, buf, len, 0);
-}
-
-/* Write data to NFC buffers */
-static void mpc5121_nfc_write_buf(struct mtd_info *mtd,
- const u_char * buf, int len)
-{
- mpc5121_nfc_buf_copy(mtd, (u_char *) buf, len, 1);
-}
-
-/* Compare buffer with NAND flash */
-static int mpc5121_nfc_verify_buf(struct mtd_info *mtd,
- const u_char * buf, int len)
-{
- u_char tmp[256];
- uint bsize;
-
- while (len) {
- bsize = min(len, 256);
- mpc5121_nfc_read_buf(mtd, tmp, bsize);
-
- if (memcmp(buf, tmp, bsize))
- return 1;
-
- buf += bsize;
- len -= bsize;
- }
-
- return 0;
-}
-
-/* Read byte from NFC buffers */
-static u8 mpc5121_nfc_read_byte(struct mtd_info *mtd)
-{
- u8 tmp;
-
- mpc5121_nfc_read_buf(mtd, &tmp, sizeof(tmp));
-
- return tmp;
-}
-
-/* Read word from NFC buffers */
-static u16 mpc5121_nfc_read_word(struct mtd_info *mtd)
-{
- u16 tmp;
-
- mpc5121_nfc_read_buf(mtd, (u_char *) & tmp, sizeof(tmp));
-
- return tmp;
-}
-
-/*
- * Read NFC configuration from Reset Config Word
- *
- * NFC is configured during reset in basis of information stored
- * in Reset Config Word. There is no other way to set NAND block
- * size, spare size and bus width.
- */
-static int mpc5121_nfc_read_hw_config(struct mtd_info *mtd)
-{
- immap_t *im = (immap_t *)CONFIG_SYS_IMMR;
- struct nand_chip *chip = mtd->priv;
- uint rcw_pagesize = 0;
- uint rcw_sparesize = 0;
- uint rcw_width;
- uint rcwh;
- uint romloc, ps;
-
- rcwh = in_be32(&(im->reset.rcwh));
-
- /* Bit 6: NFC bus width */
- rcw_width = ((rcwh >> 6) & 0x1) ? 2 : 1;
-
- /* Bit 7: NFC Page/Spare size */
- ps = (rcwh >> 7) & 0x1;
-
- /* Bits [22:21]: ROM Location */
- romloc = (rcwh >> 21) & 0x3;
-
- /* Decode RCW bits */
- switch ((ps << 2) | romloc) {
- case 0x00:
- case 0x01:
- rcw_pagesize = 512;
- rcw_sparesize = 16;
- break;
- case 0x02:
- case 0x03:
- rcw_pagesize = 4096;
- rcw_sparesize = 128;
- break;
- case 0x04:
- case 0x05:
- rcw_pagesize = 2048;
- rcw_sparesize = 64;
- break;
- case 0x06:
- case 0x07:
- rcw_pagesize = 4096;
- rcw_sparesize = 218;
- break;
- }
-
- mtd->writesize = rcw_pagesize;
- mtd->oobsize = rcw_sparesize;
- if (rcw_width == 2)
- chip->options |= NAND_BUSWIDTH_16;
-
- debug(KERN_NOTICE DRV_NAME ": Configured for "
- "%u-bit NAND, page size %u with %u spare.\n",
- rcw_width * 8, rcw_pagesize, rcw_sparesize);
- return 0;
-}
-
-int board_nand_init(struct nand_chip *chip)
-{
- struct mpc5121_nfc_prv *prv;
- struct mtd_info *mtd;
- int resettime = 0;
- int retval = 0;
- int rev;
- static int chip_nr = 0;
-
- /*
- * Check SoC revision. This driver supports only NFC
- * in MPC5121 revision 2.
- */
- rev = (mfspr(SPRN_SVR) >> 4) & 0xF;
- if (rev != 2) {
- printk(KERN_ERR DRV_NAME
- ": SoC revision %u is not supported!\n", rev);
- return -ENXIO;
- }
-
- prv = malloc(sizeof(*prv));
- if (!prv) {
- printk(KERN_ERR DRV_NAME ": Memory exhausted!\n");
- return -ENOMEM;
- }
-
- mtd = &nand_info[chip_nr++];
- mtd->priv = chip;
- chip->priv = prv;
-
- /* Read NFC configuration from Reset Config Word */
- retval = mpc5121_nfc_read_hw_config(mtd);
- if (retval) {
- printk(KERN_ERR DRV_NAME ": Unable to read NFC config!\n");
- return retval;
- }
-
- prv->regs = (void __iomem *)CONFIG_SYS_NAND_BASE;
- chip->dev_ready = mpc5121_nfc_dev_ready;
- chip->cmdfunc = mpc5121_nfc_command;
- chip->read_byte = mpc5121_nfc_read_byte;
- chip->read_word = mpc5121_nfc_read_word;
- chip->read_buf = mpc5121_nfc_read_buf;
- chip->write_buf = mpc5121_nfc_write_buf;
- chip->verify_buf = mpc5121_nfc_verify_buf;
- chip->select_chip = mpc5121_nfc_select_chip;
- chip->bbt_options = NAND_BBT_USE_FLASH;
- chip->ecc.mode = NAND_ECC_SOFT;
-
- /* Reset NAND Flash controller */
- nfc_set(mtd, NFC_CONFIG1, NFC_RESET);
- while (nfc_read(mtd, NFC_CONFIG1) & NFC_RESET) {
- if (resettime++ >= NFC_RESET_TIMEOUT) {
- printk(KERN_ERR DRV_NAME
- ": Timeout while resetting NFC!\n");
- retval = -EINVAL;
- goto error;
- }
-
- udelay(1);
- }
-
- /* Enable write to NFC memory */
- nfc_write(mtd, NFC_CONFIG, NFC_BLS_UNLOCKED);
-
- /* Enable write to all NAND pages */
- nfc_write(mtd, NFC_UNLOCKSTART_BLK0, 0x0000);
- nfc_write(mtd, NFC_UNLOCKEND_BLK0, 0xFFFF);
- nfc_write(mtd, NFC_WRPROT, NFC_WPC_UNLOCK);
-
- /*
- * Setup NFC:
- * - Big Endian transfers,
- * - Interrupt after full page read/write.
- */
- nfc_write(mtd, NFC_CONFIG1, NFC_BIG_ENDIAN | NFC_INT_MASK |
- NFC_FULL_PAGE_INT);
-
- /* Set spare area size */
- nfc_write(mtd, NFC_SPAS, mtd->oobsize >> 1);
-
- /* Detect NAND chips */
- if (nand_scan(mtd, 1)) {
- printk(KERN_ERR DRV_NAME ": NAND Flash not found !\n");
- retval = -ENXIO;
- goto error;
- }
-
- /* Set erase block size */
- switch (mtd->erasesize / mtd->writesize) {
- case 32:
- nfc_set(mtd, NFC_CONFIG1, NFC_PPB_32);
- break;
-
- case 64:
- nfc_set(mtd, NFC_CONFIG1, NFC_PPB_64);
- break;
-
- case 128:
- nfc_set(mtd, NFC_CONFIG1, NFC_PPB_128);
- break;
-
- case 256:
- nfc_set(mtd, NFC_CONFIG1, NFC_PPB_256);
- break;
-
- default:
- printk(KERN_ERR DRV_NAME ": Unsupported NAND flash!\n");
- retval = -ENXIO;
- goto error;
- }
-
- return 0;
-error:
- return retval;
-}
diff --git a/qemu/roms/u-boot/drivers/mtd/nand/mxc_nand.c b/qemu/roms/u-boot/drivers/mtd/nand/mxc_nand.c
deleted file mode 100644
index ed0ca3aca..000000000
--- a/qemu/roms/u-boot/drivers/mtd/nand/mxc_nand.c
+++ /dev/null
@@ -1,1342 +0,0 @@
-/*
- * Copyright 2004-2007 Freescale Semiconductor, Inc.
- * Copyright 2008 Sascha Hauer, kernel@pengutronix.de
- * Copyright 2009 Ilya Yanok, <yanok@emcraft.com>
- *
- * SPDX-License-Identifier: GPL-2.0+
- */
-
-#include <common.h>
-#include <nand.h>
-#include <linux/err.h>
-#include <asm/io.h>
-#if defined(CONFIG_MX25) || defined(CONFIG_MX27) || defined(CONFIG_MX35) || \
- defined(CONFIG_MX51) || defined(CONFIG_MX53)
-#include <asm/arch/imx-regs.h>
-#endif
-#include "mxc_nand.h"
-
-#define DRIVER_NAME "mxc_nand"
-
-struct mxc_nand_host {
- struct mtd_info mtd;
- struct nand_chip *nand;
-
- struct mxc_nand_regs __iomem *regs;
-#ifdef MXC_NFC_V3_2
- struct mxc_nand_ip_regs __iomem *ip_regs;
-#endif
- int spare_only;
- int status_request;
- int pagesize_2k;
- int clk_act;
- uint16_t col_addr;
- unsigned int page_addr;
-};
-
-static struct mxc_nand_host mxc_host;
-static struct mxc_nand_host *host = &mxc_host;
-
-/* Define delays in microsec for NAND device operations */
-#define TROP_US_DELAY 2000
-/* Macros to get byte and bit positions of ECC */
-#define COLPOS(x) ((x) >> 3)
-#define BITPOS(x) ((x) & 0xf)
-
-/* Define single bit Error positions in Main & Spare area */
-#define MAIN_SINGLEBIT_ERROR 0x4
-#define SPARE_SINGLEBIT_ERROR 0x1
-
-/* OOB placement block for use with hardware ecc generation */
-#if defined(MXC_NFC_V1)
-#ifndef CONFIG_SYS_NAND_LARGEPAGE
-static struct nand_ecclayout nand_hw_eccoob = {
- .eccbytes = 5,
- .eccpos = {6, 7, 8, 9, 10},
- .oobfree = { {0, 5}, {11, 5}, }
-};
-#else
-static struct nand_ecclayout nand_hw_eccoob2k = {
- .eccbytes = 20,
- .eccpos = {
- 6, 7, 8, 9, 10,
- 22, 23, 24, 25, 26,
- 38, 39, 40, 41, 42,
- 54, 55, 56, 57, 58,
- },
- .oobfree = { {2, 4}, {11, 11}, {27, 11}, {43, 11}, {59, 5} },
-};
-#endif
-#elif defined(MXC_NFC_V2_1) || defined(MXC_NFC_V3_2)
-#ifndef CONFIG_SYS_NAND_LARGEPAGE
-static struct nand_ecclayout nand_hw_eccoob = {
- .eccbytes = 9,
- .eccpos = {7, 8, 9, 10, 11, 12, 13, 14, 15},
- .oobfree = { {2, 5} }
-};
-#else
-static struct nand_ecclayout nand_hw_eccoob2k = {
- .eccbytes = 36,
- .eccpos = {
- 7, 8, 9, 10, 11, 12, 13, 14, 15,
- 23, 24, 25, 26, 27, 28, 29, 30, 31,
- 39, 40, 41, 42, 43, 44, 45, 46, 47,
- 55, 56, 57, 58, 59, 60, 61, 62, 63,
- },
- .oobfree = { {2, 5}, {16, 7}, {32, 7}, {48, 7} },
-};
-#endif
-#endif
-
-static int is_16bit_nand(void)
-{
-#if defined(CONFIG_SYS_NAND_BUSWIDTH_16BIT)
- return 1;
-#else
- return 0;
-#endif
-}
-
-static uint32_t *mxc_nand_memcpy32(uint32_t *dest, uint32_t *source, size_t size)
-{
- uint32_t *d = dest;
-
- size >>= 2;
- while (size--)
- __raw_writel(__raw_readl(source++), d++);
- return dest;
-}
-
-/*
- * This function polls the NANDFC to wait for the basic operation to
- * complete by checking the INT bit.
- */
-static void wait_op_done(struct mxc_nand_host *host, int max_retries,
- uint16_t param)
-{
- uint32_t tmp;
-
- while (max_retries-- > 0) {
-#if defined(MXC_NFC_V1) || defined(MXC_NFC_V2_1)
- tmp = readnfc(&host->regs->config2);
- if (tmp & NFC_V1_V2_CONFIG2_INT) {
- tmp &= ~NFC_V1_V2_CONFIG2_INT;
- writenfc(tmp, &host->regs->config2);
-#elif defined(MXC_NFC_V3_2)
- tmp = readnfc(&host->ip_regs->ipc);
- if (tmp & NFC_V3_IPC_INT) {
- tmp &= ~NFC_V3_IPC_INT;
- writenfc(tmp, &host->ip_regs->ipc);
-#endif
- break;
- }
- udelay(1);
- }
- if (max_retries < 0) {
- MTDDEBUG(MTD_DEBUG_LEVEL0, "%s(%d): INT not set\n",
- __func__, param);
- }
-}
-
-/*
- * This function issues the specified command to the NAND device and
- * waits for completion.
- */
-static void send_cmd(struct mxc_nand_host *host, uint16_t cmd)
-{
- MTDDEBUG(MTD_DEBUG_LEVEL3, "send_cmd(host, 0x%x)\n", cmd);
-
- writenfc(cmd, &host->regs->flash_cmd);
- writenfc(NFC_CMD, &host->regs->operation);
-
- /* Wait for operation to complete */
- wait_op_done(host, TROP_US_DELAY, cmd);
-}
-
-/*
- * This function sends an address (or partial address) to the
- * NAND device. The address is used to select the source/destination for
- * a NAND command.
- */
-static void send_addr(struct mxc_nand_host *host, uint16_t addr)
-{
- MTDDEBUG(MTD_DEBUG_LEVEL3, "send_addr(host, 0x%x)\n", addr);
-
- writenfc(addr, &host->regs->flash_addr);
- writenfc(NFC_ADDR, &host->regs->operation);
-
- /* Wait for operation to complete */
- wait_op_done(host, TROP_US_DELAY, addr);
-}
-
-/*
- * This function requests the NANDFC to initiate the transfer
- * of data currently in the NANDFC RAM buffer to the NAND device.
- */
-static void send_prog_page(struct mxc_nand_host *host, uint8_t buf_id,
- int spare_only)
-{
- if (spare_only)
- MTDDEBUG(MTD_DEBUG_LEVEL1, "send_prog_page (%d)\n", spare_only);
-
- if (is_mxc_nfc_21() || is_mxc_nfc_32()) {
- int i;
- /*
- * The controller copies the 64 bytes of spare data from
- * the first 16 bytes of each of the 4 64 byte spare buffers.
- * Copy the contiguous data starting in spare_area[0] to
- * the four spare area buffers.
- */
- for (i = 1; i < 4; i++) {
- void __iomem *src = &host->regs->spare_area[0][i * 16];
- void __iomem *dst = &host->regs->spare_area[i][0];
-
- mxc_nand_memcpy32(dst, src, 16);
- }
- }
-
-#if defined(MXC_NFC_V1) || defined(MXC_NFC_V2_1)
- writenfc(buf_id, &host->regs->buf_addr);
-#elif defined(MXC_NFC_V3_2)
- uint32_t tmp = readnfc(&host->regs->config1);
- tmp &= ~NFC_V3_CONFIG1_RBA_MASK;
- tmp |= NFC_V3_CONFIG1_RBA(buf_id);
- writenfc(tmp, &host->regs->config1);
-#endif
-
- /* Configure spare or page+spare access */
- if (!host->pagesize_2k) {
- uint32_t config1 = readnfc(&host->regs->config1);
- if (spare_only)
- config1 |= NFC_CONFIG1_SP_EN;
- else
- config1 &= ~NFC_CONFIG1_SP_EN;
- writenfc(config1, &host->regs->config1);
- }
-
- writenfc(NFC_INPUT, &host->regs->operation);
-
- /* Wait for operation to complete */
- wait_op_done(host, TROP_US_DELAY, spare_only);
-}
-
-/*
- * Requests NANDFC to initiate the transfer of data from the
- * NAND device into in the NANDFC ram buffer.
- */
-static void send_read_page(struct mxc_nand_host *host, uint8_t buf_id,
- int spare_only)
-{
- MTDDEBUG(MTD_DEBUG_LEVEL3, "send_read_page (%d)\n", spare_only);
-
-#if defined(MXC_NFC_V1) || defined(MXC_NFC_V2_1)
- writenfc(buf_id, &host->regs->buf_addr);
-#elif defined(MXC_NFC_V3_2)
- uint32_t tmp = readnfc(&host->regs->config1);
- tmp &= ~NFC_V3_CONFIG1_RBA_MASK;
- tmp |= NFC_V3_CONFIG1_RBA(buf_id);
- writenfc(tmp, &host->regs->config1);
-#endif
-
- /* Configure spare or page+spare access */
- if (!host->pagesize_2k) {
- uint32_t config1 = readnfc(&host->regs->config1);
- if (spare_only)
- config1 |= NFC_CONFIG1_SP_EN;
- else
- config1 &= ~NFC_CONFIG1_SP_EN;
- writenfc(config1, &host->regs->config1);
- }
-
- writenfc(NFC_OUTPUT, &host->regs->operation);
-
- /* Wait for operation to complete */
- wait_op_done(host, TROP_US_DELAY, spare_only);
-
- if (is_mxc_nfc_21() || is_mxc_nfc_32()) {
- int i;
-
- /*
- * The controller copies the 64 bytes of spare data to
- * the first 16 bytes of each of the 4 spare buffers.
- * Make the data contiguous starting in spare_area[0].
- */
- for (i = 1; i < 4; i++) {
- void __iomem *src = &host->regs->spare_area[i][0];
- void __iomem *dst = &host->regs->spare_area[0][i * 16];
-
- mxc_nand_memcpy32(dst, src, 16);
- }
- }
-}
-
-/* Request the NANDFC to perform a read of the NAND device ID. */
-static void send_read_id(struct mxc_nand_host *host)
-{
- uint32_t tmp;
-
-#if defined(MXC_NFC_V1) || defined(MXC_NFC_V2_1)
- /* NANDFC buffer 0 is used for device ID output */
- writenfc(0x0, &host->regs->buf_addr);
-#elif defined(MXC_NFC_V3_2)
- tmp = readnfc(&host->regs->config1);
- tmp &= ~NFC_V3_CONFIG1_RBA_MASK;
- writenfc(tmp, &host->regs->config1);
-#endif
-
- /* Read ID into main buffer */
- tmp = readnfc(&host->regs->config1);
- tmp &= ~NFC_CONFIG1_SP_EN;
- writenfc(tmp, &host->regs->config1);
-
- writenfc(NFC_ID, &host->regs->operation);
-
- /* Wait for operation to complete */
- wait_op_done(host, TROP_US_DELAY, 0);
-}
-
-/*
- * This function requests the NANDFC to perform a read of the
- * NAND device status and returns the current status.
- */
-static uint16_t get_dev_status(struct mxc_nand_host *host)
-{
-#if defined(MXC_NFC_V1) || defined(MXC_NFC_V2_1)
- void __iomem *main_buf = host->regs->main_area[1];
- uint32_t store;
-#endif
- uint32_t ret, tmp;
- /* Issue status request to NAND device */
-
-#if defined(MXC_NFC_V1) || defined(MXC_NFC_V2_1)
- /* store the main area1 first word, later do recovery */
- store = readl(main_buf);
- /* NANDFC buffer 1 is used for device status */
- writenfc(1, &host->regs->buf_addr);
-#endif
-
- /* Read status into main buffer */
- tmp = readnfc(&host->regs->config1);
- tmp &= ~NFC_CONFIG1_SP_EN;
- writenfc(tmp, &host->regs->config1);
-
- writenfc(NFC_STATUS, &host->regs->operation);
-
- /* Wait for operation to complete */
- wait_op_done(host, TROP_US_DELAY, 0);
-
-#if defined(MXC_NFC_V1) || defined(MXC_NFC_V2_1)
- /*
- * Status is placed in first word of main buffer
- * get status, then recovery area 1 data
- */
- ret = readw(main_buf);
- writel(store, main_buf);
-#elif defined(MXC_NFC_V3_2)
- ret = readnfc(&host->regs->config1) >> 16;
-#endif
-
- return ret;
-}
-
-/* This function is used by upper layer to checks if device is ready */
-static int mxc_nand_dev_ready(struct mtd_info *mtd)
-{
- /*
- * NFC handles R/B internally. Therefore, this function
- * always returns status as ready.
- */
- return 1;
-}
-
-static void _mxc_nand_enable_hwecc(struct mtd_info *mtd, int on)
-{
- struct nand_chip *nand_chip = mtd->priv;
- struct mxc_nand_host *host = nand_chip->priv;
-#if defined(MXC_NFC_V1) || defined(MXC_NFC_V2_1)
- uint16_t tmp = readnfc(&host->regs->config1);
-
- if (on)
- tmp |= NFC_V1_V2_CONFIG1_ECC_EN;
- else
- tmp &= ~NFC_V1_V2_CONFIG1_ECC_EN;
- writenfc(tmp, &host->regs->config1);
-#elif defined(MXC_NFC_V3_2)
- uint32_t tmp = readnfc(&host->ip_regs->config2);
-
- if (on)
- tmp |= NFC_V3_CONFIG2_ECC_EN;
- else
- tmp &= ~NFC_V3_CONFIG2_ECC_EN;
- writenfc(tmp, &host->ip_regs->config2);
-#endif
-}
-
-#ifdef CONFIG_MXC_NAND_HWECC
-static void mxc_nand_enable_hwecc(struct mtd_info *mtd, int mode)
-{
- /*
- * If HW ECC is enabled, we turn it on during init. There is
- * no need to enable again here.
- */
-}
-
-#if defined(MXC_NFC_V2_1) || defined(MXC_NFC_V3_2)
-static int mxc_nand_read_oob_syndrome(struct mtd_info *mtd,
- struct nand_chip *chip,
- int page)
-{
- struct mxc_nand_host *host = chip->priv;
- uint8_t *buf = chip->oob_poi;
- int length = mtd->oobsize;
- int eccpitch = chip->ecc.bytes + chip->ecc.prepad + chip->ecc.postpad;
- uint8_t *bufpoi = buf;
- int i, toread;
-
- MTDDEBUG(MTD_DEBUG_LEVEL0,
- "%s: Reading OOB area of page %u to oob %p\n",
- __func__, page, buf);
-
- chip->cmdfunc(mtd, NAND_CMD_READOOB, mtd->writesize, page);
- for (i = 0; i < chip->ecc.steps; i++) {
- toread = min_t(int, length, chip->ecc.prepad);
- if (toread) {
- chip->read_buf(mtd, bufpoi, toread);
- bufpoi += toread;
- length -= toread;
- }
- bufpoi += chip->ecc.bytes;
- host->col_addr += chip->ecc.bytes;
- length -= chip->ecc.bytes;
-
- toread = min_t(int, length, chip->ecc.postpad);
- if (toread) {
- chip->read_buf(mtd, bufpoi, toread);
- bufpoi += toread;
- length -= toread;
- }
- }
- if (length > 0)
- chip->read_buf(mtd, bufpoi, length);
-
- _mxc_nand_enable_hwecc(mtd, 0);
- chip->cmdfunc(mtd, NAND_CMD_READOOB,
- mtd->writesize + chip->ecc.prepad, page);
- bufpoi = buf + chip->ecc.prepad;
- length = mtd->oobsize - chip->ecc.prepad;
- for (i = 0; i < chip->ecc.steps; i++) {
- toread = min_t(int, length, chip->ecc.bytes);
- chip->read_buf(mtd, bufpoi, toread);
- bufpoi += eccpitch;
- length -= eccpitch;
- host->col_addr += chip->ecc.postpad + chip->ecc.prepad;
- }
- _mxc_nand_enable_hwecc(mtd, 1);
- return 1;
-}
-
-static int mxc_nand_read_page_raw_syndrome(struct mtd_info *mtd,
- struct nand_chip *chip,
- uint8_t *buf,
- int oob_required,
- int page)
-{
- struct mxc_nand_host *host = chip->priv;
- int eccsize = chip->ecc.size;
- int eccbytes = chip->ecc.bytes;
- int eccpitch = eccbytes + chip->ecc.prepad + chip->ecc.postpad;
- uint8_t *oob = chip->oob_poi;
- int steps, size;
- int n;
-
- _mxc_nand_enable_hwecc(mtd, 0);
- chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page);
-
- for (n = 0, steps = chip->ecc.steps; steps > 0; n++, steps--) {
- host->col_addr = n * eccsize;
- chip->read_buf(mtd, buf, eccsize);
- buf += eccsize;
-
- host->col_addr = mtd->writesize + n * eccpitch;
- if (chip->ecc.prepad) {
- chip->read_buf(mtd, oob, chip->ecc.prepad);
- oob += chip->ecc.prepad;
- }
-
- chip->read_buf(mtd, oob, eccbytes);
- oob += eccbytes;
-
- if (chip->ecc.postpad) {
- chip->read_buf(mtd, oob, chip->ecc.postpad);
- oob += chip->ecc.postpad;
- }
- }
-
- size = mtd->oobsize - (oob - chip->oob_poi);
- if (size)
- chip->read_buf(mtd, oob, size);
- _mxc_nand_enable_hwecc(mtd, 1);
-
- return 0;
-}
-
-static int mxc_nand_read_page_syndrome(struct mtd_info *mtd,
- struct nand_chip *chip,
- uint8_t *buf,
- int oob_required,
- int page)
-{
- struct mxc_nand_host *host = chip->priv;
- int n, eccsize = chip->ecc.size;
- int eccbytes = chip->ecc.bytes;
- int eccpitch = eccbytes + chip->ecc.prepad + chip->ecc.postpad;
- int eccsteps = chip->ecc.steps;
- uint8_t *p = buf;
- uint8_t *oob = chip->oob_poi;
-
- MTDDEBUG(MTD_DEBUG_LEVEL1, "Reading page %u to buf %p oob %p\n",
- page, buf, oob);
-
- /* first read the data area and the available portion of OOB */
- for (n = 0; eccsteps; n++, eccsteps--, p += eccsize) {
- int stat;
-
- host->col_addr = n * eccsize;
-
- chip->read_buf(mtd, p, eccsize);
-
- host->col_addr = mtd->writesize + n * eccpitch;
-
- if (chip->ecc.prepad) {
- chip->read_buf(mtd, oob, chip->ecc.prepad);
- oob += chip->ecc.prepad;
- }
-
- stat = chip->ecc.correct(mtd, p, oob, NULL);
-
- if (stat < 0)
- mtd->ecc_stats.failed++;
- else
- mtd->ecc_stats.corrected += stat;
- oob += eccbytes;
-
- if (chip->ecc.postpad) {
- chip->read_buf(mtd, oob, chip->ecc.postpad);
- oob += chip->ecc.postpad;
- }
- }
-
- /* Calculate remaining oob bytes */
- n = mtd->oobsize - (oob - chip->oob_poi);
- if (n)
- chip->read_buf(mtd, oob, n);
-
- /* Then switch ECC off and read the OOB area to get the ECC code */
- _mxc_nand_enable_hwecc(mtd, 0);
- chip->cmdfunc(mtd, NAND_CMD_READOOB, mtd->writesize, page);
- eccsteps = chip->ecc.steps;
- oob = chip->oob_poi + chip->ecc.prepad;
- for (n = 0; eccsteps; n++, eccsteps--, p += eccsize) {
- host->col_addr = mtd->writesize +
- n * eccpitch +
- chip->ecc.prepad;
- chip->read_buf(mtd, oob, eccbytes);
- oob += eccbytes + chip->ecc.postpad;
- }
- _mxc_nand_enable_hwecc(mtd, 1);
- return 0;
-}
-
-static int mxc_nand_write_oob_syndrome(struct mtd_info *mtd,
- struct nand_chip *chip, int page)
-{
- struct mxc_nand_host *host = chip->priv;
- int eccpitch = chip->ecc.bytes + chip->ecc.prepad + chip->ecc.postpad;
- int length = mtd->oobsize;
- int i, len, status, steps = chip->ecc.steps;
- const uint8_t *bufpoi = chip->oob_poi;
-
- chip->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize, page);
- for (i = 0; i < steps; i++) {
- len = min_t(int, length, eccpitch);
-
- chip->write_buf(mtd, bufpoi, len);
- bufpoi += len;
- length -= len;
- host->col_addr += chip->ecc.prepad + chip->ecc.postpad;
- }
- if (length > 0)
- chip->write_buf(mtd, bufpoi, length);
-
- chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
- status = chip->waitfunc(mtd, chip);
- return status & NAND_STATUS_FAIL ? -EIO : 0;
-}
-
-static int mxc_nand_write_page_raw_syndrome(struct mtd_info *mtd,
- struct nand_chip *chip,
- const uint8_t *buf,
- int oob_required)
-{
- struct mxc_nand_host *host = chip->priv;
- int eccsize = chip->ecc.size;
- int eccbytes = chip->ecc.bytes;
- int eccpitch = eccbytes + chip->ecc.prepad + chip->ecc.postpad;
- uint8_t *oob = chip->oob_poi;
- int steps, size;
- int n;
-
- for (n = 0, steps = chip->ecc.steps; steps > 0; n++, steps--) {
- host->col_addr = n * eccsize;
- chip->write_buf(mtd, buf, eccsize);
- buf += eccsize;
-
- host->col_addr = mtd->writesize + n * eccpitch;
-
- if (chip->ecc.prepad) {
- chip->write_buf(mtd, oob, chip->ecc.prepad);
- oob += chip->ecc.prepad;
- }
-
- host->col_addr += eccbytes;
- oob += eccbytes;
-
- if (chip->ecc.postpad) {
- chip->write_buf(mtd, oob, chip->ecc.postpad);
- oob += chip->ecc.postpad;
- }
- }
-
- size = mtd->oobsize - (oob - chip->oob_poi);
- if (size)
- chip->write_buf(mtd, oob, size);
- return 0;
-}
-
-static int mxc_nand_write_page_syndrome(struct mtd_info *mtd,
- struct nand_chip *chip,
- const uint8_t *buf,
- int oob_required)
-{
- struct mxc_nand_host *host = chip->priv;
- int i, n, eccsize = chip->ecc.size;
- int eccbytes = chip->ecc.bytes;
- int eccpitch = eccbytes + chip->ecc.prepad + chip->ecc.postpad;
- int eccsteps = chip->ecc.steps;
- const uint8_t *p = buf;
- uint8_t *oob = chip->oob_poi;
-
- chip->ecc.hwctl(mtd, NAND_ECC_WRITE);
-
- for (i = n = 0;
- eccsteps;
- n++, eccsteps--, i += eccbytes, p += eccsize) {
- host->col_addr = n * eccsize;
-
- chip->write_buf(mtd, p, eccsize);
-
- host->col_addr = mtd->writesize + n * eccpitch;
-
- if (chip->ecc.prepad) {
- chip->write_buf(mtd, oob, chip->ecc.prepad);
- oob += chip->ecc.prepad;
- }
-
- chip->write_buf(mtd, oob, eccbytes);
- oob += eccbytes;
-
- if (chip->ecc.postpad) {
- chip->write_buf(mtd, oob, chip->ecc.postpad);
- oob += chip->ecc.postpad;
- }
- }
-
- /* Calculate remaining oob bytes */
- i = mtd->oobsize - (oob - chip->oob_poi);
- if (i)
- chip->write_buf(mtd, oob, i);
- return 0;
-}
-
-static int mxc_nand_correct_data(struct mtd_info *mtd, u_char *dat,
- u_char *read_ecc, u_char *calc_ecc)
-{
- struct nand_chip *nand_chip = mtd->priv;
- struct mxc_nand_host *host = nand_chip->priv;
- uint32_t ecc_status = readl(&host->regs->ecc_status_result);
- int subpages = mtd->writesize / nand_chip->subpagesize;
- int pg2blk_shift = nand_chip->phys_erase_shift -
- nand_chip->page_shift;
-
- do {
- if ((ecc_status & 0xf) > 4) {
- static int last_bad = -1;
-
- if (last_bad != host->page_addr >> pg2blk_shift) {
- last_bad = host->page_addr >> pg2blk_shift;
- printk(KERN_DEBUG
- "MXC_NAND: HWECC uncorrectable ECC error"
- " in block %u page %u subpage %d\n",
- last_bad, host->page_addr,
- mtd->writesize / nand_chip->subpagesize
- - subpages);
- }
- return -1;
- }
- ecc_status >>= 4;
- subpages--;
- } while (subpages > 0);
-
- return 0;
-}
-#else
-#define mxc_nand_read_page_syndrome NULL
-#define mxc_nand_read_page_raw_syndrome NULL
-#define mxc_nand_read_oob_syndrome NULL
-#define mxc_nand_write_page_syndrome NULL
-#define mxc_nand_write_page_raw_syndrome NULL
-#define mxc_nand_write_oob_syndrome NULL
-
-static int mxc_nand_correct_data(struct mtd_info *mtd, u_char *dat,
- u_char *read_ecc, u_char *calc_ecc)
-{
- struct nand_chip *nand_chip = mtd->priv;
- struct mxc_nand_host *host = nand_chip->priv;
-
- /*
- * 1-Bit errors are automatically corrected in HW. No need for
- * additional correction. 2-Bit errors cannot be corrected by
- * HW ECC, so we need to return failure
- */
- uint16_t ecc_status = readnfc(&host->regs->ecc_status_result);
-
- if (((ecc_status & 0x3) == 2) || ((ecc_status >> 2) == 2)) {
- MTDDEBUG(MTD_DEBUG_LEVEL0,
- "MXC_NAND: HWECC uncorrectable 2-bit ECC error\n");
- return -1;
- }
-
- return 0;
-}
-#endif
-
-static int mxc_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
- u_char *ecc_code)
-{
- return 0;
-}
-#endif
-
-static u_char mxc_nand_read_byte(struct mtd_info *mtd)
-{
- struct nand_chip *nand_chip = mtd->priv;
- struct mxc_nand_host *host = nand_chip->priv;
- uint8_t ret = 0;
- uint16_t col;
- uint16_t __iomem *main_buf =
- (uint16_t __iomem *)host->regs->main_area[0];
- uint16_t __iomem *spare_buf =
- (uint16_t __iomem *)host->regs->spare_area[0];
- union {
- uint16_t word;
- uint8_t bytes[2];
- } nfc_word;
-
- /* Check for status request */
- if (host->status_request)
- return get_dev_status(host) & 0xFF;
-
- /* Get column for 16-bit access */
- col = host->col_addr >> 1;
-
- /* If we are accessing the spare region */
- if (host->spare_only)
- nfc_word.word = readw(&spare_buf[col]);
- else
- nfc_word.word = readw(&main_buf[col]);
-
- /* Pick upper/lower byte of word from RAM buffer */
- ret = nfc_word.bytes[host->col_addr & 0x1];
-
- /* Update saved column address */
- if (nand_chip->options & NAND_BUSWIDTH_16)
- host->col_addr += 2;
- else
- host->col_addr++;
-
- return ret;
-}
-
-static uint16_t mxc_nand_read_word(struct mtd_info *mtd)
-{
- struct nand_chip *nand_chip = mtd->priv;
- struct mxc_nand_host *host = nand_chip->priv;
- uint16_t col, ret;
- uint16_t __iomem *p;
-
- MTDDEBUG(MTD_DEBUG_LEVEL3,
- "mxc_nand_read_word(col = %d)\n", host->col_addr);
-
- col = host->col_addr;
- /* Adjust saved column address */
- if (col < mtd->writesize && host->spare_only)
- col += mtd->writesize;
-
- if (col < mtd->writesize) {
- p = (uint16_t __iomem *)(host->regs->main_area[0] +
- (col >> 1));
- } else {
- p = (uint16_t __iomem *)(host->regs->spare_area[0] +
- ((col - mtd->writesize) >> 1));
- }
-
- if (col & 1) {
- union {
- uint16_t word;
- uint8_t bytes[2];
- } nfc_word[3];
-
- nfc_word[0].word = readw(p);
- nfc_word[1].word = readw(p + 1);
-
- nfc_word[2].bytes[0] = nfc_word[0].bytes[1];
- nfc_word[2].bytes[1] = nfc_word[1].bytes[0];
-
- ret = nfc_word[2].word;
- } else {
- ret = readw(p);
- }
-
- /* Update saved column address */
- host->col_addr = col + 2;
-
- return ret;
-}
-
-/*
- * Write data of length len to buffer buf. The data to be
- * written on NAND Flash is first copied to RAMbuffer. After the Data Input
- * Operation by the NFC, the data is written to NAND Flash
- */
-static void mxc_nand_write_buf(struct mtd_info *mtd,
- const u_char *buf, int len)
-{
- struct nand_chip *nand_chip = mtd->priv;
- struct mxc_nand_host *host = nand_chip->priv;
- int n, col, i = 0;
-
- MTDDEBUG(MTD_DEBUG_LEVEL3,
- "mxc_nand_write_buf(col = %d, len = %d)\n", host->col_addr,
- len);
-
- col = host->col_addr;
-
- /* Adjust saved column address */
- if (col < mtd->writesize && host->spare_only)
- col += mtd->writesize;
-
- n = mtd->writesize + mtd->oobsize - col;
- n = min(len, n);
-
- MTDDEBUG(MTD_DEBUG_LEVEL3,
- "%s:%d: col = %d, n = %d\n", __func__, __LINE__, col, n);
-
- while (n > 0) {
- void __iomem *p;
-
- if (col < mtd->writesize) {
- p = host->regs->main_area[0] + (col & ~3);
- } else {
- p = host->regs->spare_area[0] -
- mtd->writesize + (col & ~3);
- }
-
- MTDDEBUG(MTD_DEBUG_LEVEL3, "%s:%d: p = %p\n", __func__,
- __LINE__, p);
-
- if (((col | (unsigned long)&buf[i]) & 3) || n < 4) {
- union {
- uint32_t word;
- uint8_t bytes[4];
- } nfc_word;
-
- nfc_word.word = readl(p);
- nfc_word.bytes[col & 3] = buf[i++];
- n--;
- col++;
-
- writel(nfc_word.word, p);
- } else {
- int m = mtd->writesize - col;
-
- if (col >= mtd->writesize)
- m += mtd->oobsize;
-
- m = min(n, m) & ~3;
-
- MTDDEBUG(MTD_DEBUG_LEVEL3,
- "%s:%d: n = %d, m = %d, i = %d, col = %d\n",
- __func__, __LINE__, n, m, i, col);
-
- mxc_nand_memcpy32(p, (uint32_t *)&buf[i], m);
- col += m;
- i += m;
- n -= m;
- }
- }
- /* Update saved column address */
- host->col_addr = col;
-}
-
-/*
- * Read the data buffer from the NAND Flash. To read the data from NAND
- * Flash first the data output cycle is initiated by the NFC, which copies
- * the data to RAMbuffer. This data of length len is then copied to buffer buf.
- */
-static void mxc_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
-{
- struct nand_chip *nand_chip = mtd->priv;
- struct mxc_nand_host *host = nand_chip->priv;
- int n, col, i = 0;
-
- MTDDEBUG(MTD_DEBUG_LEVEL3,
- "mxc_nand_read_buf(col = %d, len = %d)\n", host->col_addr, len);
-
- col = host->col_addr;
-
- /* Adjust saved column address */
- if (col < mtd->writesize && host->spare_only)
- col += mtd->writesize;
-
- n = mtd->writesize + mtd->oobsize - col;
- n = min(len, n);
-
- while (n > 0) {
- void __iomem *p;
-
- if (col < mtd->writesize) {
- p = host->regs->main_area[0] + (col & ~3);
- } else {
- p = host->regs->spare_area[0] -
- mtd->writesize + (col & ~3);
- }
-
- if (((col | (int)&buf[i]) & 3) || n < 4) {
- union {
- uint32_t word;
- uint8_t bytes[4];
- } nfc_word;
-
- nfc_word.word = readl(p);
- buf[i++] = nfc_word.bytes[col & 3];
- n--;
- col++;
- } else {
- int m = mtd->writesize - col;
-
- if (col >= mtd->writesize)
- m += mtd->oobsize;
-
- m = min(n, m) & ~3;
- mxc_nand_memcpy32((uint32_t *)&buf[i], p, m);
-
- col += m;
- i += m;
- n -= m;
- }
- }
- /* Update saved column address */
- host->col_addr = col;
-}
-
-/*
- * Used by the upper layer to verify the data in NAND Flash
- * with the data in the buf.
- */
-static int mxc_nand_verify_buf(struct mtd_info *mtd,
- const u_char *buf, int len)
-{
- u_char tmp[256];
- uint bsize;
-
- while (len) {
- bsize = min(len, 256);
- mxc_nand_read_buf(mtd, tmp, bsize);
-
- if (memcmp(buf, tmp, bsize))
- return 1;
-
- buf += bsize;
- len -= bsize;
- }
-
- return 0;
-}
-
-/*
- * This function is used by upper layer for select and
- * deselect of the NAND chip
- */
-static void mxc_nand_select_chip(struct mtd_info *mtd, int chip)
-{
- struct nand_chip *nand_chip = mtd->priv;
- struct mxc_nand_host *host = nand_chip->priv;
-
- switch (chip) {
- case -1:
- /* TODO: Disable the NFC clock */
- if (host->clk_act)
- host->clk_act = 0;
- break;
- case 0:
- /* TODO: Enable the NFC clock */
- if (!host->clk_act)
- host->clk_act = 1;
- break;
-
- default:
- break;
- }
-}
-
-/*
- * Used by the upper layer to write command to NAND Flash for
- * different operations to be carried out on NAND Flash
- */
-void mxc_nand_command(struct mtd_info *mtd, unsigned command,
- int column, int page_addr)
-{
- struct nand_chip *nand_chip = mtd->priv;
- struct mxc_nand_host *host = nand_chip->priv;
-
- MTDDEBUG(MTD_DEBUG_LEVEL3,
- "mxc_nand_command (cmd = 0x%x, col = 0x%x, page = 0x%x)\n",
- command, column, page_addr);
-
- /* Reset command state information */
- host->status_request = false;
-
- /* Command pre-processing step */
- switch (command) {
-
- case NAND_CMD_STATUS:
- host->col_addr = 0;
- host->status_request = true;
- break;
-
- case NAND_CMD_READ0:
- host->page_addr = page_addr;
- host->col_addr = column;
- host->spare_only = false;
- break;
-
- case NAND_CMD_READOOB:
- host->col_addr = column;
- host->spare_only = true;
- if (host->pagesize_2k)
- command = NAND_CMD_READ0; /* only READ0 is valid */
- break;
-
- case NAND_CMD_SEQIN:
- if (column >= mtd->writesize) {
- /*
- * before sending SEQIN command for partial write,
- * we need read one page out. FSL NFC does not support
- * partial write. It always sends out 512+ecc+512+ecc
- * for large page nand flash. But for small page nand
- * flash, it does support SPARE ONLY operation.
- */
- if (host->pagesize_2k) {
- /* call ourself to read a page */
- mxc_nand_command(mtd, NAND_CMD_READ0, 0,
- page_addr);
- }
-
- host->col_addr = column - mtd->writesize;
- host->spare_only = true;
-
- /* Set program pointer to spare region */
- if (!host->pagesize_2k)
- send_cmd(host, NAND_CMD_READOOB);
- } else {
- host->spare_only = false;
- host->col_addr = column;
-
- /* Set program pointer to page start */
- if (!host->pagesize_2k)
- send_cmd(host, NAND_CMD_READ0);
- }
- break;
-
- case NAND_CMD_PAGEPROG:
- send_prog_page(host, 0, host->spare_only);
-
- if (host->pagesize_2k && is_mxc_nfc_1()) {
- /* data in 4 areas */
- send_prog_page(host, 1, host->spare_only);
- send_prog_page(host, 2, host->spare_only);
- send_prog_page(host, 3, host->spare_only);
- }
-
- break;
- }
-
- /* Write out the command to the device. */
- send_cmd(host, command);
-
- /* Write out column address, if necessary */
- if (column != -1) {
- /*
- * MXC NANDFC can only perform full page+spare or
- * spare-only read/write. When the upper layers perform
- * a read/write buffer operation, we will use the saved
- * column address to index into the full page.
- */
- send_addr(host, 0);
- if (host->pagesize_2k)
- /* another col addr cycle for 2k page */
- send_addr(host, 0);
- }
-
- /* Write out page address, if necessary */
- if (page_addr != -1) {
- u32 page_mask = nand_chip->pagemask;
- do {
- send_addr(host, page_addr & 0xFF);
- page_addr >>= 8;
- page_mask >>= 8;
- } while (page_mask);
- }
-
- /* Command post-processing step */
- switch (command) {
-
- case NAND_CMD_RESET:
- break;
-
- case NAND_CMD_READOOB:
- case NAND_CMD_READ0:
- if (host->pagesize_2k) {
- /* send read confirm command */
- send_cmd(host, NAND_CMD_READSTART);
- /* read for each AREA */
- send_read_page(host, 0, host->spare_only);
- if (is_mxc_nfc_1()) {
- send_read_page(host, 1, host->spare_only);
- send_read_page(host, 2, host->spare_only);
- send_read_page(host, 3, host->spare_only);
- }
- } else {
- send_read_page(host, 0, host->spare_only);
- }
- break;
-
- case NAND_CMD_READID:
- host->col_addr = 0;
- send_read_id(host);
- break;
-
- case NAND_CMD_PAGEPROG:
- break;
-
- case NAND_CMD_STATUS:
- break;
-
- case NAND_CMD_ERASE2:
- break;
- }
-}
-
-#ifdef CONFIG_SYS_NAND_USE_FLASH_BBT
-
-static u8 bbt_pattern[] = {'B', 'b', 't', '0' };
-static u8 mirror_pattern[] = {'1', 't', 'b', 'B' };
-
-static struct nand_bbt_descr bbt_main_descr = {
- .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE |
- NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
- .offs = 0,
- .len = 4,
- .veroffs = 4,
- .maxblocks = 4,
- .pattern = bbt_pattern,
-};
-
-static struct nand_bbt_descr bbt_mirror_descr = {
- .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE |
- NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
- .offs = 0,
- .len = 4,
- .veroffs = 4,
- .maxblocks = 4,
- .pattern = mirror_pattern,
-};
-
-#endif
-
-int board_nand_init(struct nand_chip *this)
-{
- struct mtd_info *mtd;
-#if defined(MXC_NFC_V2_1) || defined(MXC_NFC_V3_2)
- uint32_t tmp;
-#endif
-
-#ifdef CONFIG_SYS_NAND_USE_FLASH_BBT
- this->bbt_options |= NAND_BBT_USE_FLASH;
- this->bbt_td = &bbt_main_descr;
- this->bbt_md = &bbt_mirror_descr;
-#endif
-
- /* structures must be linked */
- mtd = &host->mtd;
- mtd->priv = this;
- host->nand = this;
-
- /* 5 us command delay time */
- this->chip_delay = 5;
-
- this->priv = host;
- this->dev_ready = mxc_nand_dev_ready;
- this->cmdfunc = mxc_nand_command;
- this->select_chip = mxc_nand_select_chip;
- this->read_byte = mxc_nand_read_byte;
- this->read_word = mxc_nand_read_word;
- this->write_buf = mxc_nand_write_buf;
- this->read_buf = mxc_nand_read_buf;
- this->verify_buf = mxc_nand_verify_buf;
-
- host->regs = (struct mxc_nand_regs __iomem *)CONFIG_MXC_NAND_REGS_BASE;
-#ifdef MXC_NFC_V3_2
- host->ip_regs =
- (struct mxc_nand_ip_regs __iomem *)CONFIG_MXC_NAND_IP_REGS_BASE;
-#endif
- host->clk_act = 1;
-
-#ifdef CONFIG_MXC_NAND_HWECC
- this->ecc.calculate = mxc_nand_calculate_ecc;
- this->ecc.hwctl = mxc_nand_enable_hwecc;
- this->ecc.correct = mxc_nand_correct_data;
- if (is_mxc_nfc_21() || is_mxc_nfc_32()) {
- this->ecc.mode = NAND_ECC_HW_SYNDROME;
- this->ecc.read_page = mxc_nand_read_page_syndrome;
- this->ecc.read_page_raw = mxc_nand_read_page_raw_syndrome;
- this->ecc.read_oob = mxc_nand_read_oob_syndrome;
- this->ecc.write_page = mxc_nand_write_page_syndrome;
- this->ecc.write_page_raw = mxc_nand_write_page_raw_syndrome;
- this->ecc.write_oob = mxc_nand_write_oob_syndrome;
- this->ecc.bytes = 9;
- this->ecc.prepad = 7;
- } else {
- this->ecc.mode = NAND_ECC_HW;
- }
-
- if (is_mxc_nfc_1())
- this->ecc.strength = 1;
- else
- this->ecc.strength = 4;
-
- host->pagesize_2k = 0;
-
- this->ecc.size = 512;
- _mxc_nand_enable_hwecc(mtd, 1);
-#else
- this->ecc.layout = &nand_soft_eccoob;
- this->ecc.mode = NAND_ECC_SOFT;
- _mxc_nand_enable_hwecc(mtd, 0);
-#endif
- /* Reset NAND */
- this->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
-
- /* NAND bus width determines access functions used by upper layer */
- if (is_16bit_nand())
- this->options |= NAND_BUSWIDTH_16;
-
-#ifdef CONFIG_SYS_NAND_LARGEPAGE
- host->pagesize_2k = 1;
- this->ecc.layout = &nand_hw_eccoob2k;
-#else
- host->pagesize_2k = 0;
- this->ecc.layout = &nand_hw_eccoob;
-#endif
-
-#if defined(MXC_NFC_V1) || defined(MXC_NFC_V2_1)
-#ifdef MXC_NFC_V2_1
- tmp = readnfc(&host->regs->config1);
- tmp |= NFC_V2_CONFIG1_ONE_CYCLE;
- tmp |= NFC_V2_CONFIG1_ECC_MODE_4;
- writenfc(tmp, &host->regs->config1);
- if (host->pagesize_2k)
- writenfc(64/2, &host->regs->spare_area_size);
- else
- writenfc(16/2, &host->regs->spare_area_size);
-#endif
-
- /*
- * preset operation
- * Unlock the internal RAM Buffer
- */
- writenfc(0x2, &host->regs->config);
-
- /* Blocks to be unlocked */
- writenfc(0x0, &host->regs->unlockstart_blkaddr);
- /* Originally (Freescale LTIB 2.6.21) 0x4000 was written to the
- * unlockend_blkaddr, but the magic 0x4000 does not always work
- * when writing more than some 32 megabytes (on 2k page nands)
- * However 0xFFFF doesn't seem to have this kind
- * of limitation (tried it back and forth several times).
- * The linux kernel driver sets this to 0xFFFF for the v2 controller
- * only, but probably this was not tested there for v1.
- * The very same limitation seems to apply to this kernel driver.
- * This might be NAND chip specific and the i.MX31 datasheet is
- * extremely vague about the semantics of this register.
- */
- writenfc(0xFFFF, &host->regs->unlockend_blkaddr);
-
- /* Unlock Block Command for given address range */
- writenfc(0x4, &host->regs->wrprot);
-#elif defined(MXC_NFC_V3_2)
- writenfc(NFC_V3_CONFIG1_RBA(0), &host->regs->config1);
- writenfc(NFC_V3_IPC_CREQ, &host->ip_regs->ipc);
-
- /* Unlock the internal RAM Buffer */
- writenfc(NFC_V3_WRPROT_BLS_UNLOCK | NFC_V3_WRPROT_UNLOCK,
- &host->ip_regs->wrprot);
-
- /* Blocks to be unlocked */
- for (tmp = 0; tmp < CONFIG_SYS_NAND_MAX_CHIPS; tmp++)
- writenfc(0x0 | 0xFFFF << 16,
- &host->ip_regs->wrprot_unlock_blkaddr[tmp]);
-
- writenfc(0, &host->ip_regs->ipc);
-
- tmp = readnfc(&host->ip_regs->config2);
- tmp &= ~(NFC_V3_CONFIG2_SPAS_MASK | NFC_V3_CONFIG2_EDC_MASK |
- NFC_V3_CONFIG2_ECC_MODE_8 | NFC_V3_CONFIG2_PS_MASK);
- tmp |= NFC_V3_CONFIG2_ONE_CYCLE;
-
- if (host->pagesize_2k) {
- tmp |= NFC_V3_CONFIG2_SPAS(64/2);
- tmp |= NFC_V3_CONFIG2_PS_2048;
- } else {
- tmp |= NFC_V3_CONFIG2_SPAS(16/2);
- tmp |= NFC_V3_CONFIG2_PS_512;
- }
-
- writenfc(tmp, &host->ip_regs->config2);
-
- tmp = NFC_V3_CONFIG3_NUM_OF_DEVS(0) |
- NFC_V3_CONFIG3_NO_SDMA |
- NFC_V3_CONFIG3_RBB_MODE |
- NFC_V3_CONFIG3_SBB(6) | /* Reset default */
- NFC_V3_CONFIG3_ADD_OP(0);
-
- if (!(this->options & NAND_BUSWIDTH_16))
- tmp |= NFC_V3_CONFIG3_FW8;
-
- writenfc(tmp, &host->ip_regs->config3);
-
- writenfc(0, &host->ip_regs->delay_line);
-#endif
-
- return 0;
-}
diff --git a/qemu/roms/u-boot/drivers/mtd/nand/mxc_nand.h b/qemu/roms/u-boot/drivers/mtd/nand/mxc_nand.h
deleted file mode 100644
index a02d6e0a5..000000000
--- a/qemu/roms/u-boot/drivers/mtd/nand/mxc_nand.h
+++ /dev/null
@@ -1,209 +0,0 @@
-/*
- * (c) 2009 Magnus Lilja <lilja.magnus@gmail.com>
- *
- * SPDX-License-Identifier: GPL-2.0+
- */
-
-#ifndef __MXC_NAND_H
-#define __MXC_NAND_H
-
-/*
- * Register map and bit definitions for the Freescale NAND Flash Controller
- * present in various i.MX devices.
- *
- * MX31 and MX27 have version 1, which has:
- * 4 512-byte main buffers and
- * 4 16-byte spare buffers
- * to support up to 2K byte pagesize nand.
- * Reading or writing a 2K page requires 4 FDI/FDO cycles.
- *
- * MX25 and MX35 have version 2.1, and MX51 and MX53 have version 3.2, which
- * have:
- * 8 512-byte main buffers and
- * 8 64-byte spare buffers
- * to support up to 4K byte pagesize nand.
- * Reading or writing a 2K or 4K page requires only 1 FDI/FDO cycle.
- * Also some of registers are moved and/or changed meaning as seen below.
- */
-#if defined(CONFIG_MX27) || defined(CONFIG_MX31)
-#define MXC_NFC_V1
-#define is_mxc_nfc_1() 1
-#define is_mxc_nfc_21() 0
-#define is_mxc_nfc_32() 0
-#elif defined(CONFIG_MX25) || defined(CONFIG_MX35)
-#define MXC_NFC_V2_1
-#define is_mxc_nfc_1() 0
-#define is_mxc_nfc_21() 1
-#define is_mxc_nfc_32() 0
-#elif defined(CONFIG_MX51) || defined(CONFIG_MX53)
-#define MXC_NFC_V3
-#define MXC_NFC_V3_2
-#define is_mxc_nfc_1() 0
-#define is_mxc_nfc_21() 0
-#define is_mxc_nfc_32() 1
-#else
-#error "MXC NFC implementation not supported"
-#endif
-#define is_mxc_nfc_3() is_mxc_nfc_32()
-
-#if defined(MXC_NFC_V1)
-#define NAND_MXC_NR_BUFS 4
-#define NAND_MXC_SPARE_BUF_SIZE 16
-#define NAND_MXC_REG_OFFSET 0xe00
-#define NAND_MXC_2K_MULTI_CYCLE
-#elif defined(MXC_NFC_V2_1) || defined(MXC_NFC_V3_2)
-#define NAND_MXC_NR_BUFS 8
-#define NAND_MXC_SPARE_BUF_SIZE 64
-#define NAND_MXC_REG_OFFSET 0x1e00
-#endif
-
-struct mxc_nand_regs {
- u8 main_area[NAND_MXC_NR_BUFS][0x200];
- u8 spare_area[NAND_MXC_NR_BUFS][NAND_MXC_SPARE_BUF_SIZE];
- /*
- * reserved size is offset of nfc registers
- * minus total main and spare sizes
- */
- u8 reserved1[NAND_MXC_REG_OFFSET
- - NAND_MXC_NR_BUFS * (512 + NAND_MXC_SPARE_BUF_SIZE)];
-#if defined(MXC_NFC_V1)
- u16 buf_size;
- u16 reserved2;
- u16 buf_addr;
- u16 flash_addr;
- u16 flash_cmd;
- u16 config;
- u16 ecc_status_result;
- u16 rsltmain_area;
- u16 rsltspare_area;
- u16 wrprot;
- u16 unlockstart_blkaddr;
- u16 unlockend_blkaddr;
- u16 nf_wrprst;
- u16 config1;
- u16 config2;
-#elif defined(MXC_NFC_V2_1)
- u16 reserved2[2];
- u16 buf_addr;
- u16 flash_addr;
- u16 flash_cmd;
- u16 config;
- u32 ecc_status_result;
- u16 spare_area_size;
- u16 wrprot;
- u16 reserved3[2];
- u16 nf_wrprst;
- u16 config1;
- u16 config2;
- u16 reserved4;
- u16 unlockstart_blkaddr;
- u16 unlockend_blkaddr;
- u16 unlockstart_blkaddr1;
- u16 unlockend_blkaddr1;
- u16 unlockstart_blkaddr2;
- u16 unlockend_blkaddr2;
- u16 unlockstart_blkaddr3;
- u16 unlockend_blkaddr3;
-#elif defined(MXC_NFC_V3_2)
- u32 flash_cmd;
- u32 flash_addr[12];
- u32 config1;
- u32 ecc_status_result;
- u32 status_sum;
- u32 launch;
-#endif
-};
-
-#ifdef MXC_NFC_V3_2
-struct mxc_nand_ip_regs {
- u32 wrprot;
- u32 wrprot_unlock_blkaddr[8];
- u32 config2;
- u32 config3;
- u32 ipc;
- u32 err_addr;
- u32 delay_line;
-};
-#endif
-
-/* Set FCMD to 1, rest to 0 for Command operation */
-#define NFC_CMD 0x1
-
-/* Set FADD to 1, rest to 0 for Address operation */
-#define NFC_ADDR 0x2
-
-/* Set FDI to 1, rest to 0 for Input operation */
-#define NFC_INPUT 0x4
-
-/* Set FDO to 001, rest to 0 for Data Output operation */
-#define NFC_OUTPUT 0x8
-
-/* Set FDO to 010, rest to 0 for Read ID operation */
-#define NFC_ID 0x10
-
-/* Set FDO to 100, rest to 0 for Read Status operation */
-#define NFC_STATUS 0x20
-
-#if defined(MXC_NFC_V1) || defined(MXC_NFC_V2_1)
-#define NFC_CONFIG1_SP_EN (1 << 2)
-#define NFC_CONFIG1_RST (1 << 6)
-#define NFC_CONFIG1_CE (1 << 7)
-#elif defined(MXC_NFC_V3_2)
-#define NFC_CONFIG1_SP_EN (1 << 0)
-#define NFC_CONFIG1_CE (1 << 1)
-#define NFC_CONFIG1_RST (1 << 2)
-#endif
-#define NFC_V1_V2_CONFIG1_ECC_EN (1 << 3)
-#define NFC_V1_V2_CONFIG1_INT_MSK (1 << 4)
-#define NFC_V1_V2_CONFIG1_BIG (1 << 5)
-#define NFC_V2_CONFIG1_ECC_MODE_4 (1 << 0)
-#define NFC_V2_CONFIG1_ONE_CYCLE (1 << 8)
-#define NFC_V2_CONFIG1_FP_INT (1 << 11)
-#define NFC_V3_CONFIG1_RBA_MASK (0x7 << 4)
-#define NFC_V3_CONFIG1_RBA(x) (((x) & 0x7) << 4)
-
-#define NFC_V1_V2_CONFIG2_INT (1 << 15)
-#define NFC_V3_CONFIG2_PS_MASK (0x3 << 0)
-#define NFC_V3_CONFIG2_PS_512 (0 << 0)
-#define NFC_V3_CONFIG2_PS_2048 (1 << 0)
-#define NFC_V3_CONFIG2_PS_4096 (2 << 0)
-#define NFC_V3_CONFIG2_ONE_CYCLE (1 << 2)
-#define NFC_V3_CONFIG2_ECC_EN (1 << 3)
-#define NFC_V3_CONFIG2_2CMD_PHASES (1 << 4)
-#define NFC_V3_CONFIG2_NUM_ADDR_PH0 (1 << 5)
-#define NFC_V3_CONFIG2_ECC_MODE_8 (1 << 6)
-#define NFC_V3_CONFIG2_PPB_MASK (0x3 << 7)
-#define NFC_V3_CONFIG2_PPB(x) (((x) & 0x3) << 7)
-#define NFC_V3_CONFIG2_EDC_MASK (0x7 << 9)
-#define NFC_V3_CONFIG2_EDC(x) (((x) & 0x7) << 9)
-#define NFC_V3_CONFIG2_NUM_ADDR_PH1(x) (((x) & 0x3) << 12)
-#define NFC_V3_CONFIG2_INT_MSK (1 << 15)
-#define NFC_V3_CONFIG2_SPAS_MASK (0xff << 16)
-#define NFC_V3_CONFIG2_SPAS(x) (((x) & 0xff) << 16)
-#define NFC_V3_CONFIG2_ST_CMD_MASK (0xff << 24)
-#define NFC_V3_CONFIG2_ST_CMD(x) (((x) & 0xff) << 24)
-
-#define NFC_V3_CONFIG3_ADD_OP(x) (((x) & 0x3) << 0)
-#define NFC_V3_CONFIG3_FW8 (1 << 3)
-#define NFC_V3_CONFIG3_SBB(x) (((x) & 0x7) << 8)
-#define NFC_V3_CONFIG3_NUM_OF_DEVS(x) (((x) & 0x7) << 12)
-#define NFC_V3_CONFIG3_RBB_MODE (1 << 15)
-#define NFC_V3_CONFIG3_NO_SDMA (1 << 20)
-
-#define NFC_V3_WRPROT_UNLOCK (1 << 2)
-#define NFC_V3_WRPROT_BLS_UNLOCK (2 << 6)
-
-#define NFC_V3_IPC_CREQ (1 << 0)
-#define NFC_V3_IPC_INT (1 << 31)
-
-#if defined(MXC_NFC_V1) || defined(MXC_NFC_V2_1)
-#define operation config2
-#define readnfc readw
-#define writenfc writew
-#elif defined(MXC_NFC_V3_2)
-#define operation launch
-#define readnfc readl
-#define writenfc writel
-#endif
-
-#endif /* __MXC_NAND_H */
diff --git a/qemu/roms/u-boot/drivers/mtd/nand/mxc_nand_spl.c b/qemu/roms/u-boot/drivers/mtd/nand/mxc_nand_spl.c
deleted file mode 100644
index 69b736a84..000000000
--- a/qemu/roms/u-boot/drivers/mtd/nand/mxc_nand_spl.c
+++ /dev/null
@@ -1,351 +0,0 @@
-/*
- * (C) Copyright 2009
- * Magnus Lilja <lilja.magnus@gmail.com>
- *
- * (C) Copyright 2008
- * Maxim Artamonov, <scn1874 at yandex.ru>
- *
- * (C) Copyright 2006-2008
- * Stefan Roese, DENX Software Engineering, sr at denx.de.
- *
- * SPDX-License-Identifier: GPL-2.0+
- */
-
-#include <common.h>
-#include <nand.h>
-#include <asm/arch/imx-regs.h>
-#include <asm/io.h>
-#include "mxc_nand.h"
-
-#if defined(MXC_NFC_V1) || defined(MXC_NFC_V2_1)
-static struct mxc_nand_regs *const nfc = (void *)NFC_BASE_ADDR;
-#elif defined(MXC_NFC_V3_2)
-static struct mxc_nand_regs *const nfc = (void *)NFC_BASE_ADDR_AXI;
-static struct mxc_nand_ip_regs *const nfc_ip = (void *)NFC_BASE_ADDR;
-#endif
-
-static void nfc_wait_ready(void)
-{
- uint32_t tmp;
-
-#if defined(MXC_NFC_V1) || defined(MXC_NFC_V2_1)
- while (!(readnfc(&nfc->config2) & NFC_V1_V2_CONFIG2_INT))
- ;
-
- /* Reset interrupt flag */
- tmp = readnfc(&nfc->config2);
- tmp &= ~NFC_V1_V2_CONFIG2_INT;
- writenfc(tmp, &nfc->config2);
-#elif defined(MXC_NFC_V3_2)
- while (!(readnfc(&nfc_ip->ipc) & NFC_V3_IPC_INT))
- ;
-
- /* Reset interrupt flag */
- tmp = readnfc(&nfc_ip->ipc);
- tmp &= ~NFC_V3_IPC_INT;
- writenfc(tmp, &nfc_ip->ipc);
-#endif
-}
-
-static void nfc_nand_init(void)
-{
-#if defined(MXC_NFC_V3_2)
- int ecc_per_page = CONFIG_SYS_NAND_PAGE_SIZE / 512;
- int tmp;
-
- tmp = (readnfc(&nfc_ip->config2) & ~(NFC_V3_CONFIG2_SPAS_MASK |
- NFC_V3_CONFIG2_EDC_MASK | NFC_V3_CONFIG2_PS_MASK)) |
- NFC_V3_CONFIG2_SPAS(CONFIG_SYS_NAND_OOBSIZE / 2) |
- NFC_V3_CONFIG2_INT_MSK | NFC_V3_CONFIG2_ECC_EN |
- NFC_V3_CONFIG2_ONE_CYCLE;
- if (CONFIG_SYS_NAND_PAGE_SIZE == 4096)
- tmp |= NFC_V3_CONFIG2_PS_4096;
- else if (CONFIG_SYS_NAND_PAGE_SIZE == 2048)
- tmp |= NFC_V3_CONFIG2_PS_2048;
- else if (CONFIG_SYS_NAND_PAGE_SIZE == 512)
- tmp |= NFC_V3_CONFIG2_PS_512;
- /*
- * if spare size is larger that 16 bytes per 512 byte hunk
- * then use 8 symbol correction instead of 4
- */
- if (CONFIG_SYS_NAND_OOBSIZE / ecc_per_page > 16)
- tmp |= NFC_V3_CONFIG2_ECC_MODE_8;
- else
- tmp &= ~NFC_V3_CONFIG2_ECC_MODE_8;
- writenfc(tmp, &nfc_ip->config2);
-
- tmp = NFC_V3_CONFIG3_NUM_OF_DEVS(0) |
- NFC_V3_CONFIG3_NO_SDMA |
- NFC_V3_CONFIG3_RBB_MODE |
- NFC_V3_CONFIG3_SBB(6) | /* Reset default */
- NFC_V3_CONFIG3_ADD_OP(0);
-#ifndef CONFIG_SYS_NAND_BUSWIDTH_16
- tmp |= NFC_V3_CONFIG3_FW8;
-#endif
- writenfc(tmp, &nfc_ip->config3);
-
- writenfc(0, &nfc_ip->delay_line);
-#elif defined(MXC_NFC_V2_1)
- int ecc_per_page = CONFIG_SYS_NAND_PAGE_SIZE / 512;
- int config1;
-
- writenfc(CONFIG_SYS_NAND_OOBSIZE / 2, &nfc->spare_area_size);
-
- /* unlocking RAM Buff */
- writenfc(0x2, &nfc->config);
-
- /* hardware ECC checking and correct */
- config1 = readnfc(&nfc->config1) | NFC_V1_V2_CONFIG1_ECC_EN |
- NFC_V1_V2_CONFIG1_INT_MSK | NFC_V2_CONFIG1_ONE_CYCLE |
- NFC_V2_CONFIG1_FP_INT;
- /*
- * if spare size is larger that 16 bytes per 512 byte hunk
- * then use 8 symbol correction instead of 4
- */
- if (CONFIG_SYS_NAND_OOBSIZE / ecc_per_page > 16)
- config1 &= ~NFC_V2_CONFIG1_ECC_MODE_4;
- else
- config1 |= NFC_V2_CONFIG1_ECC_MODE_4;
- writenfc(config1, &nfc->config1);
-#elif defined(MXC_NFC_V1)
- /* unlocking RAM Buff */
- writenfc(0x2, &nfc->config);
-
- /* hardware ECC checking and correct */
- writenfc(NFC_V1_V2_CONFIG1_ECC_EN | NFC_V1_V2_CONFIG1_INT_MSK,
- &nfc->config1);
-#endif
-}
-
-static void nfc_nand_command(unsigned short command)
-{
- writenfc(command, &nfc->flash_cmd);
- writenfc(NFC_CMD, &nfc->operation);
- nfc_wait_ready();
-}
-
-static void nfc_nand_address(unsigned short address)
-{
- writenfc(address, &nfc->flash_addr);
- writenfc(NFC_ADDR, &nfc->operation);
- nfc_wait_ready();
-}
-
-static void nfc_nand_page_address(unsigned int page_address)
-{
- unsigned int page_count;
-
- nfc_nand_address(0x00);
-
- /* code only for large page flash */
- if (CONFIG_SYS_NAND_PAGE_SIZE > 512)
- nfc_nand_address(0x00);
-
- page_count = CONFIG_SYS_NAND_SIZE / CONFIG_SYS_NAND_PAGE_SIZE;
-
- if (page_address <= page_count) {
- page_count--; /* transform 0x01000000 to 0x00ffffff */
- do {
- nfc_nand_address(page_address & 0xff);
- page_address = page_address >> 8;
- page_count = page_count >> 8;
- } while (page_count);
- }
-
- nfc_nand_address(0x00);
-}
-
-static void nfc_nand_data_output(void)
-{
-#ifdef NAND_MXC_2K_MULTI_CYCLE
- int i;
-#endif
-
-#if defined(MXC_NFC_V1) || defined(MXC_NFC_V2_1)
- writenfc(0, &nfc->buf_addr);
-#elif defined(MXC_NFC_V3_2)
- int config1 = readnfc(&nfc->config1);
- config1 &= ~NFC_V3_CONFIG1_RBA_MASK;
- writenfc(config1, &nfc->config1);
-#endif
- writenfc(NFC_OUTPUT, &nfc->operation);
- nfc_wait_ready();
-#ifdef NAND_MXC_2K_MULTI_CYCLE
- /*
- * This NAND controller requires multiple input commands
- * for pages larger than 512 bytes.
- */
- for (i = 1; i < CONFIG_SYS_NAND_PAGE_SIZE / 512; i++) {
- writenfc(i, &nfc->buf_addr);
- writenfc(NFC_OUTPUT, &nfc->operation);
- nfc_wait_ready();
- }
-#endif
-}
-
-static int nfc_nand_check_ecc(void)
-{
-#if defined(MXC_NFC_V1)
- u16 ecc_status = readw(&nfc->ecc_status_result);
- return (ecc_status & 0x3) == 2 || (ecc_status >> 2) == 2;
-#elif defined(MXC_NFC_V2_1) || defined(MXC_NFC_V3_2)
- u32 ecc_status = readl(&nfc->ecc_status_result);
- int ecc_per_page = CONFIG_SYS_NAND_PAGE_SIZE / 512;
- int err_limit = CONFIG_SYS_NAND_OOBSIZE / ecc_per_page > 16 ? 8 : 4;
- int subpages = CONFIG_SYS_NAND_PAGE_SIZE / 512;
-
- do {
- if ((ecc_status & 0xf) > err_limit)
- return 1;
- ecc_status >>= 4;
- } while (--subpages);
-
- return 0;
-#endif
-}
-
-static void nfc_nand_read_page(unsigned int page_address)
-{
- /* read in first 0 buffer */
-#if defined(MXC_NFC_V1) || defined(MXC_NFC_V2_1)
- writenfc(0, &nfc->buf_addr);
-#elif defined(MXC_NFC_V3_2)
- int config1 = readnfc(&nfc->config1);
- config1 &= ~NFC_V3_CONFIG1_RBA_MASK;
- writenfc(config1, &nfc->config1);
-#endif
- nfc_nand_command(NAND_CMD_READ0);
- nfc_nand_page_address(page_address);
-
- if (CONFIG_SYS_NAND_PAGE_SIZE > 512)
- nfc_nand_command(NAND_CMD_READSTART);
-
- nfc_nand_data_output(); /* fill the main buffer 0 */
-}
-
-static int nfc_read_page(unsigned int page_address, unsigned char *buf)
-{
- int i;
- u32 *src;
- u32 *dst;
-
- nfc_nand_read_page(page_address);
-
- if (nfc_nand_check_ecc())
- return -1;
-
- src = (u32 *)&nfc->main_area[0][0];
- dst = (u32 *)buf;
-
- /* main copy loop from NAND-buffer to SDRAM memory */
- for (i = 0; i < CONFIG_SYS_NAND_PAGE_SIZE / 4; i++) {
- writel(readl(src), dst);
- src++;
- dst++;
- }
-
- return 0;
-}
-
-static int is_badblock(int pagenumber)
-{
- int page = pagenumber;
- u32 badblock;
- u32 *src;
-
- /* Check the first two pages for bad block markers */
- for (page = pagenumber; page < pagenumber + 2; page++) {
- nfc_nand_read_page(page);
-
- src = (u32 *)&nfc->spare_area[0][0];
-
- /*
- * IMPORTANT NOTE: The nand flash controller uses a non-
- * standard layout for large page devices. This can
- * affect the position of the bad block marker.
- */
- /* Get the bad block marker */
- badblock = readl(&src[CONFIG_SYS_NAND_BAD_BLOCK_POS / 4]);
- badblock >>= 8 * (CONFIG_SYS_NAND_BAD_BLOCK_POS % 4);
- badblock &= 0xff;
-
- /* bad block marker verify */
- if (badblock != 0xff)
- return 1; /* potential bad block */
- }
-
- return 0;
-}
-
-int nand_spl_load_image(uint32_t from, unsigned int size, void *buf)
-{
- int i;
- unsigned int page;
- unsigned int maxpages = CONFIG_SYS_NAND_SIZE /
- CONFIG_SYS_NAND_PAGE_SIZE;
-
- nfc_nand_init();
-
- /* Convert to page number */
- page = from / CONFIG_SYS_NAND_PAGE_SIZE;
- i = 0;
-
- size = roundup(size, CONFIG_SYS_NAND_PAGE_SIZE);
- while (i < size / CONFIG_SYS_NAND_PAGE_SIZE) {
- if (nfc_read_page(page, buf) < 0)
- return -1;
-
- page++;
- i++;
- buf = buf + CONFIG_SYS_NAND_PAGE_SIZE;
-
- /*
- * Check if we have crossed a block boundary, and if so
- * check for bad block.
- */
- if (!(page % CONFIG_SYS_NAND_PAGE_COUNT)) {
- /*
- * Yes, new block. See if this block is good. If not,
- * loop until we find a good block.
- */
- while (is_badblock(page)) {
- page = page + CONFIG_SYS_NAND_PAGE_COUNT;
- /* Check i we've reached the end of flash. */
- if (page >= maxpages)
- return -1;
- }
- }
- }
-
- return 0;
-}
-
-#ifndef CONFIG_SPL_FRAMEWORK
-/*
- * The main entry for NAND booting. It's necessary that SDRAM is already
- * configured and available since this code loads the main U-Boot image
- * from NAND into SDRAM and starts it from there.
- */
-void nand_boot(void)
-{
- __attribute__((noreturn)) void (*uboot)(void);
-
- /*
- * CONFIG_SYS_NAND_U_BOOT_OFFS and CONFIG_SYS_NAND_U_BOOT_SIZE must
- * be aligned to full pages
- */
- if (!nand_spl_load_image(CONFIG_SYS_NAND_U_BOOT_OFFS,
- CONFIG_SYS_NAND_U_BOOT_SIZE,
- (uchar *)CONFIG_SYS_NAND_U_BOOT_DST)) {
- /* Copy from NAND successful, start U-boot */
- uboot = (void *)CONFIG_SYS_NAND_U_BOOT_START;
- uboot();
- } else {
- /* Unrecoverable error when copying from NAND */
- hang();
- }
-}
-#endif
-
-void nand_init(void) {}
-void nand_deselect(void) {}
diff --git a/qemu/roms/u-boot/drivers/mtd/nand/mxs_nand.c b/qemu/roms/u-boot/drivers/mtd/nand/mxs_nand.c
deleted file mode 100644
index 036c113ad..000000000
--- a/qemu/roms/u-boot/drivers/mtd/nand/mxs_nand.c
+++ /dev/null
@@ -1,1179 +0,0 @@
-/*
- * Freescale i.MX28 NAND flash driver
- *
- * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
- * on behalf of DENX Software Engineering GmbH
- *
- * Based on code from LTIB:
- * Freescale GPMI NFC NAND Flash Driver
- *
- * Copyright (C) 2010 Freescale Semiconductor, Inc.
- * Copyright (C) 2008 Embedded Alley Solutions, Inc.
- *
- * SPDX-License-Identifier: GPL-2.0+
- */
-
-#include <common.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
-#include <linux/types.h>
-#include <malloc.h>
-#include <asm/errno.h>
-#include <asm/io.h>
-#include <asm/arch/clock.h>
-#include <asm/arch/imx-regs.h>
-#include <asm/imx-common/regs-bch.h>
-#include <asm/imx-common/regs-gpmi.h>
-#include <asm/arch/sys_proto.h>
-#include <asm/imx-common/dma.h>
-
-#define MXS_NAND_DMA_DESCRIPTOR_COUNT 4
-
-#define MXS_NAND_CHUNK_DATA_CHUNK_SIZE 512
-#if defined(CONFIG_MX6)
-#define MXS_NAND_CHUNK_DATA_CHUNK_SIZE_SHIFT 2
-#else
-#define MXS_NAND_CHUNK_DATA_CHUNK_SIZE_SHIFT 0
-#endif
-#define MXS_NAND_METADATA_SIZE 10
-
-#define MXS_NAND_COMMAND_BUFFER_SIZE 32
-
-#define MXS_NAND_BCH_TIMEOUT 10000
-
-struct mxs_nand_info {
- int cur_chip;
-
- uint32_t cmd_queue_len;
- uint32_t data_buf_size;
-
- uint8_t *cmd_buf;
- uint8_t *data_buf;
- uint8_t *oob_buf;
-
- uint8_t marking_block_bad;
- uint8_t raw_oob_mode;
-
- /* Functions with altered behaviour */
- int (*hooked_read_oob)(struct mtd_info *mtd,
- loff_t from, struct mtd_oob_ops *ops);
- int (*hooked_write_oob)(struct mtd_info *mtd,
- loff_t to, struct mtd_oob_ops *ops);
- int (*hooked_block_markbad)(struct mtd_info *mtd,
- loff_t ofs);
-
- /* DMA descriptors */
- struct mxs_dma_desc **desc;
- uint32_t desc_index;
-};
-
-struct nand_ecclayout fake_ecc_layout;
-
-/*
- * Cache management functions
- */
-#ifndef CONFIG_SYS_DCACHE_OFF
-static void mxs_nand_flush_data_buf(struct mxs_nand_info *info)
-{
- uint32_t addr = (uint32_t)info->data_buf;
-
- flush_dcache_range(addr, addr + info->data_buf_size);
-}
-
-static void mxs_nand_inval_data_buf(struct mxs_nand_info *info)
-{
- uint32_t addr = (uint32_t)info->data_buf;
-
- invalidate_dcache_range(addr, addr + info->data_buf_size);
-}
-
-static void mxs_nand_flush_cmd_buf(struct mxs_nand_info *info)
-{
- uint32_t addr = (uint32_t)info->cmd_buf;
-
- flush_dcache_range(addr, addr + MXS_NAND_COMMAND_BUFFER_SIZE);
-}
-#else
-static inline void mxs_nand_flush_data_buf(struct mxs_nand_info *info) {}
-static inline void mxs_nand_inval_data_buf(struct mxs_nand_info *info) {}
-static inline void mxs_nand_flush_cmd_buf(struct mxs_nand_info *info) {}
-#endif
-
-static struct mxs_dma_desc *mxs_nand_get_dma_desc(struct mxs_nand_info *info)
-{
- struct mxs_dma_desc *desc;
-
- if (info->desc_index >= MXS_NAND_DMA_DESCRIPTOR_COUNT) {
- printf("MXS NAND: Too many DMA descriptors requested\n");
- return NULL;
- }
-
- desc = info->desc[info->desc_index];
- info->desc_index++;
-
- return desc;
-}
-
-static void mxs_nand_return_dma_descs(struct mxs_nand_info *info)
-{
- int i;
- struct mxs_dma_desc *desc;
-
- for (i = 0; i < info->desc_index; i++) {
- desc = info->desc[i];
- memset(desc, 0, sizeof(struct mxs_dma_desc));
- desc->address = (dma_addr_t)desc;
- }
-
- info->desc_index = 0;
-}
-
-static uint32_t mxs_nand_ecc_chunk_cnt(uint32_t page_data_size)
-{
- return page_data_size / MXS_NAND_CHUNK_DATA_CHUNK_SIZE;
-}
-
-static uint32_t mxs_nand_ecc_size_in_bits(uint32_t ecc_strength)
-{
- return ecc_strength * 13;
-}
-
-static uint32_t mxs_nand_aux_status_offset(void)
-{
- return (MXS_NAND_METADATA_SIZE + 0x3) & ~0x3;
-}
-
-static inline uint32_t mxs_nand_get_ecc_strength(uint32_t page_data_size,
- uint32_t page_oob_size)
-{
- if (page_data_size == 2048)
- return 8;
-
- if (page_data_size == 4096) {
- if (page_oob_size == 128)
- return 8;
-
- if (page_oob_size == 218)
- return 16;
-
- if (page_oob_size == 224)
- return 16;
- }
-
- return 0;
-}
-
-static inline uint32_t mxs_nand_get_mark_offset(uint32_t page_data_size,
- uint32_t ecc_strength)
-{
- uint32_t chunk_data_size_in_bits;
- uint32_t chunk_ecc_size_in_bits;
- uint32_t chunk_total_size_in_bits;
- uint32_t block_mark_chunk_number;
- uint32_t block_mark_chunk_bit_offset;
- uint32_t block_mark_bit_offset;
-
- chunk_data_size_in_bits = MXS_NAND_CHUNK_DATA_CHUNK_SIZE * 8;
- chunk_ecc_size_in_bits = mxs_nand_ecc_size_in_bits(ecc_strength);
-
- chunk_total_size_in_bits =
- chunk_data_size_in_bits + chunk_ecc_size_in_bits;
-
- /* Compute the bit offset of the block mark within the physical page. */
- block_mark_bit_offset = page_data_size * 8;
-
- /* Subtract the metadata bits. */
- block_mark_bit_offset -= MXS_NAND_METADATA_SIZE * 8;
-
- /*
- * Compute the chunk number (starting at zero) in which the block mark
- * appears.
- */
- block_mark_chunk_number =
- block_mark_bit_offset / chunk_total_size_in_bits;
-
- /*
- * Compute the bit offset of the block mark within its chunk, and
- * validate it.
- */
- block_mark_chunk_bit_offset = block_mark_bit_offset -
- (block_mark_chunk_number * chunk_total_size_in_bits);
-
- if (block_mark_chunk_bit_offset > chunk_data_size_in_bits)
- return 1;
-
- /*
- * Now that we know the chunk number in which the block mark appears,
- * we can subtract all the ECC bits that appear before it.
- */
- block_mark_bit_offset -=
- block_mark_chunk_number * chunk_ecc_size_in_bits;
-
- return block_mark_bit_offset;
-}
-
-static uint32_t mxs_nand_mark_byte_offset(struct mtd_info *mtd)
-{
- uint32_t ecc_strength;
- ecc_strength = mxs_nand_get_ecc_strength(mtd->writesize, mtd->oobsize);
- return mxs_nand_get_mark_offset(mtd->writesize, ecc_strength) >> 3;
-}
-
-static uint32_t mxs_nand_mark_bit_offset(struct mtd_info *mtd)
-{
- uint32_t ecc_strength;
- ecc_strength = mxs_nand_get_ecc_strength(mtd->writesize, mtd->oobsize);
- return mxs_nand_get_mark_offset(mtd->writesize, ecc_strength) & 0x7;
-}
-
-/*
- * Wait for BCH complete IRQ and clear the IRQ
- */
-static int mxs_nand_wait_for_bch_complete(void)
-{
- struct mxs_bch_regs *bch_regs = (struct mxs_bch_regs *)MXS_BCH_BASE;
- int timeout = MXS_NAND_BCH_TIMEOUT;
- int ret;
-
- ret = mxs_wait_mask_set(&bch_regs->hw_bch_ctrl_reg,
- BCH_CTRL_COMPLETE_IRQ, timeout);
-
- writel(BCH_CTRL_COMPLETE_IRQ, &bch_regs->hw_bch_ctrl_clr);
-
- return ret;
-}
-
-/*
- * This is the function that we install in the cmd_ctrl function pointer of the
- * owning struct nand_chip. The only functions in the reference implementation
- * that use these functions pointers are cmdfunc and select_chip.
- *
- * In this driver, we implement our own select_chip, so this function will only
- * be called by the reference implementation's cmdfunc. For this reason, we can
- * ignore the chip enable bit and concentrate only on sending bytes to the NAND
- * Flash.
- */
-static void mxs_nand_cmd_ctrl(struct mtd_info *mtd, int data, unsigned int ctrl)
-{
- struct nand_chip *nand = mtd->priv;
- struct mxs_nand_info *nand_info = nand->priv;
- struct mxs_dma_desc *d;
- uint32_t channel = MXS_DMA_CHANNEL_AHB_APBH_GPMI0 + nand_info->cur_chip;
- int ret;
-
- /*
- * If this condition is true, something is _VERY_ wrong in MTD
- * subsystem!
- */
- if (nand_info->cmd_queue_len == MXS_NAND_COMMAND_BUFFER_SIZE) {
- printf("MXS NAND: Command queue too long\n");
- return;
- }
-
- /*
- * Every operation begins with a command byte and a series of zero or
- * more address bytes. These are distinguished by either the Address
- * Latch Enable (ALE) or Command Latch Enable (CLE) signals being
- * asserted. When MTD is ready to execute the command, it will
- * deasert both latch enables.
- *
- * Rather than run a separate DMA operation for every single byte, we
- * queue them up and run a single DMA operation for the entire series
- * of command and data bytes.
- */
- if (ctrl & (NAND_ALE | NAND_CLE)) {
- if (data != NAND_CMD_NONE)
- nand_info->cmd_buf[nand_info->cmd_queue_len++] = data;
- return;
- }
-
- /*
- * If control arrives here, MTD has deasserted both the ALE and CLE,
- * which means it's ready to run an operation. Check if we have any
- * bytes to send.
- */
- if (nand_info->cmd_queue_len == 0)
- return;
-
- /* Compile the DMA descriptor -- a descriptor that sends command. */
- d = mxs_nand_get_dma_desc(nand_info);
- d->cmd.data =
- MXS_DMA_DESC_COMMAND_DMA_READ | MXS_DMA_DESC_IRQ |
- MXS_DMA_DESC_CHAIN | MXS_DMA_DESC_DEC_SEM |
- MXS_DMA_DESC_WAIT4END | (3 << MXS_DMA_DESC_PIO_WORDS_OFFSET) |
- (nand_info->cmd_queue_len << MXS_DMA_DESC_BYTES_OFFSET);
-
- d->cmd.address = (dma_addr_t)nand_info->cmd_buf;
-
- d->cmd.pio_words[0] =
- GPMI_CTRL0_COMMAND_MODE_WRITE |
- GPMI_CTRL0_WORD_LENGTH |
- (nand_info->cur_chip << GPMI_CTRL0_CS_OFFSET) |
- GPMI_CTRL0_ADDRESS_NAND_CLE |
- GPMI_CTRL0_ADDRESS_INCREMENT |
- nand_info->cmd_queue_len;
-
- mxs_dma_desc_append(channel, d);
-
- /* Flush caches */
- mxs_nand_flush_cmd_buf(nand_info);
-
- /* Execute the DMA chain. */
- ret = mxs_dma_go(channel);
- if (ret)
- printf("MXS NAND: Error sending command\n");
-
- mxs_nand_return_dma_descs(nand_info);
-
- /* Reset the command queue. */
- nand_info->cmd_queue_len = 0;
-}
-
-/*
- * Test if the NAND flash is ready.
- */
-static int mxs_nand_device_ready(struct mtd_info *mtd)
-{
- struct nand_chip *chip = mtd->priv;
- struct mxs_nand_info *nand_info = chip->priv;
- struct mxs_gpmi_regs *gpmi_regs =
- (struct mxs_gpmi_regs *)MXS_GPMI_BASE;
- uint32_t tmp;
-
- tmp = readl(&gpmi_regs->hw_gpmi_stat);
- tmp >>= (GPMI_STAT_READY_BUSY_OFFSET + nand_info->cur_chip);
-
- return tmp & 1;
-}
-
-/*
- * Select the NAND chip.
- */
-static void mxs_nand_select_chip(struct mtd_info *mtd, int chip)
-{
- struct nand_chip *nand = mtd->priv;
- struct mxs_nand_info *nand_info = nand->priv;
-
- nand_info->cur_chip = chip;
-}
-
-/*
- * Handle block mark swapping.
- *
- * Note that, when this function is called, it doesn't know whether it's
- * swapping the block mark, or swapping it *back* -- but it doesn't matter
- * because the the operation is the same.
- */
-static void mxs_nand_swap_block_mark(struct mtd_info *mtd,
- uint8_t *data_buf, uint8_t *oob_buf)
-{
- uint32_t bit_offset;
- uint32_t buf_offset;
-
- uint32_t src;
- uint32_t dst;
-
- bit_offset = mxs_nand_mark_bit_offset(mtd);
- buf_offset = mxs_nand_mark_byte_offset(mtd);
-
- /*
- * Get the byte from the data area that overlays the block mark. Since
- * the ECC engine applies its own view to the bits in the page, the
- * physical block mark won't (in general) appear on a byte boundary in
- * the data.
- */
- src = data_buf[buf_offset] >> bit_offset;
- src |= data_buf[buf_offset + 1] << (8 - bit_offset);
-
- dst = oob_buf[0];
-
- oob_buf[0] = src;
-
- data_buf[buf_offset] &= ~(0xff << bit_offset);
- data_buf[buf_offset + 1] &= 0xff << bit_offset;
-
- data_buf[buf_offset] |= dst << bit_offset;
- data_buf[buf_offset + 1] |= dst >> (8 - bit_offset);
-}
-
-/*
- * Read data from NAND.
- */
-static void mxs_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int length)
-{
- struct nand_chip *nand = mtd->priv;
- struct mxs_nand_info *nand_info = nand->priv;
- struct mxs_dma_desc *d;
- uint32_t channel = MXS_DMA_CHANNEL_AHB_APBH_GPMI0 + nand_info->cur_chip;
- int ret;
-
- if (length > NAND_MAX_PAGESIZE) {
- printf("MXS NAND: DMA buffer too big\n");
- return;
- }
-
- if (!buf) {
- printf("MXS NAND: DMA buffer is NULL\n");
- return;
- }
-
- /* Compile the DMA descriptor - a descriptor that reads data. */
- d = mxs_nand_get_dma_desc(nand_info);
- d->cmd.data =
- MXS_DMA_DESC_COMMAND_DMA_WRITE | MXS_DMA_DESC_IRQ |
- MXS_DMA_DESC_DEC_SEM | MXS_DMA_DESC_WAIT4END |
- (1 << MXS_DMA_DESC_PIO_WORDS_OFFSET) |
- (length << MXS_DMA_DESC_BYTES_OFFSET);
-
- d->cmd.address = (dma_addr_t)nand_info->data_buf;
-
- d->cmd.pio_words[0] =
- GPMI_CTRL0_COMMAND_MODE_READ |
- GPMI_CTRL0_WORD_LENGTH |
- (nand_info->cur_chip << GPMI_CTRL0_CS_OFFSET) |
- GPMI_CTRL0_ADDRESS_NAND_DATA |
- length;
-
- mxs_dma_desc_append(channel, d);
-
- /*
- * A DMA descriptor that waits for the command to end and the chip to
- * become ready.
- *
- * I think we actually should *not* be waiting for the chip to become
- * ready because, after all, we don't care. I think the original code
- * did that and no one has re-thought it yet.
- */
- d = mxs_nand_get_dma_desc(nand_info);
- d->cmd.data =
- MXS_DMA_DESC_COMMAND_NO_DMAXFER | MXS_DMA_DESC_IRQ |
- MXS_DMA_DESC_NAND_WAIT_4_READY | MXS_DMA_DESC_DEC_SEM |
- MXS_DMA_DESC_WAIT4END | (4 << MXS_DMA_DESC_PIO_WORDS_OFFSET);
-
- d->cmd.address = 0;
-
- d->cmd.pio_words[0] =
- GPMI_CTRL0_COMMAND_MODE_WAIT_FOR_READY |
- GPMI_CTRL0_WORD_LENGTH |
- (nand_info->cur_chip << GPMI_CTRL0_CS_OFFSET) |
- GPMI_CTRL0_ADDRESS_NAND_DATA;
-
- mxs_dma_desc_append(channel, d);
-
- /* Execute the DMA chain. */
- ret = mxs_dma_go(channel);
- if (ret) {
- printf("MXS NAND: DMA read error\n");
- goto rtn;
- }
-
- /* Invalidate caches */
- mxs_nand_inval_data_buf(nand_info);
-
- memcpy(buf, nand_info->data_buf, length);
-
-rtn:
- mxs_nand_return_dma_descs(nand_info);
-}
-
-/*
- * Write data to NAND.
- */
-static void mxs_nand_write_buf(struct mtd_info *mtd, const uint8_t *buf,
- int length)
-{
- struct nand_chip *nand = mtd->priv;
- struct mxs_nand_info *nand_info = nand->priv;
- struct mxs_dma_desc *d;
- uint32_t channel = MXS_DMA_CHANNEL_AHB_APBH_GPMI0 + nand_info->cur_chip;
- int ret;
-
- if (length > NAND_MAX_PAGESIZE) {
- printf("MXS NAND: DMA buffer too big\n");
- return;
- }
-
- if (!buf) {
- printf("MXS NAND: DMA buffer is NULL\n");
- return;
- }
-
- memcpy(nand_info->data_buf, buf, length);
-
- /* Compile the DMA descriptor - a descriptor that writes data. */
- d = mxs_nand_get_dma_desc(nand_info);
- d->cmd.data =
- MXS_DMA_DESC_COMMAND_DMA_READ | MXS_DMA_DESC_IRQ |
- MXS_DMA_DESC_DEC_SEM | MXS_DMA_DESC_WAIT4END |
- (4 << MXS_DMA_DESC_PIO_WORDS_OFFSET) |
- (length << MXS_DMA_DESC_BYTES_OFFSET);
-
- d->cmd.address = (dma_addr_t)nand_info->data_buf;
-
- d->cmd.pio_words[0] =
- GPMI_CTRL0_COMMAND_MODE_WRITE |
- GPMI_CTRL0_WORD_LENGTH |
- (nand_info->cur_chip << GPMI_CTRL0_CS_OFFSET) |
- GPMI_CTRL0_ADDRESS_NAND_DATA |
- length;
-
- mxs_dma_desc_append(channel, d);
-
- /* Flush caches */
- mxs_nand_flush_data_buf(nand_info);
-
- /* Execute the DMA chain. */
- ret = mxs_dma_go(channel);
- if (ret)
- printf("MXS NAND: DMA write error\n");
-
- mxs_nand_return_dma_descs(nand_info);
-}
-
-/*
- * Read a single byte from NAND.
- */
-static uint8_t mxs_nand_read_byte(struct mtd_info *mtd)
-{
- uint8_t buf;
- mxs_nand_read_buf(mtd, &buf, 1);
- return buf;
-}
-
-/*
- * Read a page from NAND.
- */
-static int mxs_nand_ecc_read_page(struct mtd_info *mtd, struct nand_chip *nand,
- uint8_t *buf, int oob_required,
- int page)
-{
- struct mxs_nand_info *nand_info = nand->priv;
- struct mxs_dma_desc *d;
- uint32_t channel = MXS_DMA_CHANNEL_AHB_APBH_GPMI0 + nand_info->cur_chip;
- uint32_t corrected = 0, failed = 0;
- uint8_t *status;
- int i, ret;
-
- /* Compile the DMA descriptor - wait for ready. */
- d = mxs_nand_get_dma_desc(nand_info);
- d->cmd.data =
- MXS_DMA_DESC_COMMAND_NO_DMAXFER | MXS_DMA_DESC_CHAIN |
- MXS_DMA_DESC_NAND_WAIT_4_READY | MXS_DMA_DESC_WAIT4END |
- (1 << MXS_DMA_DESC_PIO_WORDS_OFFSET);
-
- d->cmd.address = 0;
-
- d->cmd.pio_words[0] =
- GPMI_CTRL0_COMMAND_MODE_WAIT_FOR_READY |
- GPMI_CTRL0_WORD_LENGTH |
- (nand_info->cur_chip << GPMI_CTRL0_CS_OFFSET) |
- GPMI_CTRL0_ADDRESS_NAND_DATA;
-
- mxs_dma_desc_append(channel, d);
-
- /* Compile the DMA descriptor - enable the BCH block and read. */
- d = mxs_nand_get_dma_desc(nand_info);
- d->cmd.data =
- MXS_DMA_DESC_COMMAND_NO_DMAXFER | MXS_DMA_DESC_CHAIN |
- MXS_DMA_DESC_WAIT4END | (6 << MXS_DMA_DESC_PIO_WORDS_OFFSET);
-
- d->cmd.address = 0;
-
- d->cmd.pio_words[0] =
- GPMI_CTRL0_COMMAND_MODE_READ |
- GPMI_CTRL0_WORD_LENGTH |
- (nand_info->cur_chip << GPMI_CTRL0_CS_OFFSET) |
- GPMI_CTRL0_ADDRESS_NAND_DATA |
- (mtd->writesize + mtd->oobsize);
- d->cmd.pio_words[1] = 0;
- d->cmd.pio_words[2] =
- GPMI_ECCCTRL_ENABLE_ECC |
- GPMI_ECCCTRL_ECC_CMD_DECODE |
- GPMI_ECCCTRL_BUFFER_MASK_BCH_PAGE;
- d->cmd.pio_words[3] = mtd->writesize + mtd->oobsize;
- d->cmd.pio_words[4] = (dma_addr_t)nand_info->data_buf;
- d->cmd.pio_words[5] = (dma_addr_t)nand_info->oob_buf;
-
- mxs_dma_desc_append(channel, d);
-
- /* Compile the DMA descriptor - disable the BCH block. */
- d = mxs_nand_get_dma_desc(nand_info);
- d->cmd.data =
- MXS_DMA_DESC_COMMAND_NO_DMAXFER | MXS_DMA_DESC_CHAIN |
- MXS_DMA_DESC_NAND_WAIT_4_READY | MXS_DMA_DESC_WAIT4END |
- (3 << MXS_DMA_DESC_PIO_WORDS_OFFSET);
-
- d->cmd.address = 0;
-
- d->cmd.pio_words[0] =
- GPMI_CTRL0_COMMAND_MODE_WAIT_FOR_READY |
- GPMI_CTRL0_WORD_LENGTH |
- (nand_info->cur_chip << GPMI_CTRL0_CS_OFFSET) |
- GPMI_CTRL0_ADDRESS_NAND_DATA |
- (mtd->writesize + mtd->oobsize);
- d->cmd.pio_words[1] = 0;
- d->cmd.pio_words[2] = 0;
-
- mxs_dma_desc_append(channel, d);
-
- /* Compile the DMA descriptor - deassert the NAND lock and interrupt. */
- d = mxs_nand_get_dma_desc(nand_info);
- d->cmd.data =
- MXS_DMA_DESC_COMMAND_NO_DMAXFER | MXS_DMA_DESC_IRQ |
- MXS_DMA_DESC_DEC_SEM;
-
- d->cmd.address = 0;
-
- mxs_dma_desc_append(channel, d);
-
- /* Execute the DMA chain. */
- ret = mxs_dma_go(channel);
- if (ret) {
- printf("MXS NAND: DMA read error\n");
- goto rtn;
- }
-
- ret = mxs_nand_wait_for_bch_complete();
- if (ret) {
- printf("MXS NAND: BCH read timeout\n");
- goto rtn;
- }
-
- /* Invalidate caches */
- mxs_nand_inval_data_buf(nand_info);
-
- /* Read DMA completed, now do the mark swapping. */
- mxs_nand_swap_block_mark(mtd, nand_info->data_buf, nand_info->oob_buf);
-
- /* Loop over status bytes, accumulating ECC status. */
- status = nand_info->oob_buf + mxs_nand_aux_status_offset();
- for (i = 0; i < mxs_nand_ecc_chunk_cnt(mtd->writesize); i++) {
- if (status[i] == 0x00)
- continue;
-
- if (status[i] == 0xff)
- continue;
-
- if (status[i] == 0xfe) {
- failed++;
- continue;
- }
-
- corrected += status[i];
- }
-
- /* Propagate ECC status to the owning MTD. */
- mtd->ecc_stats.failed += failed;
- mtd->ecc_stats.corrected += corrected;
-
- /*
- * It's time to deliver the OOB bytes. See mxs_nand_ecc_read_oob() for
- * details about our policy for delivering the OOB.
- *
- * We fill the caller's buffer with set bits, and then copy the block
- * mark to the caller's buffer. Note that, if block mark swapping was
- * necessary, it has already been done, so we can rely on the first
- * byte of the auxiliary buffer to contain the block mark.
- */
- memset(nand->oob_poi, 0xff, mtd->oobsize);
-
- nand->oob_poi[0] = nand_info->oob_buf[0];
-
- memcpy(buf, nand_info->data_buf, mtd->writesize);
-
-rtn:
- mxs_nand_return_dma_descs(nand_info);
-
- return ret;
-}
-
-/*
- * Write a page to NAND.
- */
-static int mxs_nand_ecc_write_page(struct mtd_info *mtd,
- struct nand_chip *nand, const uint8_t *buf,
- int oob_required)
-{
- struct mxs_nand_info *nand_info = nand->priv;
- struct mxs_dma_desc *d;
- uint32_t channel = MXS_DMA_CHANNEL_AHB_APBH_GPMI0 + nand_info->cur_chip;
- int ret;
-
- memcpy(nand_info->data_buf, buf, mtd->writesize);
- memcpy(nand_info->oob_buf, nand->oob_poi, mtd->oobsize);
-
- /* Handle block mark swapping. */
- mxs_nand_swap_block_mark(mtd, nand_info->data_buf, nand_info->oob_buf);
-
- /* Compile the DMA descriptor - write data. */
- d = mxs_nand_get_dma_desc(nand_info);
- d->cmd.data =
- MXS_DMA_DESC_COMMAND_NO_DMAXFER | MXS_DMA_DESC_IRQ |
- MXS_DMA_DESC_DEC_SEM | MXS_DMA_DESC_WAIT4END |
- (6 << MXS_DMA_DESC_PIO_WORDS_OFFSET);
-
- d->cmd.address = 0;
-
- d->cmd.pio_words[0] =
- GPMI_CTRL0_COMMAND_MODE_WRITE |
- GPMI_CTRL0_WORD_LENGTH |
- (nand_info->cur_chip << GPMI_CTRL0_CS_OFFSET) |
- GPMI_CTRL0_ADDRESS_NAND_DATA;
- d->cmd.pio_words[1] = 0;
- d->cmd.pio_words[2] =
- GPMI_ECCCTRL_ENABLE_ECC |
- GPMI_ECCCTRL_ECC_CMD_ENCODE |
- GPMI_ECCCTRL_BUFFER_MASK_BCH_PAGE;
- d->cmd.pio_words[3] = (mtd->writesize + mtd->oobsize);
- d->cmd.pio_words[4] = (dma_addr_t)nand_info->data_buf;
- d->cmd.pio_words[5] = (dma_addr_t)nand_info->oob_buf;
-
- mxs_dma_desc_append(channel, d);
-
- /* Flush caches */
- mxs_nand_flush_data_buf(nand_info);
-
- /* Execute the DMA chain. */
- ret = mxs_dma_go(channel);
- if (ret) {
- printf("MXS NAND: DMA write error\n");
- goto rtn;
- }
-
- ret = mxs_nand_wait_for_bch_complete();
- if (ret) {
- printf("MXS NAND: BCH write timeout\n");
- goto rtn;
- }
-
-rtn:
- mxs_nand_return_dma_descs(nand_info);
- return 0;
-}
-
-/*
- * Read OOB from NAND.
- *
- * This function is a veneer that replaces the function originally installed by
- * the NAND Flash MTD code.
- */
-static int mxs_nand_hook_read_oob(struct mtd_info *mtd, loff_t from,
- struct mtd_oob_ops *ops)
-{
- struct nand_chip *chip = mtd->priv;
- struct mxs_nand_info *nand_info = chip->priv;
- int ret;
-
- if (ops->mode == MTD_OPS_RAW)
- nand_info->raw_oob_mode = 1;
- else
- nand_info->raw_oob_mode = 0;
-
- ret = nand_info->hooked_read_oob(mtd, from, ops);
-
- nand_info->raw_oob_mode = 0;
-
- return ret;
-}
-
-/*
- * Write OOB to NAND.
- *
- * This function is a veneer that replaces the function originally installed by
- * the NAND Flash MTD code.
- */
-static int mxs_nand_hook_write_oob(struct mtd_info *mtd, loff_t to,
- struct mtd_oob_ops *ops)
-{
- struct nand_chip *chip = mtd->priv;
- struct mxs_nand_info *nand_info = chip->priv;
- int ret;
-
- if (ops->mode == MTD_OPS_RAW)
- nand_info->raw_oob_mode = 1;
- else
- nand_info->raw_oob_mode = 0;
-
- ret = nand_info->hooked_write_oob(mtd, to, ops);
-
- nand_info->raw_oob_mode = 0;
-
- return ret;
-}
-
-/*
- * Mark a block bad in NAND.
- *
- * This function is a veneer that replaces the function originally installed by
- * the NAND Flash MTD code.
- */
-static int mxs_nand_hook_block_markbad(struct mtd_info *mtd, loff_t ofs)
-{
- struct nand_chip *chip = mtd->priv;
- struct mxs_nand_info *nand_info = chip->priv;
- int ret;
-
- nand_info->marking_block_bad = 1;
-
- ret = nand_info->hooked_block_markbad(mtd, ofs);
-
- nand_info->marking_block_bad = 0;
-
- return ret;
-}
-
-/*
- * There are several places in this driver where we have to handle the OOB and
- * block marks. This is the function where things are the most complicated, so
- * this is where we try to explain it all. All the other places refer back to
- * here.
- *
- * These are the rules, in order of decreasing importance:
- *
- * 1) Nothing the caller does can be allowed to imperil the block mark, so all
- * write operations take measures to protect it.
- *
- * 2) In read operations, the first byte of the OOB we return must reflect the
- * true state of the block mark, no matter where that block mark appears in
- * the physical page.
- *
- * 3) ECC-based read operations return an OOB full of set bits (since we never
- * allow ECC-based writes to the OOB, it doesn't matter what ECC-based reads
- * return).
- *
- * 4) "Raw" read operations return a direct view of the physical bytes in the
- * page, using the conventional definition of which bytes are data and which
- * are OOB. This gives the caller a way to see the actual, physical bytes
- * in the page, without the distortions applied by our ECC engine.
- *
- * What we do for this specific read operation depends on whether we're doing
- * "raw" read, or an ECC-based read.
- *
- * It turns out that knowing whether we want an "ECC-based" or "raw" read is not
- * easy. When reading a page, for example, the NAND Flash MTD code calls our
- * ecc.read_page or ecc.read_page_raw function. Thus, the fact that MTD wants an
- * ECC-based or raw view of the page is implicit in which function it calls
- * (there is a similar pair of ECC-based/raw functions for writing).
- *
- * Since MTD assumes the OOB is not covered by ECC, there is no pair of
- * ECC-based/raw functions for reading or or writing the OOB. The fact that the
- * caller wants an ECC-based or raw view of the page is not propagated down to
- * this driver.
- *
- * Since our OOB *is* covered by ECC, we need this information. So, we hook the
- * ecc.read_oob and ecc.write_oob function pointers in the owning
- * struct mtd_info with our own functions. These hook functions set the
- * raw_oob_mode field so that, when control finally arrives here, we'll know
- * what to do.
- */
-static int mxs_nand_ecc_read_oob(struct mtd_info *mtd, struct nand_chip *nand,
- int page)
-{
- struct mxs_nand_info *nand_info = nand->priv;
-
- /*
- * First, fill in the OOB buffer. If we're doing a raw read, we need to
- * get the bytes from the physical page. If we're not doing a raw read,
- * we need to fill the buffer with set bits.
- */
- if (nand_info->raw_oob_mode) {
- /*
- * If control arrives here, we're doing a "raw" read. Send the
- * command to read the conventional OOB and read it.
- */
- nand->cmdfunc(mtd, NAND_CMD_READ0, mtd->writesize, page);
- nand->read_buf(mtd, nand->oob_poi, mtd->oobsize);
- } else {
- /*
- * If control arrives here, we're not doing a "raw" read. Fill
- * the OOB buffer with set bits and correct the block mark.
- */
- memset(nand->oob_poi, 0xff, mtd->oobsize);
-
- nand->cmdfunc(mtd, NAND_CMD_READ0, mtd->writesize, page);
- mxs_nand_read_buf(mtd, nand->oob_poi, 1);
- }
-
- return 0;
-
-}
-
-/*
- * Write OOB data to NAND.
- */
-static int mxs_nand_ecc_write_oob(struct mtd_info *mtd, struct nand_chip *nand,
- int page)
-{
- struct mxs_nand_info *nand_info = nand->priv;
- uint8_t block_mark = 0;
-
- /*
- * There are fundamental incompatibilities between the i.MX GPMI NFC and
- * the NAND Flash MTD model that make it essentially impossible to write
- * the out-of-band bytes.
- *
- * We permit *ONE* exception. If the *intent* of writing the OOB is to
- * mark a block bad, we can do that.
- */
-
- if (!nand_info->marking_block_bad) {
- printf("NXS NAND: Writing OOB isn't supported\n");
- return -EIO;
- }
-
- /* Write the block mark. */
- nand->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize, page);
- nand->write_buf(mtd, &block_mark, 1);
- nand->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
-
- /* Check if it worked. */
- if (nand->waitfunc(mtd, nand) & NAND_STATUS_FAIL)
- return -EIO;
-
- return 0;
-}
-
-/*
- * Claims all blocks are good.
- *
- * In principle, this function is *only* called when the NAND Flash MTD system
- * isn't allowed to keep an in-memory bad block table, so it is forced to ask
- * the driver for bad block information.
- *
- * In fact, we permit the NAND Flash MTD system to have an in-memory BBT, so
- * this function is *only* called when we take it away.
- *
- * Thus, this function is only called when we want *all* blocks to look good,
- * so it *always* return success.
- */
-static int mxs_nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)
-{
- return 0;
-}
-
-/*
- * Nominally, the purpose of this function is to look for or create the bad
- * block table. In fact, since the we call this function at the very end of
- * the initialization process started by nand_scan(), and we doesn't have a
- * more formal mechanism, we "hook" this function to continue init process.
- *
- * At this point, the physical NAND Flash chips have been identified and
- * counted, so we know the physical geometry. This enables us to make some
- * important configuration decisions.
- *
- * The return value of this function propogates directly back to this driver's
- * call to nand_scan(). Anything other than zero will cause this driver to
- * tear everything down and declare failure.
- */
-static int mxs_nand_scan_bbt(struct mtd_info *mtd)
-{
- struct nand_chip *nand = mtd->priv;
- struct mxs_nand_info *nand_info = nand->priv;
- struct mxs_bch_regs *bch_regs = (struct mxs_bch_regs *)MXS_BCH_BASE;
- uint32_t tmp;
-
- /* Configure BCH and set NFC geometry */
- mxs_reset_block(&bch_regs->hw_bch_ctrl_reg);
-
- /* Configure layout 0 */
- tmp = (mxs_nand_ecc_chunk_cnt(mtd->writesize) - 1)
- << BCH_FLASHLAYOUT0_NBLOCKS_OFFSET;
- tmp |= MXS_NAND_METADATA_SIZE << BCH_FLASHLAYOUT0_META_SIZE_OFFSET;
- tmp |= (mxs_nand_get_ecc_strength(mtd->writesize, mtd->oobsize) >> 1)
- << BCH_FLASHLAYOUT0_ECC0_OFFSET;
- tmp |= MXS_NAND_CHUNK_DATA_CHUNK_SIZE
- >> MXS_NAND_CHUNK_DATA_CHUNK_SIZE_SHIFT;
- writel(tmp, &bch_regs->hw_bch_flash0layout0);
-
- tmp = (mtd->writesize + mtd->oobsize)
- << BCH_FLASHLAYOUT1_PAGE_SIZE_OFFSET;
- tmp |= (mxs_nand_get_ecc_strength(mtd->writesize, mtd->oobsize) >> 1)
- << BCH_FLASHLAYOUT1_ECCN_OFFSET;
- tmp |= MXS_NAND_CHUNK_DATA_CHUNK_SIZE
- >> MXS_NAND_CHUNK_DATA_CHUNK_SIZE_SHIFT;
- writel(tmp, &bch_regs->hw_bch_flash0layout1);
-
- /* Set *all* chip selects to use layout 0 */
- writel(0, &bch_regs->hw_bch_layoutselect);
-
- /* Enable BCH complete interrupt */
- writel(BCH_CTRL_COMPLETE_IRQ_EN, &bch_regs->hw_bch_ctrl_set);
-
- /* Hook some operations at the MTD level. */
- if (mtd->_read_oob != mxs_nand_hook_read_oob) {
- nand_info->hooked_read_oob = mtd->_read_oob;
- mtd->_read_oob = mxs_nand_hook_read_oob;
- }
-
- if (mtd->_write_oob != mxs_nand_hook_write_oob) {
- nand_info->hooked_write_oob = mtd->_write_oob;
- mtd->_write_oob = mxs_nand_hook_write_oob;
- }
-
- if (mtd->_block_markbad != mxs_nand_hook_block_markbad) {
- nand_info->hooked_block_markbad = mtd->_block_markbad;
- mtd->_block_markbad = mxs_nand_hook_block_markbad;
- }
-
- /* We use the reference implementation for bad block management. */
- return nand_default_bbt(mtd);
-}
-
-/*
- * Allocate DMA buffers
- */
-int mxs_nand_alloc_buffers(struct mxs_nand_info *nand_info)
-{
- uint8_t *buf;
- const int size = NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZE;
-
- nand_info->data_buf_size = roundup(size, MXS_DMA_ALIGNMENT);
-
- /* DMA buffers */
- buf = memalign(MXS_DMA_ALIGNMENT, nand_info->data_buf_size);
- if (!buf) {
- printf("MXS NAND: Error allocating DMA buffers\n");
- return -ENOMEM;
- }
-
- memset(buf, 0, nand_info->data_buf_size);
-
- nand_info->data_buf = buf;
- nand_info->oob_buf = buf + NAND_MAX_PAGESIZE;
- /* Command buffers */
- nand_info->cmd_buf = memalign(MXS_DMA_ALIGNMENT,
- MXS_NAND_COMMAND_BUFFER_SIZE);
- if (!nand_info->cmd_buf) {
- free(buf);
- printf("MXS NAND: Error allocating command buffers\n");
- return -ENOMEM;
- }
- memset(nand_info->cmd_buf, 0, MXS_NAND_COMMAND_BUFFER_SIZE);
- nand_info->cmd_queue_len = 0;
-
- return 0;
-}
-
-/*
- * Initializes the NFC hardware.
- */
-int mxs_nand_init(struct mxs_nand_info *info)
-{
- struct mxs_gpmi_regs *gpmi_regs =
- (struct mxs_gpmi_regs *)MXS_GPMI_BASE;
- struct mxs_bch_regs *bch_regs =
- (struct mxs_bch_regs *)MXS_BCH_BASE;
- int i = 0, j;
-
- info->desc = malloc(sizeof(struct mxs_dma_desc *) *
- MXS_NAND_DMA_DESCRIPTOR_COUNT);
- if (!info->desc)
- goto err1;
-
- /* Allocate the DMA descriptors. */
- for (i = 0; i < MXS_NAND_DMA_DESCRIPTOR_COUNT; i++) {
- info->desc[i] = mxs_dma_desc_alloc();
- if (!info->desc[i])
- goto err2;
- }
-
- /* Init the DMA controller. */
- for (j = MXS_DMA_CHANNEL_AHB_APBH_GPMI0;
- j <= MXS_DMA_CHANNEL_AHB_APBH_GPMI7; j++) {
- if (mxs_dma_init_channel(j))
- goto err3;
- }
-
- /* Reset the GPMI block. */
- mxs_reset_block(&gpmi_regs->hw_gpmi_ctrl0_reg);
- mxs_reset_block(&bch_regs->hw_bch_ctrl_reg);
-
- /*
- * Choose NAND mode, set IRQ polarity, disable write protection and
- * select BCH ECC.
- */
- clrsetbits_le32(&gpmi_regs->hw_gpmi_ctrl1,
- GPMI_CTRL1_GPMI_MODE,
- GPMI_CTRL1_ATA_IRQRDY_POLARITY | GPMI_CTRL1_DEV_RESET |
- GPMI_CTRL1_BCH_MODE);
-
- return 0;
-
-err3:
- for (--j; j >= 0; j--)
- mxs_dma_release(j);
-err2:
- free(info->desc);
-err1:
- for (--i; i >= 0; i--)
- mxs_dma_desc_free(info->desc[i]);
- printf("MXS NAND: Unable to allocate DMA descriptors\n");
- return -ENOMEM;
-}
-
-/*!
- * This function is called during the driver binding process.
- *
- * @param pdev the device structure used to store device specific
- * information that is used by the suspend, resume and
- * remove functions
- *
- * @return The function always returns 0.
- */
-int board_nand_init(struct nand_chip *nand)
-{
- struct mxs_nand_info *nand_info;
- int err;
-
- nand_info = malloc(sizeof(struct mxs_nand_info));
- if (!nand_info) {
- printf("MXS NAND: Failed to allocate private data\n");
- return -ENOMEM;
- }
- memset(nand_info, 0, sizeof(struct mxs_nand_info));
-
- err = mxs_nand_alloc_buffers(nand_info);
- if (err)
- goto err1;
-
- err = mxs_nand_init(nand_info);
- if (err)
- goto err2;
-
- memset(&fake_ecc_layout, 0, sizeof(fake_ecc_layout));
-
- nand->priv = nand_info;
- nand->options |= NAND_NO_SUBPAGE_WRITE;
-
- nand->cmd_ctrl = mxs_nand_cmd_ctrl;
-
- nand->dev_ready = mxs_nand_device_ready;
- nand->select_chip = mxs_nand_select_chip;
- nand->block_bad = mxs_nand_block_bad;
- nand->scan_bbt = mxs_nand_scan_bbt;
-
- nand->read_byte = mxs_nand_read_byte;
-
- nand->read_buf = mxs_nand_read_buf;
- nand->write_buf = mxs_nand_write_buf;
-
- nand->ecc.read_page = mxs_nand_ecc_read_page;
- nand->ecc.write_page = mxs_nand_ecc_write_page;
- nand->ecc.read_oob = mxs_nand_ecc_read_oob;
- nand->ecc.write_oob = mxs_nand_ecc_write_oob;
-
- nand->ecc.layout = &fake_ecc_layout;
- nand->ecc.mode = NAND_ECC_HW;
- nand->ecc.bytes = 9;
- nand->ecc.size = 512;
- nand->ecc.strength = 8;
-
- return 0;
-
-err2:
- free(nand_info->data_buf);
- free(nand_info->cmd_buf);
-err1:
- free(nand_info);
- return err;
-}
diff --git a/qemu/roms/u-boot/drivers/mtd/nand/nand.c b/qemu/roms/u-boot/drivers/mtd/nand/nand.c
deleted file mode 100644
index 4cf4c1c70..000000000
--- a/qemu/roms/u-boot/drivers/mtd/nand/nand.c
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * (C) Copyright 2005
- * 2N Telekomunikace, a.s. <www.2n.cz>
- * Ladislav Michl <michl@2n.cz>
- *
- * See file CREDITS for list of people who contributed to this
- * project.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
- * MA 02111-1307 USA
- */
-
-#include <common.h>
-#include <nand.h>
-#include <errno.h>
-
-#ifndef CONFIG_SYS_NAND_BASE_LIST
-#define CONFIG_SYS_NAND_BASE_LIST { CONFIG_SYS_NAND_BASE }
-#endif
-
-DECLARE_GLOBAL_DATA_PTR;
-
-int nand_curr_device = -1;
-
-
-nand_info_t nand_info[CONFIG_SYS_MAX_NAND_DEVICE];
-
-#ifndef CONFIG_SYS_NAND_SELF_INIT
-static struct nand_chip nand_chip[CONFIG_SYS_MAX_NAND_DEVICE];
-static ulong base_address[CONFIG_SYS_MAX_NAND_DEVICE] = CONFIG_SYS_NAND_BASE_LIST;
-#endif
-
-static char dev_name[CONFIG_SYS_MAX_NAND_DEVICE][8];
-
-static unsigned long total_nand_size; /* in kiB */
-
-/* Register an initialized NAND mtd device with the U-Boot NAND command. */
-int nand_register(int devnum)
-{
- struct mtd_info *mtd;
-
- if (devnum >= CONFIG_SYS_MAX_NAND_DEVICE)
- return -EINVAL;
-
- mtd = &nand_info[devnum];
-
- sprintf(dev_name[devnum], "nand%d", devnum);
- mtd->name = dev_name[devnum];
-
-#ifdef CONFIG_MTD_DEVICE
- /*
- * Add MTD device so that we can reference it later
- * via the mtdcore infrastructure (e.g. ubi).
- */
- add_mtd_device(mtd);
-#endif
-
- total_nand_size += mtd->size / 1024;
-
- if (nand_curr_device == -1)
- nand_curr_device = devnum;
-
- return 0;
-}
-
-#ifndef CONFIG_SYS_NAND_SELF_INIT
-static void nand_init_chip(int i)
-{
- struct mtd_info *mtd = &nand_info[i];
- struct nand_chip *nand = &nand_chip[i];
- ulong base_addr = base_address[i];
- int maxchips = CONFIG_SYS_NAND_MAX_CHIPS;
-
- if (maxchips < 1)
- maxchips = 1;
-
- mtd->priv = nand;
- nand->IO_ADDR_R = nand->IO_ADDR_W = (void __iomem *)base_addr;
-
- if (board_nand_init(nand))
- return;
-
- if (nand_scan(mtd, maxchips))
- return;
-
- nand_register(i);
-}
-#endif
-
-void nand_init(void)
-{
-#ifdef CONFIG_SYS_NAND_SELF_INIT
- board_nand_init();
-#else
- int i;
-
- for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++)
- nand_init_chip(i);
-#endif
-
- printf("%lu MiB\n", total_nand_size / 1024);
-
-#ifdef CONFIG_SYS_NAND_SELECT_DEVICE
- /*
- * Select the chip in the board/cpu specific driver
- */
- board_nand_select_device(nand_info[nand_curr_device].priv, nand_curr_device);
-#endif
-}
diff --git a/qemu/roms/u-boot/drivers/mtd/nand/nand_base.c b/qemu/roms/u-boot/drivers/mtd/nand/nand_base.c
deleted file mode 100644
index 1ce55fde8..000000000
--- a/qemu/roms/u-boot/drivers/mtd/nand/nand_base.c
+++ /dev/null
@@ -1,3438 +0,0 @@
-/*
- * drivers/mtd/nand.c
- *
- * Overview:
- * This is the generic MTD driver for NAND flash devices. It should be
- * capable of working with almost all NAND chips currently available.
- * Basic support for AG-AND chips is provided.
- *
- * Additional technical information is available on
- * http://www.linux-mtd.infradead.org/doc/nand.html
- *
- * Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com)
- * 2002-2006 Thomas Gleixner (tglx@linutronix.de)
- *
- * Credits:
- * David Woodhouse for adding multichip support
- *
- * Aleph One Ltd. and Toby Churchill Ltd. for supporting the
- * rework for 2K page size chips
- *
- * TODO:
- * Enable cached programming for 2k page size chips
- * Check, if mtd->ecctype should be set to MTD_ECC_HW
- * if we have HW ECC support.
- * The AG-AND chips have nice features for speed improvement,
- * which are not supported yet. Read / program 4 pages in one go.
- * BBT table is not serialized, has to be fixed
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- */
-
-#include <common.h>
-
-#define ENOTSUPP 524 /* Operation is not supported */
-
-#include <malloc.h>
-#include <watchdog.h>
-#include <linux/err.h>
-#include <linux/compat.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
-#include <linux/mtd/nand_ecc.h>
-#include <linux/mtd/nand_bch.h>
-
-#ifdef CONFIG_MTD_PARTITIONS
-#include <linux/mtd/partitions.h>
-#endif
-
-#include <asm/io.h>
-#include <asm/errno.h>
-
-/*
- * CONFIG_SYS_NAND_RESET_CNT is used as a timeout mechanism when resetting
- * a flash. NAND flash is initialized prior to interrupts so standard timers
- * can't be used. CONFIG_SYS_NAND_RESET_CNT should be set to a value
- * which is greater than (max NAND reset time / NAND status read time).
- * A conservative default of 200000 (500 us / 25 ns) is used as a default.
- */
-#ifndef CONFIG_SYS_NAND_RESET_CNT
-#define CONFIG_SYS_NAND_RESET_CNT 200000
-#endif
-
-/* Define default oob placement schemes for large and small page devices */
-static struct nand_ecclayout nand_oob_8 = {
- .eccbytes = 3,
- .eccpos = {0, 1, 2},
- .oobfree = {
- {.offset = 3,
- .length = 2},
- {.offset = 6,
- .length = 2} }
-};
-
-static struct nand_ecclayout nand_oob_16 = {
- .eccbytes = 6,
- .eccpos = {0, 1, 2, 3, 6, 7},
- .oobfree = {
- {.offset = 8,
- . length = 8} }
-};
-
-static struct nand_ecclayout nand_oob_64 = {
- .eccbytes = 24,
- .eccpos = {
- 40, 41, 42, 43, 44, 45, 46, 47,
- 48, 49, 50, 51, 52, 53, 54, 55,
- 56, 57, 58, 59, 60, 61, 62, 63},
- .oobfree = {
- {.offset = 2,
- .length = 38} }
-};
-
-static struct nand_ecclayout nand_oob_128 = {
- .eccbytes = 48,
- .eccpos = {
- 80, 81, 82, 83, 84, 85, 86, 87,
- 88, 89, 90, 91, 92, 93, 94, 95,
- 96, 97, 98, 99, 100, 101, 102, 103,
- 104, 105, 106, 107, 108, 109, 110, 111,
- 112, 113, 114, 115, 116, 117, 118, 119,
- 120, 121, 122, 123, 124, 125, 126, 127},
- .oobfree = {
- {.offset = 2,
- .length = 78} }
-};
-
-static int nand_get_device(struct nand_chip *chip, struct mtd_info *mtd,
- int new_state);
-
-static int nand_do_write_oob(struct mtd_info *mtd, loff_t to,
- struct mtd_oob_ops *ops);
-
-static int nand_wait(struct mtd_info *mtd, struct nand_chip *this);
-
-static int check_offs_len(struct mtd_info *mtd,
- loff_t ofs, uint64_t len)
-{
- struct nand_chip *chip = mtd->priv;
- int ret = 0;
-
- /* Start address must align on block boundary */
- if (ofs & ((1 << chip->phys_erase_shift) - 1)) {
- MTDDEBUG(MTD_DEBUG_LEVEL0, "%s: Unaligned address\n", __func__);
- ret = -EINVAL;
- }
-
- /* Length must align on block boundary */
- if (len & ((1 << chip->phys_erase_shift) - 1)) {
- MTDDEBUG(MTD_DEBUG_LEVEL0, "%s: Length not block aligned\n",
- __func__);
- ret = -EINVAL;
- }
-
- return ret;
-}
-
-/**
- * nand_release_device - [GENERIC] release chip
- * @mtd: MTD device structure
- *
- * Deselect, release chip lock and wake up anyone waiting on the device.
- */
-static void nand_release_device(struct mtd_info *mtd)
-{
- struct nand_chip *chip = mtd->priv;
-
- /* De-select the NAND device */
- chip->select_chip(mtd, -1);
-}
-
-/**
- * nand_read_byte - [DEFAULT] read one byte from the chip
- * @mtd: MTD device structure
- *
- * Default read function for 8bit buswidth.
- */
-uint8_t nand_read_byte(struct mtd_info *mtd)
-{
- struct nand_chip *chip = mtd->priv;
- return readb(chip->IO_ADDR_R);
-}
-
-/**
- * nand_read_byte16 - [DEFAULT] read one byte endianess aware from the chip
- * nand_read_byte16 - [DEFAULT] read one byte endianness aware from the chip
- * @mtd: MTD device structure
- *
- * Default read function for 16bit buswidth with endianness conversion.
- *
- */
-static uint8_t nand_read_byte16(struct mtd_info *mtd)
-{
- struct nand_chip *chip = mtd->priv;
- return (uint8_t) cpu_to_le16(readw(chip->IO_ADDR_R));
-}
-
-/**
- * nand_read_word - [DEFAULT] read one word from the chip
- * @mtd: MTD device structure
- *
- * Default read function for 16bit buswidth without endianness conversion.
- */
-static u16 nand_read_word(struct mtd_info *mtd)
-{
- struct nand_chip *chip = mtd->priv;
- return readw(chip->IO_ADDR_R);
-}
-
-/**
- * nand_select_chip - [DEFAULT] control CE line
- * @mtd: MTD device structure
- * @chipnr: chipnumber to select, -1 for deselect
- *
- * Default select function for 1 chip devices.
- */
-static void nand_select_chip(struct mtd_info *mtd, int chipnr)
-{
- struct nand_chip *chip = mtd->priv;
-
- switch (chipnr) {
- case -1:
- chip->cmd_ctrl(mtd, NAND_CMD_NONE, 0 | NAND_CTRL_CHANGE);
- break;
- case 0:
- break;
-
- default:
- BUG();
- }
-}
-
-/**
- * nand_write_buf - [DEFAULT] write buffer to chip
- * @mtd: MTD device structure
- * @buf: data buffer
- * @len: number of bytes to write
- *
- * Default write function for 8bit buswidth.
- */
-void nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
-{
- int i;
- struct nand_chip *chip = mtd->priv;
-
- for (i = 0; i < len; i++)
- writeb(buf[i], chip->IO_ADDR_W);
-}
-
-/**
- * nand_read_buf - [DEFAULT] read chip data into buffer
- * @mtd: MTD device structure
- * @buf: buffer to store date
- * @len: number of bytes to read
- *
- * Default read function for 8bit buswidth.
- */
-void nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
-{
- int i;
- struct nand_chip *chip = mtd->priv;
-
- for (i = 0; i < len; i++)
- buf[i] = readb(chip->IO_ADDR_R);
-}
-
-/**
- * nand_verify_buf - [DEFAULT] Verify chip data against buffer
- * @mtd: MTD device structure
- * @buf: buffer containing the data to compare
- * @len: number of bytes to compare
- *
- * Default verify function for 8bit buswidth.
- */
-static int nand_verify_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
-{
- int i;
- struct nand_chip *chip = mtd->priv;
-
- for (i = 0; i < len; i++)
- if (buf[i] != readb(chip->IO_ADDR_R))
- return -EFAULT;
- return 0;
-}
-
-/**
- * nand_write_buf16 - [DEFAULT] write buffer to chip
- * @mtd: MTD device structure
- * @buf: data buffer
- * @len: number of bytes to write
- *
- * Default write function for 16bit buswidth.
- */
-void nand_write_buf16(struct mtd_info *mtd, const uint8_t *buf, int len)
-{
- int i;
- struct nand_chip *chip = mtd->priv;
- u16 *p = (u16 *) buf;
- len >>= 1;
-
- for (i = 0; i < len; i++)
- writew(p[i], chip->IO_ADDR_W);
-
-}
-
-/**
- * nand_read_buf16 - [DEFAULT] read chip data into buffer
- * @mtd: MTD device structure
- * @buf: buffer to store date
- * @len: number of bytes to read
- *
- * Default read function for 16bit buswidth.
- */
-void nand_read_buf16(struct mtd_info *mtd, uint8_t *buf, int len)
-{
- int i;
- struct nand_chip *chip = mtd->priv;
- u16 *p = (u16 *) buf;
- len >>= 1;
-
- for (i = 0; i < len; i++)
- p[i] = readw(chip->IO_ADDR_R);
-}
-
-/**
- * nand_verify_buf16 - [DEFAULT] Verify chip data against buffer
- * @mtd: MTD device structure
- * @buf: buffer containing the data to compare
- * @len: number of bytes to compare
- *
- * Default verify function for 16bit buswidth.
- */
-static int nand_verify_buf16(struct mtd_info *mtd, const uint8_t *buf, int len)
-{
- int i;
- struct nand_chip *chip = mtd->priv;
- u16 *p = (u16 *) buf;
- len >>= 1;
-
- for (i = 0; i < len; i++)
- if (p[i] != readw(chip->IO_ADDR_R))
- return -EFAULT;
-
- return 0;
-}
-
-/**
- * nand_block_bad - [DEFAULT] Read bad block marker from the chip
- * @mtd: MTD device structure
- * @ofs: offset from device start
- * @getchip: 0, if the chip is already selected
- *
- * Check, if the block is bad.
- */
-static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)
-{
- int page, chipnr, res = 0, i = 0;
- struct nand_chip *chip = mtd->priv;
- u16 bad;
-
- if (chip->bbt_options & NAND_BBT_SCANLASTPAGE)
- ofs += mtd->erasesize - mtd->writesize;
-
- page = (int)(ofs >> chip->page_shift) & chip->pagemask;
-
- if (getchip) {
- chipnr = (int)(ofs >> chip->chip_shift);
-
- nand_get_device(chip, mtd, FL_READING);
-
- /* Select the NAND device */
- chip->select_chip(mtd, chipnr);
- }
-
- do {
- if (chip->options & NAND_BUSWIDTH_16) {
- chip->cmdfunc(mtd, NAND_CMD_READOOB,
- chip->badblockpos & 0xFE, page);
- bad = cpu_to_le16(chip->read_word(mtd));
- if (chip->badblockpos & 0x1)
- bad >>= 8;
- else
- bad &= 0xFF;
- } else {
- chip->cmdfunc(mtd, NAND_CMD_READOOB, chip->badblockpos,
- page);
- bad = chip->read_byte(mtd);
- }
-
- if (likely(chip->badblockbits == 8))
- res = bad != 0xFF;
- else
- res = hweight8(bad) < chip->badblockbits;
- ofs += mtd->writesize;
- page = (int)(ofs >> chip->page_shift) & chip->pagemask;
- i++;
- } while (!res && i < 2 && (chip->bbt_options & NAND_BBT_SCAN2NDPAGE));
-
- if (getchip)
- nand_release_device(mtd);
-
- return res;
-}
-
-/**
- * nand_default_block_markbad - [DEFAULT] mark a block bad
- * @mtd: MTD device structure
- * @ofs: offset from device start
- *
- * This is the default implementation, which can be overridden by a hardware
- * specific driver. We try operations in the following order, according to our
- * bbt_options (NAND_BBT_NO_OOB_BBM and NAND_BBT_USE_FLASH):
- * (1) erase the affected block, to allow OOB marker to be written cleanly
- * (2) update in-memory BBT
- * (3) write bad block marker to OOB area of affected block
- * (4) update flash-based BBT
- * Note that we retain the first error encountered in (3) or (4), finish the
- * procedures, and dump the error in the end.
-*/
-static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
-{
- struct nand_chip *chip = mtd->priv;
- uint8_t buf[2] = { 0, 0 };
- int block, res, ret = 0, i = 0;
- int write_oob = !(chip->bbt_options & NAND_BBT_NO_OOB_BBM);
-
- if (write_oob) {
- struct erase_info einfo;
-
- /* Attempt erase before marking OOB */
- memset(&einfo, 0, sizeof(einfo));
- einfo.mtd = mtd;
- einfo.addr = ofs;
- einfo.len = 1 << chip->phys_erase_shift;
- nand_erase_nand(mtd, &einfo, 0);
- }
-
- /* Get block number */
- block = (int)(ofs >> chip->bbt_erase_shift);
- /* Mark block bad in memory-based BBT */
- if (chip->bbt)
- chip->bbt[block >> 2] |= 0x01 << ((block & 0x03) << 1);
-
- /* Write bad block marker to OOB */
- if (write_oob) {
- struct mtd_oob_ops ops;
- loff_t wr_ofs = ofs;
-
- nand_get_device(chip, mtd, FL_WRITING);
-
- ops.datbuf = NULL;
- ops.oobbuf = buf;
- ops.ooboffs = chip->badblockpos;
- if (chip->options & NAND_BUSWIDTH_16) {
- ops.ooboffs &= ~0x01;
- ops.len = ops.ooblen = 2;
- } else {
- ops.len = ops.ooblen = 1;
- }
- ops.mode = MTD_OPS_PLACE_OOB;
-
- /* Write to first/last page(s) if necessary */
- if (chip->bbt_options & NAND_BBT_SCANLASTPAGE)
- wr_ofs += mtd->erasesize - mtd->writesize;
- do {
- res = nand_do_write_oob(mtd, wr_ofs, &ops);
- if (!ret)
- ret = res;
-
- i++;
- wr_ofs += mtd->writesize;
- } while ((chip->bbt_options & NAND_BBT_SCAN2NDPAGE) && i < 2);
-
- nand_release_device(mtd);
- }
-
- /* Update flash-based bad block table */
- if (chip->bbt_options & NAND_BBT_USE_FLASH) {
- res = nand_update_bbt(mtd, ofs);
- if (!ret)
- ret = res;
- }
-
- if (!ret)
- mtd->ecc_stats.badblocks++;
-
- return ret;
-}
-
-/**
- * nand_check_wp - [GENERIC] check if the chip is write protected
- * @mtd: MTD device structure
- *
- * Check, if the device is write protected. The function expects, that the
- * device is already selected.
- */
-static int nand_check_wp(struct mtd_info *mtd)
-{
- struct nand_chip *chip = mtd->priv;
-
- /* Broken xD cards report WP despite being writable */
- if (chip->options & NAND_BROKEN_XD)
- return 0;
-
- /* Check the WP bit */
- chip->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1);
- return (chip->read_byte(mtd) & NAND_STATUS_WP) ? 0 : 1;
-}
-
-/**
- * nand_block_checkbad - [GENERIC] Check if a block is marked bad
- * @mtd: MTD device structure
- * @ofs: offset from device start
- * @getchip: 0, if the chip is already selected
- * @allowbbt: 1, if its allowed to access the bbt area
- *
- * Check, if the block is bad. Either by reading the bad block table or
- * calling of the scan function.
- */
-static int nand_block_checkbad(struct mtd_info *mtd, loff_t ofs, int getchip,
- int allowbbt)
-{
- struct nand_chip *chip = mtd->priv;
-
- if (!(chip->options & NAND_BBT_SCANNED)) {
- chip->options |= NAND_BBT_SCANNED;
- chip->scan_bbt(mtd);
- }
-
- if (!chip->bbt)
- return chip->block_bad(mtd, ofs, getchip);
-
- /* Return info from the table */
- return nand_isbad_bbt(mtd, ofs, allowbbt);
-}
-
-/* Wait for the ready pin, after a command. The timeout is caught later. */
-void nand_wait_ready(struct mtd_info *mtd)
-{
- struct nand_chip *chip = mtd->priv;
- u32 timeo = (CONFIG_SYS_HZ * 20) / 1000;
- u32 time_start;
-
- time_start = get_timer(0);
-
- /* Wait until command is processed or timeout occurs */
- while (get_timer(time_start) < timeo) {
- if (chip->dev_ready)
- if (chip->dev_ready(mtd))
- break;
- }
-}
-
-/**
- * nand_command - [DEFAULT] Send command to NAND device
- * @mtd: MTD device structure
- * @command: the command to be sent
- * @column: the column address for this command, -1 if none
- * @page_addr: the page address for this command, -1 if none
- *
- * Send command to NAND device. This function is used for small page devices
- * (256/512 Bytes per page).
- */
-static void nand_command(struct mtd_info *mtd, unsigned int command,
- int column, int page_addr)
-{
- register struct nand_chip *chip = mtd->priv;
- int ctrl = NAND_CTRL_CLE | NAND_CTRL_CHANGE;
- uint32_t rst_sts_cnt = CONFIG_SYS_NAND_RESET_CNT;
-
- /* Write out the command to the device */
- if (command == NAND_CMD_SEQIN) {
- int readcmd;
-
- if (column >= mtd->writesize) {
- /* OOB area */
- column -= mtd->writesize;
- readcmd = NAND_CMD_READOOB;
- } else if (column < 256) {
- /* First 256 bytes --> READ0 */
- readcmd = NAND_CMD_READ0;
- } else {
- column -= 256;
- readcmd = NAND_CMD_READ1;
- }
- chip->cmd_ctrl(mtd, readcmd, ctrl);
- ctrl &= ~NAND_CTRL_CHANGE;
- }
- chip->cmd_ctrl(mtd, command, ctrl);
-
- /* Address cycle, when necessary */
- ctrl = NAND_CTRL_ALE | NAND_CTRL_CHANGE;
- /* Serially input address */
- if (column != -1) {
- /* Adjust columns for 16 bit buswidth */
- if (chip->options & NAND_BUSWIDTH_16)
- column >>= 1;
- chip->cmd_ctrl(mtd, column, ctrl);
- ctrl &= ~NAND_CTRL_CHANGE;
- }
- if (page_addr != -1) {
- chip->cmd_ctrl(mtd, page_addr, ctrl);
- ctrl &= ~NAND_CTRL_CHANGE;
- chip->cmd_ctrl(mtd, page_addr >> 8, ctrl);
- /* One more address cycle for devices > 32MiB */
- if (chip->chipsize > (32 << 20))
- chip->cmd_ctrl(mtd, page_addr >> 16, ctrl);
- }
- chip->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
-
- /*
- * Program and erase have their own busy handlers status and sequential
- * in needs no delay
- */
- switch (command) {
-
- case NAND_CMD_PAGEPROG:
- case NAND_CMD_ERASE1:
- case NAND_CMD_ERASE2:
- case NAND_CMD_SEQIN:
- case NAND_CMD_STATUS:
- return;
-
- case NAND_CMD_RESET:
- if (chip->dev_ready)
- break;
- udelay(chip->chip_delay);
- chip->cmd_ctrl(mtd, NAND_CMD_STATUS,
- NAND_CTRL_CLE | NAND_CTRL_CHANGE);
- chip->cmd_ctrl(mtd,
- NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
- while (!(chip->read_byte(mtd) & NAND_STATUS_READY) &&
- (rst_sts_cnt--));
- return;
-
- /* This applies to read commands */
- default:
- /*
- * If we don't have access to the busy pin, we apply the given
- * command delay
- */
- if (!chip->dev_ready) {
- udelay(chip->chip_delay);
- return;
- }
- }
- /*
- * Apply this short delay always to ensure that we do wait tWB in
- * any case on any machine.
- */
- ndelay(100);
-
- nand_wait_ready(mtd);
-}
-
-/**
- * nand_command_lp - [DEFAULT] Send command to NAND large page device
- * @mtd: MTD device structure
- * @command: the command to be sent
- * @column: the column address for this command, -1 if none
- * @page_addr: the page address for this command, -1 if none
- *
- * Send command to NAND device. This is the version for the new large page
- * devices. We don't have the separate regions as we have in the small page
- * devices. We must emulate NAND_CMD_READOOB to keep the code compatible.
- */
-static void nand_command_lp(struct mtd_info *mtd, unsigned int command,
- int column, int page_addr)
-{
- register struct nand_chip *chip = mtd->priv;
- uint32_t rst_sts_cnt = CONFIG_SYS_NAND_RESET_CNT;
-
- /* Emulate NAND_CMD_READOOB */
- if (command == NAND_CMD_READOOB) {
- column += mtd->writesize;
- command = NAND_CMD_READ0;
- }
-
- /* Command latch cycle */
- chip->cmd_ctrl(mtd, command & 0xff,
- NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE);
-
- if (column != -1 || page_addr != -1) {
- int ctrl = NAND_CTRL_CHANGE | NAND_NCE | NAND_ALE;
-
- /* Serially input address */
- if (column != -1) {
- /* Adjust columns for 16 bit buswidth */
- if (chip->options & NAND_BUSWIDTH_16)
- column >>= 1;
- chip->cmd_ctrl(mtd, column, ctrl);
- ctrl &= ~NAND_CTRL_CHANGE;
- chip->cmd_ctrl(mtd, column >> 8, ctrl);
- }
- if (page_addr != -1) {
- chip->cmd_ctrl(mtd, page_addr, ctrl);
- chip->cmd_ctrl(mtd, page_addr >> 8,
- NAND_NCE | NAND_ALE);
- /* One more address cycle for devices > 128MiB */
- if (chip->chipsize > (128 << 20))
- chip->cmd_ctrl(mtd, page_addr >> 16,
- NAND_NCE | NAND_ALE);
- }
- }
- chip->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
-
- /*
- * Program and erase have their own busy handlers status, sequential
- * in, and deplete1 need no delay.
- */
- switch (command) {
-
- case NAND_CMD_CACHEDPROG:
- case NAND_CMD_PAGEPROG:
- case NAND_CMD_ERASE1:
- case NAND_CMD_ERASE2:
- case NAND_CMD_SEQIN:
- case NAND_CMD_RNDIN:
- case NAND_CMD_STATUS:
- case NAND_CMD_DEPLETE1:
- return;
-
- case NAND_CMD_STATUS_ERROR:
- case NAND_CMD_STATUS_ERROR0:
- case NAND_CMD_STATUS_ERROR1:
- case NAND_CMD_STATUS_ERROR2:
- case NAND_CMD_STATUS_ERROR3:
- /* Read error status commands require only a short delay */
- udelay(chip->chip_delay);
- return;
-
- case NAND_CMD_RESET:
- if (chip->dev_ready)
- break;
- udelay(chip->chip_delay);
- chip->cmd_ctrl(mtd, NAND_CMD_STATUS,
- NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE);
- chip->cmd_ctrl(mtd, NAND_CMD_NONE,
- NAND_NCE | NAND_CTRL_CHANGE);
- while (!(chip->read_byte(mtd) & NAND_STATUS_READY) &&
- (rst_sts_cnt--));
- return;
-
- case NAND_CMD_RNDOUT:
- /* No ready / busy check necessary */
- chip->cmd_ctrl(mtd, NAND_CMD_RNDOUTSTART,
- NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE);
- chip->cmd_ctrl(mtd, NAND_CMD_NONE,
- NAND_NCE | NAND_CTRL_CHANGE);
- return;
-
- case NAND_CMD_READ0:
- chip->cmd_ctrl(mtd, NAND_CMD_READSTART,
- NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE);
- chip->cmd_ctrl(mtd, NAND_CMD_NONE,
- NAND_NCE | NAND_CTRL_CHANGE);
-
- /* This applies to read commands */
- default:
- /*
- * If we don't have access to the busy pin, we apply the given
- * command delay.
- */
- if (!chip->dev_ready) {
- udelay(chip->chip_delay);
- return;
- }
- }
-
- /*
- * Apply this short delay always to ensure that we do wait tWB in
- * any case on any machine.
- */
- ndelay(100);
-
- nand_wait_ready(mtd);
-}
-
-/**
- * nand_get_device - [GENERIC] Get chip for selected access
- * @chip: the nand chip descriptor
- * @mtd: MTD device structure
- * @new_state: the state which is requested
- *
- * Get the device and lock it for exclusive access
- */
-static int
-nand_get_device(struct nand_chip *chip, struct mtd_info *mtd, int new_state)
-{
- chip->state = new_state;
- return 0;
-}
-
-/**
- * nand_wait - [DEFAULT] wait until the command is done
- * @mtd: MTD device structure
- * @chip: NAND chip structure
- *
- * Wait for command done. This applies to erase and program only. Erase can
- * take up to 400ms and program up to 20ms according to general NAND and
- * SmartMedia specs.
- */
-static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip)
-{
- unsigned long timeo;
- int state = chip->state;
- u32 time_start;
-
- if (state == FL_ERASING)
- timeo = (CONFIG_SYS_HZ * 400) / 1000;
- else
- timeo = (CONFIG_SYS_HZ * 20) / 1000;
-
- if ((state == FL_ERASING) && (chip->options & NAND_IS_AND))
- chip->cmdfunc(mtd, NAND_CMD_STATUS_MULTI, -1, -1);
- else
- chip->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1);
-
- time_start = get_timer(0);
-
- while (1) {
- if (get_timer(time_start) > timeo) {
- printf("Timeout!");
- return 0x01;
- }
-
- if (chip->dev_ready) {
- if (chip->dev_ready(mtd))
- break;
- } else {
- if (chip->read_byte(mtd) & NAND_STATUS_READY)
- break;
- }
- }
-#ifdef PPCHAMELON_NAND_TIMER_HACK
- time_start = get_timer(0);
- while (get_timer(time_start) < 10)
- ;
-#endif /* PPCHAMELON_NAND_TIMER_HACK */
-
- return (int)chip->read_byte(mtd);
-}
-
-/**
- * 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 nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
- uint8_t *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;
-}
-
-/**
- * nand_read_page_raw_syndrome - [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
- *
- * We need a special oob layout and handling even when OOB isn't used.
- */
-static int nand_read_page_raw_syndrome(struct mtd_info *mtd,
- struct nand_chip *chip, uint8_t *buf,
- int oob_required, int page)
-{
- int eccsize = chip->ecc.size;
- int eccbytes = chip->ecc.bytes;
- uint8_t *oob = chip->oob_poi;
- int steps, size;
-
- for (steps = chip->ecc.steps; steps > 0; steps--) {
- chip->read_buf(mtd, buf, eccsize);
- buf += eccsize;
-
- if (chip->ecc.prepad) {
- chip->read_buf(mtd, oob, chip->ecc.prepad);
- oob += chip->ecc.prepad;
- }
-
- chip->read_buf(mtd, oob, eccbytes);
- oob += eccbytes;
-
- if (chip->ecc.postpad) {
- chip->read_buf(mtd, oob, chip->ecc.postpad);
- oob += chip->ecc.postpad;
- }
- }
-
- size = mtd->oobsize - (oob - chip->oob_poi);
- if (size)
- chip->read_buf(mtd, oob, size);
-
- return 0;
-}
-
-/**
- * nand_read_page_swecc - [REPLACEABLE] software ECC based page read function
- * @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
- */
-static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
- uint8_t *buf, int oob_required, int page)
-{
- int i, eccsize = chip->ecc.size;
- int eccbytes = chip->ecc.bytes;
- int eccsteps = chip->ecc.steps;
- 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;
-
- chip->ecc.read_page_raw(mtd, chip, buf, 1, page);
-
- for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize)
- chip->ecc.calculate(mtd, p, &ecc_calc[i]);
-
- for (i = 0; i < chip->ecc.total; i++)
- ecc_code[i] = chip->oob_poi[eccpos[i]];
-
- eccsteps = chip->ecc.steps;
- p = buf;
-
- for (i = 0 ; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
- int stat;
-
- stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]);
- if (stat < 0)
- mtd->ecc_stats.failed++;
- else
- mtd->ecc_stats.corrected += stat;
- }
- return 0;
-}
-
-/**
- * nand_read_subpage - [REPLACEABLE] software ECC based sub-page read function
- * @mtd: mtd info structure
- * @chip: nand chip info structure
- * @data_offs: offset of requested data within the page
- * @readlen: data length
- * @bufpoi: buffer to store read data
- */
-static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip,
- uint32_t data_offs, uint32_t readlen, uint8_t *bufpoi)
-{
- int start_step, end_step, num_steps;
- uint32_t *eccpos = chip->ecc.layout->eccpos;
- uint8_t *p;
- int data_col_addr, i, gaps = 0;
- int datafrag_len, eccfrag_len, aligned_len, aligned_pos;
- int busw = (chip->options & NAND_BUSWIDTH_16) ? 2 : 1;
- int index = 0;
-
- /* Column address within the page aligned to ECC size (256bytes) */
- start_step = data_offs / chip->ecc.size;
- end_step = (data_offs + readlen - 1) / chip->ecc.size;
- num_steps = end_step - start_step + 1;
-
- /* Data size aligned to ECC ecc.size */
- datafrag_len = num_steps * chip->ecc.size;
- eccfrag_len = num_steps * chip->ecc.bytes;
-
- data_col_addr = start_step * chip->ecc.size;
- /* If we read not a page aligned data */
- if (data_col_addr != 0)
- chip->cmdfunc(mtd, NAND_CMD_RNDOUT, data_col_addr, -1);
-
- p = bufpoi + data_col_addr;
- chip->read_buf(mtd, p, datafrag_len);
-
- /* Calculate ECC */
- for (i = 0; i < eccfrag_len ; i += chip->ecc.bytes, p += chip->ecc.size)
- chip->ecc.calculate(mtd, p, &chip->buffers->ecccalc[i]);
-
- /*
- * The performance is faster if we position offsets according to
- * ecc.pos. Let's make sure that there are no gaps in ECC positions.
- */
- for (i = 0; i < eccfrag_len - 1; i++) {
- if (eccpos[i + start_step * chip->ecc.bytes] + 1 !=
- eccpos[i + start_step * chip->ecc.bytes + 1]) {
- gaps = 1;
- break;
- }
- }
- if (gaps) {
- chip->cmdfunc(mtd, NAND_CMD_RNDOUT, mtd->writesize, -1);
- chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
- } else {
- /*
- * Send the command to read the particular ECC bytes take care
- * about buswidth alignment in read_buf.
- */
- index = start_step * chip->ecc.bytes;
-
- aligned_pos = eccpos[index] & ~(busw - 1);
- aligned_len = eccfrag_len;
- if (eccpos[index] & (busw - 1))
- aligned_len++;
- if (eccpos[index + (num_steps * chip->ecc.bytes)] & (busw - 1))
- aligned_len++;
-
- chip->cmdfunc(mtd, NAND_CMD_RNDOUT,
- mtd->writesize + aligned_pos, -1);
- chip->read_buf(mtd, &chip->oob_poi[aligned_pos], aligned_len);
- }
-
- for (i = 0; i < eccfrag_len; i++)
- chip->buffers->ecccode[i] = chip->oob_poi[eccpos[i + index]];
-
- p = bufpoi + data_col_addr;
- for (i = 0; i < eccfrag_len ; i += chip->ecc.bytes, p += chip->ecc.size) {
- int stat;
-
- stat = chip->ecc.correct(mtd, p,
- &chip->buffers->ecccode[i], &chip->buffers->ecccalc[i]);
- if (stat < 0)
- mtd->ecc_stats.failed++;
- else
- mtd->ecc_stats.corrected += stat;
- }
- return 0;
-}
-
-/**
- * nand_read_page_hwecc - [REPLACEABLE] hardware ECC based page read function
- * @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 need a special oob layout.
- */
-static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
- uint8_t *buf, int oob_required, int page)
-{
- int i, eccsize = chip->ecc.size;
- int eccbytes = chip->ecc.bytes;
- int eccsteps = chip->ecc.steps;
- 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;
-
- for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
- chip->ecc.hwctl(mtd, NAND_ECC_READ);
- chip->read_buf(mtd, p, eccsize);
- chip->ecc.calculate(mtd, p, &ecc_calc[i]);
- }
- chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
-
- for (i = 0; i < chip->ecc.total; i++)
- ecc_code[i] = chip->oob_poi[eccpos[i]];
-
- eccsteps = chip->ecc.steps;
- p = buf;
-
- for (i = 0 ; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
- int stat;
-
- stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]);
- if (stat < 0)
- mtd->ecc_stats.failed++;
- else
- mtd->ecc_stats.corrected += stat;
- }
- return 0;
-}
-
-/**
- * nand_read_page_hwecc_oob_first - [REPLACEABLE] hw ecc, read oob first
- * @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
- *
- * Hardware ECC for large page chips, require OOB to be read first. For this
- * ECC mode, the write_page method is re-used from ECC_HW. These methods
- * read/write ECC from the OOB area, unlike the ECC_HW_SYNDROME support with
- * multiple ECC steps, follows the "infix ECC" scheme and reads/writes ECC from
- * the data area, by overwriting the NAND manufacturer bad block markings.
- */
-static int nand_read_page_hwecc_oob_first(struct mtd_info *mtd,
- struct nand_chip *chip, uint8_t *buf, int oob_required, int page)
-{
- int i, eccsize = chip->ecc.size;
- int eccbytes = chip->ecc.bytes;
- int eccsteps = chip->ecc.steps;
- uint8_t *p = buf;
- uint8_t *ecc_code = chip->buffers->ecccode;
- uint32_t *eccpos = chip->ecc.layout->eccpos;
- uint8_t *ecc_calc = chip->buffers->ecccalc;
-
- /* Read the OOB area first */
- chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page);
- chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
- chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page);
-
- for (i = 0; i < chip->ecc.total; i++)
- ecc_code[i] = chip->oob_poi[eccpos[i]];
-
- for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
- int stat;
-
- chip->ecc.hwctl(mtd, NAND_ECC_READ);
- chip->read_buf(mtd, p, eccsize);
- chip->ecc.calculate(mtd, p, &ecc_calc[i]);
-
- stat = chip->ecc.correct(mtd, p, &ecc_code[i], NULL);
- if (stat < 0)
- mtd->ecc_stats.failed++;
- else
- mtd->ecc_stats.corrected += stat;
- }
- return 0;
-}
-
-/**
- * nand_read_page_syndrome - [REPLACEABLE] hardware ECC syndrome based page read
- * @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
- *
- * The hw generator calculates the error syndrome automatically. Therefore we
- * need a special oob layout and handling.
- */
-static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip,
- uint8_t *buf, int oob_required, int page)
-{
- int i, eccsize = chip->ecc.size;
- int eccbytes = chip->ecc.bytes;
- int eccsteps = chip->ecc.steps;
- uint8_t *p = buf;
- uint8_t *oob = chip->oob_poi;
-
- for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
- int stat;
-
- chip->ecc.hwctl(mtd, NAND_ECC_READ);
- chip->read_buf(mtd, p, eccsize);
-
- if (chip->ecc.prepad) {
- chip->read_buf(mtd, oob, chip->ecc.prepad);
- oob += chip->ecc.prepad;
- }
-
- chip->ecc.hwctl(mtd, NAND_ECC_READSYN);
- chip->read_buf(mtd, oob, eccbytes);
- stat = chip->ecc.correct(mtd, p, oob, NULL);
-
- if (stat < 0)
- mtd->ecc_stats.failed++;
- else
- mtd->ecc_stats.corrected += stat;
-
- oob += eccbytes;
-
- if (chip->ecc.postpad) {
- chip->read_buf(mtd, oob, chip->ecc.postpad);
- oob += chip->ecc.postpad;
- }
- }
-
- /* Calculate remaining oob bytes */
- i = mtd->oobsize - (oob - chip->oob_poi);
- if (i)
- chip->read_buf(mtd, oob, i);
-
- return 0;
-}
-
-/**
- * nand_transfer_oob - [INTERN] Transfer oob to client buffer
- * @chip: nand chip structure
- * @oob: oob destination address
- * @ops: oob ops structure
- * @len: size of oob to transfer
- */
-static uint8_t *nand_transfer_oob(struct nand_chip *chip, uint8_t *oob,
- struct mtd_oob_ops *ops, size_t len)
-{
- switch (ops->mode) {
-
- case MTD_OPS_PLACE_OOB:
- case MTD_OPS_RAW:
- memcpy(oob, chip->oob_poi + ops->ooboffs, len);
- return oob + len;
-
- case MTD_OPS_AUTO_OOB: {
- struct nand_oobfree *free = chip->ecc.layout->oobfree;
- uint32_t boffs = 0, roffs = ops->ooboffs;
- size_t bytes = 0;
-
- for (; free->length && len; free++, len -= bytes) {
- /* Read request not from offset 0? */
- if (unlikely(roffs)) {
- if (roffs >= free->length) {
- roffs -= free->length;
- continue;
- }
- boffs = free->offset + roffs;
- bytes = min_t(size_t, len,
- (free->length - roffs));
- roffs = 0;
- } else {
- bytes = min_t(size_t, len, free->length);
- boffs = free->offset;
- }
- memcpy(oob, chip->oob_poi + boffs, bytes);
- oob += bytes;
- }
- return oob;
- }
- default:
- BUG();
- }
- return NULL;
-}
-
-/**
- * nand_do_read_ops - [INTERN] Read data with ECC
- * @mtd: MTD device structure
- * @from: offset to read from
- * @ops: oob ops structure
- *
- * Internal function. Called with chip held.
- */
-static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
- struct mtd_oob_ops *ops)
-{
- int chipnr, page, realpage, col, bytes, aligned, oob_required;
- struct nand_chip *chip = mtd->priv;
- struct mtd_ecc_stats stats;
- int ret = 0;
- uint32_t readlen = ops->len;
- uint32_t oobreadlen = ops->ooblen;
- uint32_t max_oobsize = ops->mode == MTD_OPS_AUTO_OOB ?
- mtd->oobavail : mtd->oobsize;
-
- uint8_t *bufpoi, *oob, *buf;
- unsigned int max_bitflips = 0;
-
- stats = mtd->ecc_stats;
-
- chipnr = (int)(from >> chip->chip_shift);
- chip->select_chip(mtd, chipnr);
-
- realpage = (int)(from >> chip->page_shift);
- page = realpage & chip->pagemask;
-
- col = (int)(from & (mtd->writesize - 1));
-
- buf = ops->datbuf;
- oob = ops->oobbuf;
- oob_required = oob ? 1 : 0;
-
- while (1) {
- WATCHDOG_RESET();
-
- bytes = min(mtd->writesize - col, readlen);
- aligned = (bytes == mtd->writesize);
-
- /* Is the current page in the buffer? */
- if (realpage != chip->pagebuf || oob) {
- bufpoi = aligned ? buf : chip->buffers->databuf;
-
- chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page);
-
- /*
- * Now read the page into the buffer. Absent an error,
- * the read methods return max bitflips per ecc step.
- */
- if (unlikely(ops->mode == MTD_OPS_RAW))
- ret = chip->ecc.read_page_raw(mtd, chip, bufpoi,
- oob_required,
- page);
- else if (!aligned && NAND_HAS_SUBPAGE_READ(chip) &&
- !oob)
- ret = chip->ecc.read_subpage(mtd, chip,
- col, bytes, bufpoi);
- else
- ret = chip->ecc.read_page(mtd, chip, bufpoi,
- oob_required, page);
- if (ret < 0) {
- if (!aligned)
- /* Invalidate page cache */
- chip->pagebuf = -1;
- break;
- }
-
- max_bitflips = max_t(unsigned int, max_bitflips, ret);
-
- /* Transfer not aligned data */
- if (!aligned) {
- if (!NAND_HAS_SUBPAGE_READ(chip) && !oob &&
- !(mtd->ecc_stats.failed - stats.failed) &&
- (ops->mode != MTD_OPS_RAW)) {
- chip->pagebuf = realpage;
- chip->pagebuf_bitflips = ret;
- } else {
- /* Invalidate page cache */
- chip->pagebuf = -1;
- }
- memcpy(buf, chip->buffers->databuf + col, bytes);
- }
-
- buf += bytes;
-
- if (unlikely(oob)) {
- int toread = min(oobreadlen, max_oobsize);
-
- if (toread) {
- oob = nand_transfer_oob(chip,
- oob, ops, toread);
- oobreadlen -= toread;
- }
- }
- } else {
- memcpy(buf, chip->buffers->databuf + col, bytes);
- buf += bytes;
- max_bitflips = max_t(unsigned int, max_bitflips,
- chip->pagebuf_bitflips);
- }
-
- readlen -= bytes;
-
- if (!readlen)
- break;
-
- /* For subsequent reads align to page boundary */
- col = 0;
- /* Increment page address */
- realpage++;
-
- page = realpage & chip->pagemask;
- /* Check, if we cross a chip boundary */
- if (!page) {
- chipnr++;
- chip->select_chip(mtd, -1);
- chip->select_chip(mtd, chipnr);
- }
- }
-
- ops->retlen = ops->len - (size_t) readlen;
- if (oob)
- ops->oobretlen = ops->ooblen - oobreadlen;
-
- if (ret)
- return ret;
-
- if (mtd->ecc_stats.failed - stats.failed)
- return -EBADMSG;
-
- return max_bitflips;
-}
-
-/**
- * nand_read - [MTD Interface] MTD compatibility function for nand_do_read_ecc
- * @mtd: MTD device structure
- * @from: offset to read from
- * @len: number of bytes to read
- * @retlen: pointer to variable to store the number of read bytes
- * @buf: the databuffer to put data
- *
- * Get hold of the chip and call nand_do_read.
- */
-static int nand_read(struct mtd_info *mtd, loff_t from, size_t len,
- size_t *retlen, uint8_t *buf)
-{
- struct nand_chip *chip = mtd->priv;
- struct mtd_oob_ops ops;
- int ret;
-
- nand_get_device(chip, mtd, FL_READING);
- ops.len = len;
- ops.datbuf = buf;
- ops.oobbuf = NULL;
- ops.mode = MTD_OPS_PLACE_OOB;
- ret = nand_do_read_ops(mtd, from, &ops);
- *retlen = ops.retlen;
- nand_release_device(mtd);
- return ret;
-}
-
-/**
- * nand_read_oob_std - [REPLACEABLE] the most common OOB data read function
- * @mtd: mtd info structure
- * @chip: nand chip info structure
- * @page: page number to read
- */
-static int 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;
-}
-
-/**
- * nand_read_oob_syndrome - [REPLACEABLE] OOB data read function for HW ECC
- * with syndromes
- * @mtd: mtd info structure
- * @chip: nand chip info structure
- * @page: page number to read
- */
-static int nand_read_oob_syndrome(struct mtd_info *mtd, struct nand_chip *chip,
- int page)
-{
- uint8_t *buf = chip->oob_poi;
- int length = mtd->oobsize;
- int chunk = chip->ecc.bytes + chip->ecc.prepad + chip->ecc.postpad;
- int eccsize = chip->ecc.size;
- uint8_t *bufpoi = buf;
- int i, toread, sndrnd = 0, pos;
-
- chip->cmdfunc(mtd, NAND_CMD_READ0, chip->ecc.size, page);
- for (i = 0; i < chip->ecc.steps; i++) {
- if (sndrnd) {
- pos = eccsize + i * (eccsize + chunk);
- if (mtd->writesize > 512)
- chip->cmdfunc(mtd, NAND_CMD_RNDOUT, pos, -1);
- else
- chip->cmdfunc(mtd, NAND_CMD_READ0, pos, page);
- } else
- sndrnd = 1;
- toread = min_t(int, length, chunk);
- chip->read_buf(mtd, bufpoi, toread);
- bufpoi += toread;
- length -= toread;
- }
- if (length > 0)
- chip->read_buf(mtd, bufpoi, length);
-
- return 0;
-}
-
-/**
- * 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 nand_write_oob_std(struct mtd_info *mtd, struct nand_chip *chip,
- int page)
-{
- int status = 0;
- const uint8_t *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;
-}
-
-/**
- * nand_write_oob_syndrome - [REPLACEABLE] OOB data write function for HW ECC
- * with syndrome - only for large page flash
- * @mtd: mtd info structure
- * @chip: nand chip info structure
- * @page: page number to write
- */
-static int nand_write_oob_syndrome(struct mtd_info *mtd,
- struct nand_chip *chip, int page)
-{
- int chunk = chip->ecc.bytes + chip->ecc.prepad + chip->ecc.postpad;
- int eccsize = chip->ecc.size, length = mtd->oobsize;
- int i, len, pos, status = 0, sndcmd = 0, steps = chip->ecc.steps;
- const uint8_t *bufpoi = chip->oob_poi;
-
- /*
- * data-ecc-data-ecc ... ecc-oob
- * or
- * data-pad-ecc-pad-data-pad .... ecc-pad-oob
- */
- if (!chip->ecc.prepad && !chip->ecc.postpad) {
- pos = steps * (eccsize + chunk);
- steps = 0;
- } else
- pos = eccsize;
-
- chip->cmdfunc(mtd, NAND_CMD_SEQIN, pos, page);
- for (i = 0; i < steps; i++) {
- if (sndcmd) {
- if (mtd->writesize <= 512) {
- uint32_t fill = 0xFFFFFFFF;
-
- len = eccsize;
- while (len > 0) {
- int num = min_t(int, len, 4);
- chip->write_buf(mtd, (uint8_t *)&fill,
- num);
- len -= num;
- }
- } else {
- pos = eccsize + i * (eccsize + chunk);
- chip->cmdfunc(mtd, NAND_CMD_RNDIN, pos, -1);
- }
- } else
- sndcmd = 1;
- len = min_t(int, length, chunk);
- chip->write_buf(mtd, bufpoi, len);
- bufpoi += len;
- length -= len;
- }
- if (length > 0)
- chip->write_buf(mtd, bufpoi, length);
-
- chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
- status = chip->waitfunc(mtd, chip);
-
- return status & NAND_STATUS_FAIL ? -EIO : 0;
-}
-
-/**
- * nand_do_read_oob - [INTERN] NAND read out-of-band
- * @mtd: MTD device structure
- * @from: offset to read from
- * @ops: oob operations description structure
- *
- * NAND read out-of-band data from the spare area.
- */
-static int nand_do_read_oob(struct mtd_info *mtd, loff_t from,
- struct mtd_oob_ops *ops)
-{
- int page, realpage, chipnr;
- struct nand_chip *chip = mtd->priv;
- struct mtd_ecc_stats stats;
- int readlen = ops->ooblen;
- int len;
- uint8_t *buf = ops->oobbuf;
- int ret = 0;
-
- MTDDEBUG(MTD_DEBUG_LEVEL3, "%s: from = 0x%08Lx, len = %i\n",
- __func__, (unsigned long long)from, readlen);
-
- stats = mtd->ecc_stats;
-
- if (ops->mode == MTD_OPS_AUTO_OOB)
- len = chip->ecc.layout->oobavail;
- else
- len = mtd->oobsize;
-
- if (unlikely(ops->ooboffs >= len)) {
- MTDDEBUG(MTD_DEBUG_LEVEL0, "%s: Attempt to start read "
- "outside oob\n", __func__);
- return -EINVAL;
- }
-
- /* Do not allow reads past end of device */
- if (unlikely(from >= mtd->size ||
- ops->ooboffs + readlen > ((mtd->size >> chip->page_shift) -
- (from >> chip->page_shift)) * len)) {
- MTDDEBUG(MTD_DEBUG_LEVEL0, "%s: Attempt read beyond end "
- "of device\n", __func__);
- return -EINVAL;
- }
-
- chipnr = (int)(from >> chip->chip_shift);
- chip->select_chip(mtd, chipnr);
-
- /* Shift to get page */
- realpage = (int)(from >> chip->page_shift);
- page = realpage & chip->pagemask;
-
- while (1) {
- WATCHDOG_RESET();
- if (ops->mode == MTD_OPS_RAW)
- ret = chip->ecc.read_oob_raw(mtd, chip, page);
- else
- ret = chip->ecc.read_oob(mtd, chip, page);
-
- if (ret < 0)
- break;
-
- len = min(len, readlen);
- buf = nand_transfer_oob(chip, buf, ops, len);
-
- readlen -= len;
- if (!readlen)
- break;
-
- /* Increment page address */
- realpage++;
-
- page = realpage & chip->pagemask;
- /* Check, if we cross a chip boundary */
- if (!page) {
- chipnr++;
- chip->select_chip(mtd, -1);
- chip->select_chip(mtd, chipnr);
- }
- }
-
- ops->oobretlen = ops->ooblen - readlen;
-
- if (ret < 0)
- return ret;
-
- if (mtd->ecc_stats.failed - stats.failed)
- return -EBADMSG;
-
- return mtd->ecc_stats.corrected - stats.corrected ? -EUCLEAN : 0;
-}
-
-/**
- * nand_read_oob - [MTD Interface] NAND read data and/or out-of-band
- * @mtd: MTD device structure
- * @from: offset to read from
- * @ops: oob operation description structure
- *
- * NAND read data and/or out-of-band data.
- */
-static int nand_read_oob(struct mtd_info *mtd, loff_t from,
- struct mtd_oob_ops *ops)
-{
- struct nand_chip *chip = mtd->priv;
- int ret = -ENOTSUPP;
-
- ops->retlen = 0;
-
- /* Do not allow reads past end of device */
- if (ops->datbuf && (from + ops->len) > mtd->size) {
- MTDDEBUG(MTD_DEBUG_LEVEL0, "%s: Attempt read "
- "beyond end of device\n", __func__);
- return -EINVAL;
- }
-
- nand_get_device(chip, mtd, FL_READING);
-
- switch (ops->mode) {
- case MTD_OPS_PLACE_OOB:
- case MTD_OPS_AUTO_OOB:
- case MTD_OPS_RAW:
- break;
-
- default:
- goto out;
- }
-
- if (!ops->datbuf)
- ret = nand_do_read_oob(mtd, from, ops);
- else
- ret = nand_do_read_ops(mtd, from, ops);
-
-out:
- nand_release_device(mtd);
- return ret;
-}
-
-
-/**
- * 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
- *
- * Not for syndrome calculating ECC controllers, which use a special oob layout.
- */
-static int nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
- const uint8_t *buf, int oob_required)
-{
- chip->write_buf(mtd, buf, mtd->writesize);
- if (oob_required)
- chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
-
- return 0;
-}
-
-/**
- * nand_write_page_raw_syndrome - [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
- *
- * We need a special oob layout and handling even when ECC isn't checked.
- */
-static int nand_write_page_raw_syndrome(struct mtd_info *mtd,
- struct nand_chip *chip,
- const uint8_t *buf, int oob_required)
-{
- int eccsize = chip->ecc.size;
- int eccbytes = chip->ecc.bytes;
- uint8_t *oob = chip->oob_poi;
- int steps, size;
-
- for (steps = chip->ecc.steps; steps > 0; steps--) {
- chip->write_buf(mtd, buf, eccsize);
- buf += eccsize;
-
- if (chip->ecc.prepad) {
- chip->write_buf(mtd, oob, chip->ecc.prepad);
- oob += chip->ecc.prepad;
- }
-
- chip->read_buf(mtd, oob, eccbytes);
- oob += eccbytes;
-
- if (chip->ecc.postpad) {
- chip->write_buf(mtd, oob, chip->ecc.postpad);
- oob += chip->ecc.postpad;
- }
- }
-
- size = mtd->oobsize - (oob - chip->oob_poi);
- if (size)
- chip->write_buf(mtd, oob, size);
-
- return 0;
-}
-/**
- * nand_write_page_swecc - [REPLACEABLE] software ECC based page write function
- * @mtd: mtd info structure
- * @chip: nand chip info structure
- * @buf: data buffer
- * @oob_required: must write chip->oob_poi to OOB
- */
-static int nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
- const uint8_t *buf, int oob_required)
-{
- int i, eccsize = chip->ecc.size;
- int eccbytes = chip->ecc.bytes;
- int eccsteps = chip->ecc.steps;
- uint8_t *ecc_calc = chip->buffers->ecccalc;
- const uint8_t *p = buf;
- uint32_t *eccpos = chip->ecc.layout->eccpos;
-
- /* Software ECC calculation */
- for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize)
- chip->ecc.calculate(mtd, p, &ecc_calc[i]);
-
- for (i = 0; i < chip->ecc.total; i++)
- chip->oob_poi[eccpos[i]] = ecc_calc[i];
-
- return chip->ecc.write_page_raw(mtd, chip, buf, 1);
-}
-
-/**
- * nand_write_page_hwecc - [REPLACEABLE] hardware ECC based page write function
- * @mtd: mtd info structure
- * @chip: nand chip info structure
- * @buf: data buffer
- * @oob_required: must write chip->oob_poi to OOB
- */
-static int nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
- const uint8_t *buf, int oob_required)
-{
- int i, eccsize = chip->ecc.size;
- int eccbytes = chip->ecc.bytes;
- int eccsteps = chip->ecc.steps;
- uint8_t *ecc_calc = chip->buffers->ecccalc;
- const uint8_t *p = buf;
- uint32_t *eccpos = chip->ecc.layout->eccpos;
-
- for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
- chip->ecc.hwctl(mtd, NAND_ECC_WRITE);
- chip->write_buf(mtd, p, eccsize);
- chip->ecc.calculate(mtd, p, &ecc_calc[i]);
- }
-
- for (i = 0; i < chip->ecc.total; i++)
- chip->oob_poi[eccpos[i]] = ecc_calc[i];
-
- chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
-
- return 0;
-}
-
-/**
- * nand_write_page_syndrome - [REPLACEABLE] hardware ECC syndrome based page write
- * @mtd: mtd info structure
- * @chip: nand chip info structure
- * @buf: data buffer
- * @oob_required: must write chip->oob_poi to OOB
- *
- * The hw generator calculates the error syndrome automatically. Therefore we
- * need a special oob layout and handling.
- */
-static int nand_write_page_syndrome(struct mtd_info *mtd,
- struct nand_chip *chip,
- const uint8_t *buf, int oob_required)
-{
- int i, eccsize = chip->ecc.size;
- int eccbytes = chip->ecc.bytes;
- int eccsteps = chip->ecc.steps;
- const uint8_t *p = buf;
- uint8_t *oob = chip->oob_poi;
-
- for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
-
- chip->ecc.hwctl(mtd, NAND_ECC_WRITE);
- chip->write_buf(mtd, p, eccsize);
-
- if (chip->ecc.prepad) {
- chip->write_buf(mtd, oob, chip->ecc.prepad);
- oob += chip->ecc.prepad;
- }
-
- chip->ecc.calculate(mtd, p, oob);
- chip->write_buf(mtd, oob, eccbytes);
- oob += eccbytes;
-
- if (chip->ecc.postpad) {
- chip->write_buf(mtd, oob, chip->ecc.postpad);
- oob += chip->ecc.postpad;
- }
- }
-
- /* Calculate remaining oob bytes */
- i = mtd->oobsize - (oob - chip->oob_poi);
- if (i)
- chip->write_buf(mtd, oob, i);
-
- return 0;
-}
-
-/**
- * nand_write_page - [REPLACEABLE] write one page
- * @mtd: MTD device structure
- * @chip: NAND chip descriptor
- * @buf: the data to write
- * @oob_required: must write chip->oob_poi to OOB
- * @page: page number to write
- * @cached: cached programming
- * @raw: use _raw version of write_page
- */
-static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip,
- const uint8_t *buf, int oob_required, int page,
- int cached, int raw)
-{
- int status;
-
- chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page);
-
- if (unlikely(raw))
- status = chip->ecc.write_page_raw(mtd, chip, buf, oob_required);
- else
- status = chip->ecc.write_page(mtd, chip, buf, oob_required);
-
- if (status < 0)
- return status;
-
- /*
- * Cached progamming disabled for now. Not sure if it's worth the
- * trouble. The speed gain is not very impressive. (2.3->2.6Mib/s).
- */
- cached = 0;
-
- if (!cached || !(chip->options & NAND_CACHEPRG)) {
-
- chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
- status = chip->waitfunc(mtd, chip);
- /*
- * See if operation failed and additional status checks are
- * available.
- */
- if ((status & NAND_STATUS_FAIL) && (chip->errstat))
- status = chip->errstat(mtd, chip, FL_WRITING, status,
- page);
-
- if (status & NAND_STATUS_FAIL)
- return -EIO;
- } else {
- chip->cmdfunc(mtd, NAND_CMD_CACHEDPROG, -1, -1);
- status = chip->waitfunc(mtd, chip);
- }
-
-#ifdef CONFIG_MTD_NAND_VERIFY_WRITE
- /* Send command to read back the data */
- chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page);
-
- if (chip->verify_buf(mtd, buf, mtd->writesize))
- return -EIO;
-
- /* Make sure the next page prog is preceded by a status read */
- chip->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1);
-#endif
- return 0;
-}
-
-/**
- * nand_fill_oob - [INTERN] Transfer client buffer to oob
- * @mtd: MTD device structure
- * @oob: oob data buffer
- * @len: oob data write length
- * @ops: oob ops structure
- */
-static uint8_t *nand_fill_oob(struct mtd_info *mtd, uint8_t *oob, size_t len,
- struct mtd_oob_ops *ops)
-{
- struct nand_chip *chip = mtd->priv;
-
- /*
- * Initialise to all 0xFF, to avoid the possibility of left over OOB
- * data from a previous OOB read.
- */
- memset(chip->oob_poi, 0xff, mtd->oobsize);
-
- switch (ops->mode) {
-
- case MTD_OPS_PLACE_OOB:
- case MTD_OPS_RAW:
- memcpy(chip->oob_poi + ops->ooboffs, oob, len);
- return oob + len;
-
- case MTD_OPS_AUTO_OOB: {
- struct nand_oobfree *free = chip->ecc.layout->oobfree;
- uint32_t boffs = 0, woffs = ops->ooboffs;
- size_t bytes = 0;
-
- for (; free->length && len; free++, len -= bytes) {
- /* Write request not from offset 0? */
- if (unlikely(woffs)) {
- if (woffs >= free->length) {
- woffs -= free->length;
- continue;
- }
- boffs = free->offset + woffs;
- bytes = min_t(size_t, len,
- (free->length - woffs));
- woffs = 0;
- } else {
- bytes = min_t(size_t, len, free->length);
- boffs = free->offset;
- }
- memcpy(chip->oob_poi + boffs, oob, bytes);
- oob += bytes;
- }
- return oob;
- }
- default:
- BUG();
- }
- return NULL;
-}
-
-#define NOTALIGNED(x) ((x & (chip->subpagesize - 1)) != 0)
-
-/**
- * nand_do_write_ops - [INTERN] NAND write with ECC
- * @mtd: MTD device structure
- * @to: offset to write to
- * @ops: oob operations description structure
- *
- * NAND write with ECC.
- */
-static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
- struct mtd_oob_ops *ops)
-{
- int chipnr, realpage, page, blockmask, column;
- struct nand_chip *chip = mtd->priv;
- uint32_t writelen = ops->len;
-
- uint32_t oobwritelen = ops->ooblen;
- uint32_t oobmaxlen = ops->mode == MTD_OPS_AUTO_OOB ?
- mtd->oobavail : mtd->oobsize;
-
- uint8_t *oob = ops->oobbuf;
- uint8_t *buf = ops->datbuf;
- int ret, subpage;
- int oob_required = oob ? 1 : 0;
-
- ops->retlen = 0;
- if (!writelen)
- return 0;
-
- column = to & (mtd->writesize - 1);
- subpage = column || (writelen & (mtd->writesize - 1));
-
- if (subpage && oob)
- return -EINVAL;
-
- chipnr = (int)(to >> chip->chip_shift);
- chip->select_chip(mtd, chipnr);
-
- /* Check, if it is write protected */
- if (nand_check_wp(mtd)) {
- printk (KERN_NOTICE "nand_do_write_ops: Device is write protected\n");
- return -EIO;
- }
-
- realpage = (int)(to >> chip->page_shift);
- page = realpage & chip->pagemask;
- blockmask = (1 << (chip->phys_erase_shift - chip->page_shift)) - 1;
-
- /* Invalidate the page cache, when we write to the cached page */
- if (to <= (chip->pagebuf << chip->page_shift) &&
- (chip->pagebuf << chip->page_shift) < (to + ops->len))
- chip->pagebuf = -1;
-
- /* Don't allow multipage oob writes with offset */
- if (oob && ops->ooboffs && (ops->ooboffs + ops->ooblen > oobmaxlen))
- return -EINVAL;
-
- while (1) {
- WATCHDOG_RESET();
-
- int bytes = mtd->writesize;
- int cached = writelen > bytes && page != blockmask;
- uint8_t *wbuf = buf;
-
- /* Partial page write? */
- if (unlikely(column || writelen < mtd->writesize)) {
- cached = 0;
- bytes = min_t(int, bytes - column, (int) writelen);
- chip->pagebuf = -1;
- memset(chip->buffers->databuf, 0xff, mtd->writesize);
- memcpy(&chip->buffers->databuf[column], buf, bytes);
- wbuf = chip->buffers->databuf;
- }
-
- if (unlikely(oob)) {
- size_t len = min(oobwritelen, oobmaxlen);
- oob = nand_fill_oob(mtd, oob, len, ops);
- oobwritelen -= len;
- } else {
- /* We still need to erase leftover OOB data */
- memset(chip->oob_poi, 0xff, mtd->oobsize);
- }
-
- ret = chip->write_page(mtd, chip, wbuf, oob_required, page,
- cached, (ops->mode == MTD_OPS_RAW));
- if (ret)
- break;
-
- writelen -= bytes;
- if (!writelen)
- break;
-
- column = 0;
- buf += bytes;
- realpage++;
-
- page = realpage & chip->pagemask;
- /* Check, if we cross a chip boundary */
- if (!page) {
- chipnr++;
- chip->select_chip(mtd, -1);
- chip->select_chip(mtd, chipnr);
- }
- }
-
- ops->retlen = ops->len - writelen;
- if (unlikely(oob))
- ops->oobretlen = ops->ooblen;
- return ret;
-}
-
-/**
- * nand_write - [MTD Interface] NAND write with ECC
- * @mtd: MTD device structure
- * @to: offset to write to
- * @len: number of bytes to write
- * @retlen: pointer to variable to store the number of written bytes
- * @buf: the data to write
- *
- * NAND write with ECC.
- */
-static int nand_write(struct mtd_info *mtd, loff_t to, size_t len,
- size_t *retlen, const uint8_t *buf)
-{
- struct nand_chip *chip = mtd->priv;
- struct mtd_oob_ops ops;
- int ret;
-
- nand_get_device(chip, mtd, FL_WRITING);
- ops.len = len;
- ops.datbuf = (uint8_t *)buf;
- ops.oobbuf = NULL;
- ops.mode = MTD_OPS_PLACE_OOB;
- ret = nand_do_write_ops(mtd, to, &ops);
- *retlen = ops.retlen;
- nand_release_device(mtd);
- return ret;
-}
-
-/**
- * nand_do_write_oob - [MTD Interface] NAND write out-of-band
- * @mtd: MTD device structure
- * @to: offset to write to
- * @ops: oob operation description structure
- *
- * NAND write out-of-band.
- */
-static int nand_do_write_oob(struct mtd_info *mtd, loff_t to,
- struct mtd_oob_ops *ops)
-{
- int chipnr, page, status, len;
- struct nand_chip *chip = mtd->priv;
-
- MTDDEBUG(MTD_DEBUG_LEVEL3, "%s: to = 0x%08x, len = %i\n",
- __func__, (unsigned int)to, (int)ops->ooblen);
-
- if (ops->mode == MTD_OPS_AUTO_OOB)
- len = chip->ecc.layout->oobavail;
- else
- len = mtd->oobsize;
-
- /* Do not allow write past end of page */
- if ((ops->ooboffs + ops->ooblen) > len) {
- MTDDEBUG(MTD_DEBUG_LEVEL0, "%s: Attempt to write "
- "past end of page\n", __func__);
- return -EINVAL;
- }
-
- if (unlikely(ops->ooboffs >= len)) {
- MTDDEBUG(MTD_DEBUG_LEVEL0, "%s: Attempt to start "
- "write outside oob\n", __func__);
- return -EINVAL;
- }
-
- /* Do not allow write past end of device */
- if (unlikely(to >= mtd->size ||
- ops->ooboffs + ops->ooblen >
- ((mtd->size >> chip->page_shift) -
- (to >> chip->page_shift)) * len)) {
- MTDDEBUG(MTD_DEBUG_LEVEL0, "%s: Attempt write beyond "
- "end of device\n", __func__);
- return -EINVAL;
- }
-
- chipnr = (int)(to >> chip->chip_shift);
- chip->select_chip(mtd, chipnr);
-
- /* Shift to get page */
- page = (int)(to >> chip->page_shift);
-
- /*
- * Reset the chip. Some chips (like the Toshiba TC5832DC found in one
- * of my DiskOnChip 2000 test units) will clear the whole data page too
- * if we don't do this. I have no clue why, but I seem to have 'fixed'
- * it in the doc2000 driver in August 1999. dwmw2.
- */
- chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
-
- /* Check, if it is write protected */
- if (nand_check_wp(mtd))
- return -EROFS;
-
- /* Invalidate the page cache, if we write to the cached page */
- if (page == chip->pagebuf)
- chip->pagebuf = -1;
-
- nand_fill_oob(mtd, ops->oobbuf, ops->ooblen, ops);
-
- if (ops->mode == MTD_OPS_RAW)
- status = chip->ecc.write_oob_raw(mtd, chip, page & chip->pagemask);
- else
- status = chip->ecc.write_oob(mtd, chip, page & chip->pagemask);
-
- if (status)
- return status;
-
- ops->oobretlen = ops->ooblen;
-
- return 0;
-}
-
-/**
- * nand_write_oob - [MTD Interface] NAND write data and/or out-of-band
- * @mtd: MTD device structure
- * @to: offset to write to
- * @ops: oob operation description structure
- */
-static int nand_write_oob(struct mtd_info *mtd, loff_t to,
- struct mtd_oob_ops *ops)
-{
- struct nand_chip *chip = mtd->priv;
- int ret = -ENOTSUPP;
-
- ops->retlen = 0;
-
- /* Do not allow writes past end of device */
- if (ops->datbuf && (to + ops->len) > mtd->size) {
- MTDDEBUG(MTD_DEBUG_LEVEL0, "%s: Attempt write beyond "
- "end of device\n", __func__);
- return -EINVAL;
- }
-
- nand_get_device(chip, mtd, FL_WRITING);
-
- switch (ops->mode) {
- case MTD_OPS_PLACE_OOB:
- case MTD_OPS_AUTO_OOB:
- case MTD_OPS_RAW:
- break;
-
- default:
- goto out;
- }
-
- if (!ops->datbuf)
- ret = nand_do_write_oob(mtd, to, ops);
- else
- ret = nand_do_write_ops(mtd, to, ops);
-
-out:
- nand_release_device(mtd);
- return ret;
-}
-
-/**
- * single_erase_cmd - [GENERIC] NAND standard block erase command function
- * @mtd: MTD device structure
- * @page: the page address of the block which will be erased
- *
- * Standard erase command for NAND chips.
- */
-static void single_erase_cmd(struct mtd_info *mtd, int page)
-{
- struct nand_chip *chip = mtd->priv;
- /* Send commands to erase a block */
- chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page);
- chip->cmdfunc(mtd, NAND_CMD_ERASE2, -1, -1);
-}
-
-/**
- * multi_erase_cmd - [GENERIC] AND specific block erase command function
- * @mtd: MTD device structure
- * @page: the page address of the block which will be erased
- *
- * AND multi block erase command function. Erase 4 consecutive blocks.
- */
-static void multi_erase_cmd(struct mtd_info *mtd, int page)
-{
- struct nand_chip *chip = mtd->priv;
- /* Send commands to erase a block */
- chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page++);
- chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page++);
- chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page++);
- chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page);
- chip->cmdfunc(mtd, NAND_CMD_ERASE2, -1, -1);
-}
-
-/**
- * nand_erase - [MTD Interface] erase block(s)
- * @mtd: MTD device structure
- * @instr: erase instruction
- *
- * Erase one ore more blocks.
- */
-static int nand_erase(struct mtd_info *mtd, struct erase_info *instr)
-{
- return nand_erase_nand(mtd, instr, 0);
-}
-
-#define BBT_PAGE_MASK 0xffffff3f
-/**
- * nand_erase_nand - [INTERN] erase block(s)
- * @mtd: MTD device structure
- * @instr: erase instruction
- * @allowbbt: allow erasing the bbt area
- *
- * Erase one ore more blocks.
- */
-int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
- int allowbbt)
-{
- int page, status, pages_per_block, ret, chipnr;
- struct nand_chip *chip = mtd->priv;
- loff_t rewrite_bbt[CONFIG_SYS_NAND_MAX_CHIPS] = {0};
- unsigned int bbt_masked_page = 0xffffffff;
- loff_t len;
-
- MTDDEBUG(MTD_DEBUG_LEVEL3, "%s: start = 0x%012llx, len = %llu\n",
- __func__, (unsigned long long)instr->addr,
- (unsigned long long)instr->len);
-
- if (check_offs_len(mtd, instr->addr, instr->len))
- return -EINVAL;
-
- /* Grab the lock and see if the device is available */
- nand_get_device(chip, mtd, FL_ERASING);
-
- /* Shift to get first page */
- page = (int)(instr->addr >> chip->page_shift);
- chipnr = (int)(instr->addr >> chip->chip_shift);
-
- /* Calculate pages in each block */
- pages_per_block = 1 << (chip->phys_erase_shift - chip->page_shift);
-
- /* Select the NAND device */
- chip->select_chip(mtd, chipnr);
-
- /* Check, if it is write protected */
- if (nand_check_wp(mtd)) {
- MTDDEBUG(MTD_DEBUG_LEVEL0, "%s: Device is write protected!!!\n",
- __func__);
- instr->state = MTD_ERASE_FAILED;
- goto erase_exit;
- }
-
- /*
- * If BBT requires refresh, set the BBT page mask to see if the BBT
- * should be rewritten. Otherwise the mask is set to 0xffffffff which
- * can not be matched. This is also done when the bbt is actually
- * erased to avoid recursive updates.
- */
- if (chip->options & BBT_AUTO_REFRESH && !allowbbt)
- bbt_masked_page = chip->bbt_td->pages[chipnr] & BBT_PAGE_MASK;
-
- /* Loop through the pages */
- len = instr->len;
-
- instr->state = MTD_ERASING;
-
- while (len) {
- WATCHDOG_RESET();
- /* Check if we have a bad block, we do not erase bad blocks! */
- if (!instr->scrub && nand_block_checkbad(mtd, ((loff_t) page) <<
- chip->page_shift, 0, allowbbt)) {
- pr_warn("%s: attempt to erase a bad block at page 0x%08x\n",
- __func__, page);
- instr->state = MTD_ERASE_FAILED;
- goto erase_exit;
- }
-
- /*
- * Invalidate the page cache, if we erase the block which
- * contains the current cached page.
- */
- if (page <= chip->pagebuf && chip->pagebuf <
- (page + pages_per_block))
- chip->pagebuf = -1;
-
- chip->erase_cmd(mtd, page & chip->pagemask);
-
- status = chip->waitfunc(mtd, chip);
-
- /*
- * See if operation failed and additional status checks are
- * available
- */
- if ((status & NAND_STATUS_FAIL) && (chip->errstat))
- status = chip->errstat(mtd, chip, FL_ERASING,
- status, page);
-
- /* See if block erase succeeded */
- if (status & NAND_STATUS_FAIL) {
- MTDDEBUG(MTD_DEBUG_LEVEL0, "%s: Failed erase, "
- "page 0x%08x\n", __func__, page);
- instr->state = MTD_ERASE_FAILED;
- instr->fail_addr =
- ((loff_t)page << chip->page_shift);
- goto erase_exit;
- }
-
- /*
- * If BBT requires refresh, set the BBT rewrite flag to the
- * page being erased.
- */
- if (bbt_masked_page != 0xffffffff &&
- (page & BBT_PAGE_MASK) == bbt_masked_page)
- rewrite_bbt[chipnr] =
- ((loff_t)page << chip->page_shift);
-
- /* Increment page address and decrement length */
- len -= (1 << chip->phys_erase_shift);
- page += pages_per_block;
-
- /* Check, if we cross a chip boundary */
- if (len && !(page & chip->pagemask)) {
- chipnr++;
- chip->select_chip(mtd, -1);
- chip->select_chip(mtd, chipnr);
-
- /*
- * If BBT requires refresh and BBT-PERCHIP, set the BBT
- * page mask to see if this BBT should be rewritten.
- */
- if (bbt_masked_page != 0xffffffff &&
- (chip->bbt_td->options & NAND_BBT_PERCHIP))
- bbt_masked_page = chip->bbt_td->pages[chipnr] &
- BBT_PAGE_MASK;
- }
- }
- instr->state = MTD_ERASE_DONE;
-
-erase_exit:
-
- ret = instr->state == MTD_ERASE_DONE ? 0 : -EIO;
-
- /* Deselect and wake up anyone waiting on the device */
- nand_release_device(mtd);
-
- /* Do call back function */
- if (!ret)
- mtd_erase_callback(instr);
-
- /*
- * If BBT requires refresh and erase was successful, rewrite any
- * selected bad block tables.
- */
- if (bbt_masked_page == 0xffffffff || ret)
- return ret;
-
- for (chipnr = 0; chipnr < chip->numchips; chipnr++) {
- if (!rewrite_bbt[chipnr])
- continue;
- /* Update the BBT for chip */
- MTDDEBUG(MTD_DEBUG_LEVEL0, "%s: nand_update_bbt "
- "(%d:0x%0llx 0x%0x)\n", __func__, chipnr,
- rewrite_bbt[chipnr], chip->bbt_td->pages[chipnr]);
- nand_update_bbt(mtd, rewrite_bbt[chipnr]);
- }
-
- /* Return more or less happy */
- return ret;
-}
-
-/**
- * nand_sync - [MTD Interface] sync
- * @mtd: MTD device structure
- *
- * Sync is actually a wait for chip ready function.
- */
-static void nand_sync(struct mtd_info *mtd)
-{
- struct nand_chip *chip = mtd->priv;
-
- MTDDEBUG(MTD_DEBUG_LEVEL3, "%s: called\n", __func__);
-
- /* Grab the lock and see if the device is available */
- nand_get_device(chip, mtd, FL_SYNCING);
- /* Release it and go back */
- nand_release_device(mtd);
-}
-
-/**
- * nand_block_isbad - [MTD Interface] Check if block at offset is bad
- * @mtd: MTD device structure
- * @offs: offset relative to mtd start
- */
-static int nand_block_isbad(struct mtd_info *mtd, loff_t offs)
-{
- return nand_block_checkbad(mtd, offs, 1, 0);
-}
-
-/**
- * nand_block_markbad - [MTD Interface] Mark block at the given offset as bad
- * @mtd: MTD device structure
- * @ofs: offset relative to mtd start
- */
-static int nand_block_markbad(struct mtd_info *mtd, loff_t ofs)
-{
- struct nand_chip *chip = mtd->priv;
- int ret;
-
- ret = nand_block_isbad(mtd, ofs);
- if (ret) {
- /* If it was bad already, return success and do nothing */
- if (ret > 0)
- return 0;
- return ret;
- }
-
- return chip->block_markbad(mtd, ofs);
-}
-
- /**
- * nand_onfi_set_features- [REPLACEABLE] set features for ONFI nand
- * @mtd: MTD device structure
- * @chip: nand chip info structure
- * @addr: feature address.
- * @subfeature_param: the subfeature parameters, a four bytes array.
- */
-static int nand_onfi_set_features(struct mtd_info *mtd, struct nand_chip *chip,
- int addr, uint8_t *subfeature_param)
-{
- int status;
-
- if (!chip->onfi_version)
- return -EINVAL;
-
- chip->cmdfunc(mtd, NAND_CMD_SET_FEATURES, addr, -1);
- chip->write_buf(mtd, subfeature_param, ONFI_SUBFEATURE_PARAM_LEN);
- status = chip->waitfunc(mtd, chip);
- if (status & NAND_STATUS_FAIL)
- return -EIO;
- return 0;
-}
-
-/**
- * nand_onfi_get_features- [REPLACEABLE] get features for ONFI nand
- * @mtd: MTD device structure
- * @chip: nand chip info structure
- * @addr: feature address.
- * @subfeature_param: the subfeature parameters, a four bytes array.
- */
-static int nand_onfi_get_features(struct mtd_info *mtd, struct nand_chip *chip,
- int addr, uint8_t *subfeature_param)
-{
- if (!chip->onfi_version)
- return -EINVAL;
-
- /* clear the sub feature parameters */
- memset(subfeature_param, 0, ONFI_SUBFEATURE_PARAM_LEN);
-
- chip->cmdfunc(mtd, NAND_CMD_GET_FEATURES, addr, -1);
- chip->read_buf(mtd, subfeature_param, ONFI_SUBFEATURE_PARAM_LEN);
- return 0;
-}
-
-/* Set default functions */
-static void nand_set_defaults(struct nand_chip *chip, int busw)
-{
- /* check for proper chip_delay setup, set 20us if not */
- if (!chip->chip_delay)
- chip->chip_delay = 20;
-
- /* check, if a user supplied command function given */
- if (chip->cmdfunc == NULL)
- chip->cmdfunc = nand_command;
-
- /* check, if a user supplied wait function given */
- if (chip->waitfunc == NULL)
- chip->waitfunc = nand_wait;
-
- if (!chip->select_chip)
- chip->select_chip = nand_select_chip;
- if (!chip->read_byte)
- chip->read_byte = busw ? nand_read_byte16 : nand_read_byte;
- if (!chip->read_word)
- chip->read_word = nand_read_word;
- if (!chip->block_bad)
- chip->block_bad = nand_block_bad;
- if (!chip->block_markbad)
- chip->block_markbad = nand_default_block_markbad;
- if (!chip->write_buf)
- chip->write_buf = busw ? nand_write_buf16 : nand_write_buf;
- if (!chip->read_buf)
- chip->read_buf = busw ? nand_read_buf16 : nand_read_buf;
- if (!chip->verify_buf)
- chip->verify_buf = busw ? nand_verify_buf16 : nand_verify_buf;
- if (!chip->scan_bbt)
- chip->scan_bbt = nand_default_bbt;
- if (!chip->controller)
- chip->controller = &chip->hwcontrol;
-}
-
-#ifdef CONFIG_SYS_NAND_ONFI_DETECTION
-/* Sanitize ONFI strings so we can safely print them */
-static void sanitize_string(char *s, size_t len)
-{
- ssize_t i;
-
- /* Null terminate */
- s[len - 1] = 0;
-
- /* Remove non printable chars */
- for (i = 0; i < len - 1; i++) {
- if (s[i] < ' ' || s[i] > 127)
- s[i] = '?';
- }
-
- /* Remove trailing spaces */
- strim(s);
-}
-
-static u16 onfi_crc16(u16 crc, u8 const *p, size_t len)
-{
- int i;
- while (len--) {
- crc ^= *p++ << 8;
- for (i = 0; i < 8; i++)
- crc = (crc << 1) ^ ((crc & 0x8000) ? 0x8005 : 0);
- }
-
- return crc;
-}
-
-/*
- * Check if the NAND chip is ONFI compliant, returns 1 if it is, 0 otherwise.
- */
-static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip,
- int *busw)
-{
- struct nand_onfi_params *p = &chip->onfi_params;
- int i;
- int val;
-
- /* Try ONFI for unknown chip or LP */
- chip->cmdfunc(mtd, NAND_CMD_READID, 0x20, -1);
- if (chip->read_byte(mtd) != 'O' || chip->read_byte(mtd) != 'N' ||
- chip->read_byte(mtd) != 'F' || chip->read_byte(mtd) != 'I')
- return 0;
-
- chip->cmdfunc(mtd, NAND_CMD_PARAM, 0, -1);
- for (i = 0; i < 3; i++) {
- chip->read_buf(mtd, (uint8_t *)p, sizeof(*p));
- if (onfi_crc16(ONFI_CRC_BASE, (uint8_t *)p, 254) ==
- le16_to_cpu(p->crc)) {
- pr_info("ONFI param page %d valid\n", i);
- break;
- }
- }
-
- if (i == 3)
- return 0;
-
- /* Check version */
- val = le16_to_cpu(p->revision);
- if (val & (1 << 5))
- chip->onfi_version = 23;
- else if (val & (1 << 4))
- chip->onfi_version = 22;
- else if (val & (1 << 3))
- chip->onfi_version = 21;
- else if (val & (1 << 2))
- chip->onfi_version = 20;
- else if (val & (1 << 1))
- chip->onfi_version = 10;
- else
- chip->onfi_version = 0;
-
- if (!chip->onfi_version) {
- pr_info("%s: unsupported ONFI version: %d\n", __func__, val);
- return 0;
- }
-
- sanitize_string(p->manufacturer, sizeof(p->manufacturer));
- sanitize_string(p->model, sizeof(p->model));
- if (!mtd->name)
- mtd->name = p->model;
- mtd->writesize = le32_to_cpu(p->byte_per_page);
- mtd->erasesize = le32_to_cpu(p->pages_per_block) * mtd->writesize;
- mtd->oobsize = le16_to_cpu(p->spare_bytes_per_page);
- chip->chipsize = le32_to_cpu(p->blocks_per_lun);
- chip->chipsize *= (uint64_t)mtd->erasesize * p->lun_count;
- *busw = 0;
- if (le16_to_cpu(p->features) & 1)
- *busw = NAND_BUSWIDTH_16;
-
- pr_info("ONFI flash detected\n");
- return 1;
-}
-#else
-static inline int nand_flash_detect_onfi(struct mtd_info *mtd,
- struct nand_chip *chip,
- int *busw)
-{
- return 0;
-}
-#endif
-
-/*
- * nand_id_has_period - Check if an ID string has a given wraparound period
- * @id_data: the ID string
- * @arrlen: the length of the @id_data array
- * @period: the period of repitition
- *
- * Check if an ID string is repeated within a given sequence of bytes at
- * specific repetition interval period (e.g., {0x20,0x01,0x7F,0x20} has a
- * period of 2). This is a helper function for nand_id_len(). Returns non-zero
- * if the repetition has a period of @period; otherwise, returns zero.
- */
-static int nand_id_has_period(u8 *id_data, int arrlen, int period)
-{
- int i, j;
- for (i = 0; i < period; i++)
- for (j = i + period; j < arrlen; j += period)
- if (id_data[i] != id_data[j])
- return 0;
- return 1;
-}
-
-/*
- * nand_id_len - Get the length of an ID string returned by CMD_READID
- * @id_data: the ID string
- * @arrlen: the length of the @id_data array
-
- * Returns the length of the ID string, according to known wraparound/trailing
- * zero patterns. If no pattern exists, returns the length of the array.
- */
-static int nand_id_len(u8 *id_data, int arrlen)
-{
- int last_nonzero, period;
-
- /* Find last non-zero byte */
- for (last_nonzero = arrlen - 1; last_nonzero >= 0; last_nonzero--)
- if (id_data[last_nonzero])
- break;
-
- /* All zeros */
- if (last_nonzero < 0)
- return 0;
-
- /* Calculate wraparound period */
- for (period = 1; period < arrlen; period++)
- if (nand_id_has_period(id_data, arrlen, period))
- break;
-
- /* There's a repeated pattern */
- if (period < arrlen)
- return period;
-
- /* There are trailing zeros */
- if (last_nonzero < arrlen - 1)
- return last_nonzero + 1;
-
- /* No pattern detected */
- return arrlen;
-}
-
-/*
- * Many new NAND share similar device ID codes, which represent the size of the
- * chip. The rest of the parameters must be decoded according to generic or
- * manufacturer-specific "extended ID" decoding patterns.
- */
-static void nand_decode_ext_id(struct mtd_info *mtd, struct nand_chip *chip,
- u8 id_data[8], int *busw)
-{
- int extid, id_len;
- /* The 3rd id byte holds MLC / multichip data */
- chip->cellinfo = id_data[2];
- /* The 4th id byte is the important one */
- extid = id_data[3];
-
- id_len = nand_id_len(id_data, 8);
-
- /*
- * Field definitions are in the following datasheets:
- * Old style (4,5 byte ID): Samsung K9GAG08U0M (p.32)
- * New Samsung (6 byte ID): Samsung K9GAG08U0F (p.44)
- * Hynix MLC (6 byte ID): Hynix H27UBG8T2B (p.22)
- *
- * Check for ID length, non-zero 6th byte, cell type, and Hynix/Samsung
- * ID to decide what to do.
- */
- if (id_len == 6 && id_data[0] == NAND_MFR_SAMSUNG &&
- (chip->cellinfo & NAND_CI_CELLTYPE_MSK) &&
- id_data[5] != 0x00) {
- /* Calc pagesize */
- mtd->writesize = 2048 << (extid & 0x03);
- extid >>= 2;
- /* Calc oobsize */
- switch (((extid >> 2) & 0x04) | (extid & 0x03)) {
- case 1:
- mtd->oobsize = 128;
- break;
- case 2:
- mtd->oobsize = 218;
- break;
- case 3:
- mtd->oobsize = 400;
- break;
- case 4:
- mtd->oobsize = 436;
- break;
- case 5:
- mtd->oobsize = 512;
- break;
- case 6:
- default: /* Other cases are "reserved" (unknown) */
- mtd->oobsize = 640;
- break;
- }
- extid >>= 2;
- /* Calc blocksize */
- mtd->erasesize = (128 * 1024) <<
- (((extid >> 1) & 0x04) | (extid & 0x03));
- *busw = 0;
- } else if (id_len == 6 && id_data[0] == NAND_MFR_HYNIX &&
- (chip->cellinfo & NAND_CI_CELLTYPE_MSK)) {
- unsigned int tmp;
-
- /* Calc pagesize */
- mtd->writesize = 2048 << (extid & 0x03);
- extid >>= 2;
- /* Calc oobsize */
- switch (((extid >> 2) & 0x04) | (extid & 0x03)) {
- case 0:
- mtd->oobsize = 128;
- break;
- case 1:
- mtd->oobsize = 224;
- break;
- case 2:
- mtd->oobsize = 448;
- break;
- case 3:
- mtd->oobsize = 64;
- break;
- case 4:
- mtd->oobsize = 32;
- break;
- case 5:
- mtd->oobsize = 16;
- break;
- default:
- mtd->oobsize = 640;
- break;
- }
- extid >>= 2;
- /* Calc blocksize */
- tmp = ((extid >> 1) & 0x04) | (extid & 0x03);
- if (tmp < 0x03)
- mtd->erasesize = (128 * 1024) << tmp;
- else if (tmp == 0x03)
- mtd->erasesize = 768 * 1024;
- else
- mtd->erasesize = (64 * 1024) << tmp;
- *busw = 0;
- } else {
- /* Calc pagesize */
- mtd->writesize = 1024 << (extid & 0x03);
- extid >>= 2;
- /* Calc oobsize */
- mtd->oobsize = (8 << (extid & 0x01)) *
- (mtd->writesize >> 9);
- extid >>= 2;
- /* Calc blocksize. Blocksize is multiples of 64KiB */
- mtd->erasesize = (64 * 1024) << (extid & 0x03);
- extid >>= 2;
- /* Get buswidth information */
- *busw = (extid & 0x01) ? NAND_BUSWIDTH_16 : 0;
- }
-}
-
- /*
- * Old devices have chip data hardcoded in the device ID table. nand_decode_id
- * decodes a matching ID table entry and assigns the MTD size parameters for
- * the chip.
- */
-static void nand_decode_id(struct mtd_info *mtd, struct nand_chip *chip,
- const struct nand_flash_dev *type, u8 id_data[8],
- int *busw)
-{
- int maf_id = id_data[0];
-
- mtd->erasesize = type->erasesize;
- mtd->writesize = type->pagesize;
- mtd->oobsize = mtd->writesize / 32;
- *busw = type->options & NAND_BUSWIDTH_16;
-
- /*
- * Check for Spansion/AMD ID + repeating 5th, 6th byte since
- * some Spansion chips have erasesize that conflicts with size
- * listed in nand_ids table.
- * Data sheet (5 byte ID): Spansion S30ML-P ORNAND (p.39)
- */
- if (maf_id == NAND_MFR_AMD && id_data[4] != 0x00 && id_data[5] == 0x00
- && id_data[6] == 0x00 && id_data[7] == 0x00
- && mtd->writesize == 512) {
- mtd->erasesize = 128 * 1024;
- mtd->erasesize <<= ((id_data[3] & 0x03) << 1);
- }
-}
-
- /*
- * Set the bad block marker/indicator (BBM/BBI) patterns according to some
- * heuristic patterns using various detected parameters (e.g., manufacturer,
- * page size, cell-type information).
- */
-static void nand_decode_bbm_options(struct mtd_info *mtd,
- struct nand_chip *chip, u8 id_data[8])
-{
- int maf_id = id_data[0];
-
- /* Set the bad block position */
- if (mtd->writesize > 512 || (chip->options & NAND_BUSWIDTH_16))
- chip->badblockpos = NAND_LARGE_BADBLOCK_POS;
- else
- chip->badblockpos = NAND_SMALL_BADBLOCK_POS;
-
- /*
- * Bad block marker is stored in the last page of each block on Samsung
- * and Hynix MLC devices; stored in first two pages of each block on
- * Micron devices with 2KiB pages and on SLC Samsung, Hynix, Toshiba,
- * AMD/Spansion, and Macronix. All others scan only the first page.
- */
- if ((chip->cellinfo & NAND_CI_CELLTYPE_MSK) &&
- (maf_id == NAND_MFR_SAMSUNG ||
- maf_id == NAND_MFR_HYNIX))
- chip->bbt_options |= NAND_BBT_SCANLASTPAGE;
- else if ((!(chip->cellinfo & NAND_CI_CELLTYPE_MSK) &&
- (maf_id == NAND_MFR_SAMSUNG ||
- maf_id == NAND_MFR_HYNIX ||
- maf_id == NAND_MFR_TOSHIBA ||
- maf_id == NAND_MFR_AMD ||
- maf_id == NAND_MFR_MACRONIX)) ||
- (mtd->writesize == 2048 &&
- maf_id == NAND_MFR_MICRON))
- chip->bbt_options |= NAND_BBT_SCAN2NDPAGE;
-}
-
-/*
- * Get the flash and manufacturer id and lookup if the type is supported.
- */
-static const struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
- struct nand_chip *chip,
- int busw,
- int *maf_id, int *dev_id,
- const struct nand_flash_dev *type)
-{
- const char *name;
- int i, maf_idx;
- u8 id_data[8];
-
- /* Select the device */
- chip->select_chip(mtd, 0);
-
- /*
- * Reset the chip, required by some chips (e.g. Micron MT29FxGxxxxx)
- * after power-up.
- */
- chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
-
- /* Send the command for reading device ID */
- chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
-
- /* Read manufacturer and device IDs */
- *maf_id = chip->read_byte(mtd);
- *dev_id = chip->read_byte(mtd);
-
- /*
- * Try again to make sure, as some systems the bus-hold or other
- * interface concerns can cause random data which looks like a
- * possibly credible NAND flash to appear. If the two results do
- * not match, ignore the device completely.
- */
-
- chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
-
- /* Read entire ID string */
- for (i = 0; i < 8; i++)
- id_data[i] = chip->read_byte(mtd);
-
- if (id_data[0] != *maf_id || id_data[1] != *dev_id) {
- pr_info("%s: second ID read did not match "
- "%02x,%02x against %02x,%02x\n", __func__,
- *maf_id, *dev_id, id_data[0], id_data[1]);
- return ERR_PTR(-ENODEV);
- }
-
- if (!type)
- type = nand_flash_ids;
-
- for (; type->name != NULL; type++)
- if (*dev_id == type->id)
- break;
-
- chip->onfi_version = 0;
- if (!type->name || !type->pagesize) {
- /* Check is chip is ONFI compliant */
- if (nand_flash_detect_onfi(mtd, chip, &busw))
- goto ident_done;
- }
-
- if (!type->name)
- return ERR_PTR(-ENODEV);
-
- if (!mtd->name)
- mtd->name = type->name;
-
- chip->chipsize = (uint64_t)type->chipsize << 20;
-
- if (!type->pagesize && chip->init_size) {
- /* Set the pagesize, oobsize, erasesize by the driver */
- busw = chip->init_size(mtd, chip, id_data);
- } else if (!type->pagesize) {
- /* Decode parameters from extended ID */
- nand_decode_ext_id(mtd, chip, id_data, &busw);
- } else {
- nand_decode_id(mtd, chip, type, id_data, &busw);
- }
- /* Get chip options, preserve non chip based options */
- chip->options |= type->options;
-
- /*
- * Check if chip is not a Samsung device. Do not clear the
- * options for chips which do not have an extended id.
- */
- if (*maf_id != NAND_MFR_SAMSUNG && !type->pagesize)
- chip->options &= ~NAND_SAMSUNG_LP_OPTIONS;
-ident_done:
-
- /* Try to identify manufacturer */
- for (maf_idx = 0; nand_manuf_ids[maf_idx].id != 0x0; maf_idx++) {
- if (nand_manuf_ids[maf_idx].id == *maf_id)
- break;
- }
-
- /*
- * Check, if buswidth is correct. Hardware drivers should set
- * chip correct!
- */
- if (busw != (chip->options & NAND_BUSWIDTH_16)) {
- pr_info("NAND device: Manufacturer ID:"
- " 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id,
- *dev_id, nand_manuf_ids[maf_idx].name, mtd->name);
- pr_warn("NAND bus width %d instead %d bit\n",
- (chip->options & NAND_BUSWIDTH_16) ? 16 : 8,
- busw ? 16 : 8);
- return ERR_PTR(-EINVAL);
- }
-
- nand_decode_bbm_options(mtd, chip, id_data);
-
- /* Calculate the address shift from the page size */
- chip->page_shift = ffs(mtd->writesize) - 1;
- /* Convert chipsize to number of pages per chip -1 */
- chip->pagemask = (chip->chipsize >> chip->page_shift) - 1;
-
- chip->bbt_erase_shift = chip->phys_erase_shift =
- ffs(mtd->erasesize) - 1;
- if (chip->chipsize & 0xffffffff)
- chip->chip_shift = ffs((unsigned)chip->chipsize) - 1;
- else {
- chip->chip_shift = ffs((unsigned)(chip->chipsize >> 32));
- chip->chip_shift += 32 - 1;
- }
-
- chip->badblockbits = 8;
-
- /* Check for AND chips with 4 page planes */
- if (chip->options & NAND_4PAGE_ARRAY)
- chip->erase_cmd = multi_erase_cmd;
- else
- chip->erase_cmd = single_erase_cmd;
-
- /* Do not replace user supplied command function! */
- if (mtd->writesize > 512 && chip->cmdfunc == nand_command)
- chip->cmdfunc = nand_command_lp;
-
- name = type->name;
-#ifdef CONFIG_SYS_NAND_ONFI_DETECTION
- if (chip->onfi_version)
- name = chip->onfi_params.model;
-#endif
- pr_info("NAND device: Manufacturer ID: 0x%02x, Chip ID: 0x%02x (%s %s),"
- " page size: %d, OOB size: %d\n",
- *maf_id, *dev_id, nand_manuf_ids[maf_idx].name,
- name,
- mtd->writesize, mtd->oobsize);
-
- return type;
-}
-
-/**
- * nand_scan_ident - [NAND Interface] Scan for the NAND device
- * @mtd: MTD device structure
- * @maxchips: number of chips to scan for
- * @table: alternative NAND ID table
- *
- * This is the first phase of the normal nand_scan() function. It reads the
- * flash ID and sets up MTD fields accordingly.
- *
- * The mtd->owner field must be set to the module of the caller.
- */
-int nand_scan_ident(struct mtd_info *mtd, int maxchips,
- const struct nand_flash_dev *table)
-{
- int i, busw, nand_maf_id, nand_dev_id;
- struct nand_chip *chip = mtd->priv;
- const struct nand_flash_dev *type;
-
- /* Get buswidth to select the correct functions */
- busw = chip->options & NAND_BUSWIDTH_16;
- /* Set the default functions */
- nand_set_defaults(chip, busw);
-
- /* Read the flash type */
- type = nand_get_flash_type(mtd, chip, busw,
- &nand_maf_id, &nand_dev_id, table);
-
- if (IS_ERR(type)) {
-#ifndef CONFIG_SYS_NAND_QUIET_TEST
- pr_warn("No NAND device found\n");
-#endif
- chip->select_chip(mtd, -1);
- return PTR_ERR(type);
- }
-
- /* Check for a chip array */
- for (i = 1; i < maxchips; i++) {
- chip->select_chip(mtd, i);
- /* See comment in nand_get_flash_type for reset */
- chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
- /* Send the command for reading device ID */
- chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
- /* Read manufacturer and device IDs */
- if (nand_maf_id != chip->read_byte(mtd) ||
- nand_dev_id != chip->read_byte(mtd))
- break;
- }
-#ifdef DEBUG
- if (i > 1)
- pr_info("%d NAND chips detected\n", i);
-#endif
-
- /* Store the number of chips and calc total size for mtd */
- chip->numchips = i;
- mtd->size = i * chip->chipsize;
-
- return 0;
-}
-
-
-/**
- * nand_scan_tail - [NAND Interface] Scan for the NAND device
- * @mtd: MTD device structure
- *
- * This is the second phase of the normal nand_scan() function. It fills out
- * all the uninitialized function pointers with the defaults and scans for a
- * bad block table if appropriate.
- */
-int nand_scan_tail(struct mtd_info *mtd)
-{
- int i;
- struct nand_chip *chip = mtd->priv;
-
- /* New bad blocks should be marked in OOB, flash-based BBT, or both */
- BUG_ON((chip->bbt_options & NAND_BBT_NO_OOB_BBM) &&
- !(chip->bbt_options & NAND_BBT_USE_FLASH));
-
- if (!(chip->options & NAND_OWN_BUFFERS))
- chip->buffers = memalign(ARCH_DMA_MINALIGN,
- sizeof(*chip->buffers));
- if (!chip->buffers)
- return -ENOMEM;
-
- /* Set the internal oob buffer location, just after the page data */
- chip->oob_poi = chip->buffers->databuf + mtd->writesize;
-
- /*
- * If no default placement scheme is given, select an appropriate one.
- */
- if (!chip->ecc.layout && (chip->ecc.mode != NAND_ECC_SOFT_BCH)) {
- switch (mtd->oobsize) {
- case 8:
- chip->ecc.layout = &nand_oob_8;
- break;
- case 16:
- chip->ecc.layout = &nand_oob_16;
- break;
- case 64:
- chip->ecc.layout = &nand_oob_64;
- break;
- case 128:
- chip->ecc.layout = &nand_oob_128;
- break;
- default:
- pr_warn("No oob scheme defined for oobsize %d\n",
- mtd->oobsize);
- }
- }
-
- if (!chip->write_page)
- chip->write_page = nand_write_page;
-
- /* set for ONFI nand */
- if (!chip->onfi_set_features)
- chip->onfi_set_features = nand_onfi_set_features;
- if (!chip->onfi_get_features)
- chip->onfi_get_features = nand_onfi_get_features;
-
- /*
- * Check ECC mode, default to software if 3byte/512byte hardware ECC is
- * selected and we have 256 byte pagesize fallback to software ECC
- */
-
- switch (chip->ecc.mode) {
- case NAND_ECC_HW_OOB_FIRST:
- /* Similar to NAND_ECC_HW, but a separate read_page handle */
- if (!chip->ecc.calculate || !chip->ecc.correct ||
- !chip->ecc.hwctl) {
- pr_warn("No ECC functions supplied; "
- "hardware ECC not possible\n");
- BUG();
- }
- if (!chip->ecc.read_page)
- chip->ecc.read_page = nand_read_page_hwecc_oob_first;
-
- case NAND_ECC_HW:
- /* Use standard hwecc read page function? */
- if (!chip->ecc.read_page)
- chip->ecc.read_page = nand_read_page_hwecc;
- if (!chip->ecc.write_page)
- chip->ecc.write_page = nand_write_page_hwecc;
- if (!chip->ecc.read_page_raw)
- chip->ecc.read_page_raw = nand_read_page_raw;
- if (!chip->ecc.write_page_raw)
- chip->ecc.write_page_raw = nand_write_page_raw;
- if (!chip->ecc.read_oob)
- chip->ecc.read_oob = nand_read_oob_std;
- if (!chip->ecc.write_oob)
- chip->ecc.write_oob = nand_write_oob_std;
-
- case NAND_ECC_HW_SYNDROME:
- if ((!chip->ecc.calculate || !chip->ecc.correct ||
- !chip->ecc.hwctl) &&
- (!chip->ecc.read_page ||
- chip->ecc.read_page == nand_read_page_hwecc ||
- !chip->ecc.write_page ||
- chip->ecc.write_page == nand_write_page_hwecc)) {
- pr_warn("No ECC functions supplied; "
- "hardware ECC not possible\n");
- BUG();
- }
- /* Use standard syndrome read/write page function? */
- if (!chip->ecc.read_page)
- chip->ecc.read_page = nand_read_page_syndrome;
- if (!chip->ecc.write_page)
- chip->ecc.write_page = nand_write_page_syndrome;
- if (!chip->ecc.read_page_raw)
- chip->ecc.read_page_raw = nand_read_page_raw_syndrome;
- if (!chip->ecc.write_page_raw)
- chip->ecc.write_page_raw = nand_write_page_raw_syndrome;
- if (!chip->ecc.read_oob)
- chip->ecc.read_oob = nand_read_oob_syndrome;
- if (!chip->ecc.write_oob)
- chip->ecc.write_oob = nand_write_oob_syndrome;
-
- if (mtd->writesize >= chip->ecc.size) {
- if (!chip->ecc.strength) {
- pr_warn("Driver must set ecc.strength when using hardware ECC\n");
- BUG();
- }
- break;
- }
- pr_warn("%d byte HW ECC not possible on "
- "%d byte page size, fallback to SW ECC\n",
- chip->ecc.size, mtd->writesize);
- chip->ecc.mode = NAND_ECC_SOFT;
-
- case NAND_ECC_SOFT:
- chip->ecc.calculate = nand_calculate_ecc;
- chip->ecc.correct = nand_correct_data;
- chip->ecc.read_page = nand_read_page_swecc;
- chip->ecc.read_subpage = nand_read_subpage;
- chip->ecc.write_page = nand_write_page_swecc;
- chip->ecc.read_page_raw = nand_read_page_raw;
- chip->ecc.write_page_raw = nand_write_page_raw;
- chip->ecc.read_oob = nand_read_oob_std;
- chip->ecc.write_oob = nand_write_oob_std;
- if (!chip->ecc.size)
- chip->ecc.size = 256;
- chip->ecc.bytes = 3;
- chip->ecc.strength = 1;
- break;
-
- case NAND_ECC_SOFT_BCH:
- if (!mtd_nand_has_bch()) {
- pr_warn("CONFIG_MTD_ECC_BCH not enabled\n");
- return -EINVAL;
- }
- chip->ecc.calculate = nand_bch_calculate_ecc;
- chip->ecc.correct = nand_bch_correct_data;
- chip->ecc.read_page = nand_read_page_swecc;
- chip->ecc.read_subpage = nand_read_subpage;
- chip->ecc.write_page = nand_write_page_swecc;
- chip->ecc.read_page_raw = nand_read_page_raw;
- chip->ecc.write_page_raw = nand_write_page_raw;
- chip->ecc.read_oob = nand_read_oob_std;
- chip->ecc.write_oob = nand_write_oob_std;
- /*
- * Board driver should supply ecc.size and ecc.bytes values to
- * select how many bits are correctable; see nand_bch_init()
- * for details. Otherwise, default to 4 bits for large page
- * devices.
- */
- if (!chip->ecc.size && (mtd->oobsize >= 64)) {
- chip->ecc.size = 512;
- chip->ecc.bytes = 7;
- }
- chip->ecc.priv = nand_bch_init(mtd,
- chip->ecc.size,
- chip->ecc.bytes,
- &chip->ecc.layout);
- if (!chip->ecc.priv)
- pr_warn("BCH ECC initialization failed!\n");
- chip->ecc.strength =
- chip->ecc.bytes * 8 / fls(8 * chip->ecc.size);
- break;
-
- case NAND_ECC_NONE:
- pr_warn("NAND_ECC_NONE selected by board driver. "
- "This is not recommended !!\n");
- chip->ecc.read_page = nand_read_page_raw;
- chip->ecc.write_page = nand_write_page_raw;
- chip->ecc.read_oob = nand_read_oob_std;
- chip->ecc.read_page_raw = nand_read_page_raw;
- chip->ecc.write_page_raw = nand_write_page_raw;
- chip->ecc.write_oob = nand_write_oob_std;
- chip->ecc.size = mtd->writesize;
- chip->ecc.bytes = 0;
- break;
-
- default:
- pr_warn("Invalid NAND_ECC_MODE %d\n", chip->ecc.mode);
- BUG();
- }
-
- /* For many systems, the standard OOB write also works for raw */
- if (!chip->ecc.read_oob_raw)
- chip->ecc.read_oob_raw = chip->ecc.read_oob;
- if (!chip->ecc.write_oob_raw)
- chip->ecc.write_oob_raw = chip->ecc.write_oob;
-
- /*
- * The number of bytes available for a client to place data into
- * the out of band area.
- */
- chip->ecc.layout->oobavail = 0;
- for (i = 0; chip->ecc.layout->oobfree[i].length
- && i < ARRAY_SIZE(chip->ecc.layout->oobfree); i++)
- chip->ecc.layout->oobavail +=
- chip->ecc.layout->oobfree[i].length;
- mtd->oobavail = chip->ecc.layout->oobavail;
-
- /*
- * Set the number of read / write steps for one page depending on ECC
- * mode.
- */
- chip->ecc.steps = mtd->writesize / chip->ecc.size;
- if (chip->ecc.steps * chip->ecc.size != mtd->writesize) {
- pr_warn("Invalid ECC parameters\n");
- BUG();
- }
- chip->ecc.total = chip->ecc.steps * chip->ecc.bytes;
-
- /* Allow subpage writes up to ecc.steps. Not possible for MLC flash */
- if (!(chip->options & NAND_NO_SUBPAGE_WRITE) &&
- !(chip->cellinfo & NAND_CI_CELLTYPE_MSK)) {
- switch (chip->ecc.steps) {
- case 2:
- mtd->subpage_sft = 1;
- break;
- case 4:
- case 8:
- case 16:
- mtd->subpage_sft = 2;
- break;
- }
- }
- chip->subpagesize = mtd->writesize >> mtd->subpage_sft;
-
- /* Initialize state */
- chip->state = FL_READY;
-
- /* De-select the device */
- chip->select_chip(mtd, -1);
-
- /* Invalidate the pagebuffer reference */
- chip->pagebuf = -1;
-
- /* Large page NAND with SOFT_ECC should support subpage reads */
- if ((chip->ecc.mode == NAND_ECC_SOFT) && (chip->page_shift > 9))
- chip->options |= NAND_SUBPAGE_READ;
-
- /* Fill in remaining MTD driver data */
- mtd->type = MTD_NANDFLASH;
- mtd->flags = (chip->options & NAND_ROM) ? MTD_CAP_ROM :
- MTD_CAP_NANDFLASH;
- mtd->_erase = nand_erase;
- mtd->_point = NULL;
- mtd->_unpoint = NULL;
- mtd->_read = nand_read;
- mtd->_write = nand_write;
- mtd->_read_oob = nand_read_oob;
- mtd->_write_oob = nand_write_oob;
- mtd->_sync = nand_sync;
- mtd->_lock = NULL;
- mtd->_unlock = NULL;
- mtd->_block_isbad = nand_block_isbad;
- mtd->_block_markbad = nand_block_markbad;
-
- /* propagate ecc info to mtd_info */
- mtd->ecclayout = chip->ecc.layout;
- mtd->ecc_strength = chip->ecc.strength;
- /*
- * Initialize bitflip_threshold to its default prior scan_bbt() call.
- * scan_bbt() might invoke mtd_read(), thus bitflip_threshold must be
- * properly set.
- */
- if (!mtd->bitflip_threshold)
- mtd->bitflip_threshold = mtd->ecc_strength;
-
- /* Check, if we should skip the bad block table scan */
- if (chip->options & NAND_SKIP_BBTSCAN)
- chip->options |= NAND_BBT_SCANNED;
-
- return 0;
-}
-
-/**
- * nand_scan - [NAND Interface] Scan for the NAND device
- * @mtd: MTD device structure
- * @maxchips: number of chips to scan for
- *
- * This fills out all the uninitialized function pointers with the defaults.
- * The flash ID is read and the mtd/chip structures are filled with the
- * appropriate values. The mtd->owner field must be set to the module of the
- * caller.
- */
-int nand_scan(struct mtd_info *mtd, int maxchips)
-{
- int ret;
-
- ret = nand_scan_ident(mtd, maxchips, NULL);
- if (!ret)
- ret = nand_scan_tail(mtd);
- return ret;
-}
-
-/**
- * nand_release - [NAND Interface] Free resources held by the NAND device
- * @mtd: MTD device structure
- */
-void nand_release(struct mtd_info *mtd)
-{
- struct nand_chip *chip = mtd->priv;
-
- if (chip->ecc.mode == NAND_ECC_SOFT_BCH)
- nand_bch_free((struct nand_bch_control *)chip->ecc.priv);
-
-#ifdef CONFIG_MTD_PARTITIONS
- /* Deregister partitions */
- del_mtd_partitions(mtd);
-#endif
-
- /* Free bad block table memory */
- kfree(chip->bbt);
- if (!(chip->options & NAND_OWN_BUFFERS))
- kfree(chip->buffers);
-
- /* Free bad block descriptor memory */
- if (chip->badblock_pattern && chip->badblock_pattern->options
- & NAND_BBT_DYNAMICSTRUCT)
- kfree(chip->badblock_pattern);
-}
diff --git a/qemu/roms/u-boot/drivers/mtd/nand/nand_bbt.c b/qemu/roms/u-boot/drivers/mtd/nand/nand_bbt.c
deleted file mode 100644
index 8ef58451d..000000000
--- a/qemu/roms/u-boot/drivers/mtd/nand/nand_bbt.c
+++ /dev/null
@@ -1,1397 +0,0 @@
-/*
- * drivers/mtd/nand_bbt.c
- *
- * Overview:
- * Bad block table support for the NAND driver
- *
- * Copyright © 2004 Thomas Gleixner (tglx@linutronix.de)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Description:
- *
- * When nand_scan_bbt is called, then it tries to find the bad block table
- * depending on the options in the BBT descriptor(s). If no flash based BBT
- * (NAND_BBT_USE_FLASH) is specified then the device is scanned for factory
- * marked good / bad blocks. This information is used to create a memory BBT.
- * Once a new bad block is discovered then the "factory" information is updated
- * on the device.
- * If a flash based BBT is specified then the function first tries to find the
- * BBT on flash. If a BBT is found then the contents are read and the memory
- * based BBT is created. If a mirrored BBT is selected then the mirror is
- * searched too and the versions are compared. If the mirror has a greater
- * version number, then the mirror BBT is used to build the memory based BBT.
- * If the tables are not versioned, then we "or" the bad block information.
- * If one of the BBTs is out of date or does not exist it is (re)created.
- * If no BBT exists at all then the device is scanned for factory marked
- * good / bad blocks and the bad block tables are created.
- *
- * For manufacturer created BBTs like the one found on M-SYS DOC devices
- * the BBT is searched and read but never created
- *
- * The auto generated bad block table is located in the last good blocks
- * of the device. The table is mirrored, so it can be updated eventually.
- * The table is marked in the OOB area with an ident pattern and a version
- * number which indicates which of both tables is more up to date. If the NAND
- * controller needs the complete OOB area for the ECC information then the
- * option NAND_BBT_NO_OOB should be used (along with NAND_BBT_USE_FLASH, of
- * course): it moves the ident pattern and the version byte into the data area
- * and the OOB area will remain untouched.
- *
- * The table uses 2 bits per block
- * 11b: block is good
- * 00b: block is factory marked bad
- * 01b, 10b: block is marked bad due to wear
- *
- * The memory bad block table uses the following scheme:
- * 00b: block is good
- * 01b: block is marked bad due to wear
- * 10b: block is reserved (to protect the bbt area)
- * 11b: block is factory marked bad
- *
- * Multichip devices like DOC store the bad block info per floor.
- *
- * Following assumptions are made:
- * - bbts start at a page boundary, if autolocated on a block boundary
- * - the space necessary for a bbt in FLASH does not exceed a block boundary
- *
- */
-
-#include <common.h>
-#include <malloc.h>
-#include <linux/compat.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/bbm.h>
-#include <linux/mtd/nand.h>
-#include <linux/mtd/nand_ecc.h>
-#include <linux/bitops.h>
-#include <linux/string.h>
-
-#include <asm/errno.h>
-
-static int check_pattern_no_oob(uint8_t *buf, struct nand_bbt_descr *td)
-{
- if (memcmp(buf, td->pattern, td->len))
- return -1;
- return 0;
-}
-
-/**
- * check_pattern - [GENERIC] check if a pattern is in the buffer
- * @buf: the buffer to search
- * @len: the length of buffer to search
- * @paglen: the pagelength
- * @td: search pattern descriptor
- *
- * Check for a pattern at the given place. Used to search bad block tables and
- * good / bad block identifiers. If the SCAN_EMPTY option is set then check, if
- * all bytes except the pattern area contain 0xff.
- */
-static int check_pattern(uint8_t *buf, int len, int paglen, struct nand_bbt_descr *td)
-{
- int end = 0;
- uint8_t *p = buf;
-
- if (td->options & NAND_BBT_NO_OOB)
- return check_pattern_no_oob(buf, td);
-
- end = paglen + td->offs;
- if (td->options & NAND_BBT_SCANEMPTY)
- if (memchr_inv(p, 0xff, end))
- return -1;
- p += end;
-
- /* Compare the pattern */
- if (memcmp(p, td->pattern, td->len))
- return -1;
-
- if (td->options & NAND_BBT_SCANEMPTY) {
- p += td->len;
- end += td->len;
- if (memchr_inv(p, 0xff, len - end))
- return -1;
- }
- return 0;
-}
-
-/**
- * check_short_pattern - [GENERIC] check if a pattern is in the buffer
- * @buf: the buffer to search
- * @td: search pattern descriptor
- *
- * Check for a pattern at the given place. Used to search bad block tables and
- * good / bad block identifiers. Same as check_pattern, but no optional empty
- * check.
- */
-static int check_short_pattern(uint8_t *buf, struct nand_bbt_descr *td)
-{
- /* Compare the pattern */
- if (memcmp(buf + td->offs, td->pattern, td->len))
- return -1;
- return 0;
-}
-
-/**
- * add_marker_len - compute the length of the marker in data area
- * @td: BBT descriptor used for computation
- *
- * The length will be 0 if the marker is located in OOB area.
- */
-static u32 add_marker_len(struct nand_bbt_descr *td)
-{
- u32 len;
-
- if (!(td->options & NAND_BBT_NO_OOB))
- return 0;
-
- len = td->len;
- if (td->options & NAND_BBT_VERSION)
- len++;
- return len;
-}
-
-/**
- * read_bbt - [GENERIC] Read the bad block table starting from page
- * @mtd: MTD device structure
- * @buf: temporary buffer
- * @page: the starting page
- * @num: the number of bbt descriptors to read
- * @td: the bbt describtion table
- * @offs: offset in the memory table
- *
- * Read the bad block table starting from page.
- */
-static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num,
- struct nand_bbt_descr *td, int offs)
-{
- int res, ret = 0, i, j, act = 0;
- struct nand_chip *this = mtd->priv;
- size_t retlen, len, totlen;
- loff_t from;
- int bits = td->options & NAND_BBT_NRBITS_MSK;
- uint8_t msk = (uint8_t)((1 << bits) - 1);
- u32 marker_len;
- int reserved_block_code = td->reserved_block_code;
-
- totlen = (num * bits) >> 3;
- marker_len = add_marker_len(td);
- from = ((loff_t)page) << this->page_shift;
-
- while (totlen) {
- len = min(totlen, (size_t)(1 << this->bbt_erase_shift));
- if (marker_len) {
- /*
- * In case the BBT marker is not in the OOB area it
- * will be just in the first page.
- */
- len -= marker_len;
- from += marker_len;
- marker_len = 0;
- }
- res = mtd_read(mtd, from, len, &retlen, buf);
- if (res < 0) {
- if (mtd_is_eccerr(res)) {
- pr_info("nand_bbt: ECC error in BBT at "
- "0x%012llx\n", from & ~mtd->writesize);
- return res;
- } else if (mtd_is_bitflip(res)) {
- pr_info("nand_bbt: corrected error in BBT at "
- "0x%012llx\n", from & ~mtd->writesize);
- ret = res;
- } else {
- pr_info("nand_bbt: error reading BBT\n");
- return res;
- }
- }
-
- /* Analyse data */
- for (i = 0; i < len; i++) {
- uint8_t dat = buf[i];
- for (j = 0; j < 8; j += bits, act += 2) {
- uint8_t tmp = (dat >> j) & msk;
- if (tmp == msk)
- continue;
- if (reserved_block_code && (tmp == reserved_block_code)) {
- pr_info("nand_read_bbt: reserved block at 0x%012llx\n",
- (loff_t)((offs << 2) + (act >> 1)) << this->bbt_erase_shift);
- this->bbt[offs + (act >> 3)] |= 0x2 << (act & 0x06);
- mtd->ecc_stats.bbtblocks++;
- continue;
- }
- pr_info("nand_read_bbt: Bad block at 0x%012llx\n",
- (loff_t)((offs << 2) + (act >> 1))
- << this->bbt_erase_shift);
- /* Factory marked bad or worn out? */
- if (tmp == 0)
- this->bbt[offs + (act >> 3)] |= 0x3 << (act & 0x06);
- else
- this->bbt[offs + (act >> 3)] |= 0x1 << (act & 0x06);
- mtd->ecc_stats.badblocks++;
- }
- }
- totlen -= len;
- from += len;
- }
- return ret;
-}
-
-/**
- * read_abs_bbt - [GENERIC] Read the bad block table starting at a given page
- * @mtd: MTD device structure
- * @buf: temporary buffer
- * @td: descriptor for the bad block table
- * @chip: read the table for a specific chip, -1 read all chips; applies only if
- * NAND_BBT_PERCHIP option is set
- *
- * Read the bad block table for all chips starting at a given page. We assume
- * that the bbt bits are in consecutive order.
- */
-static int read_abs_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td, int chip)
-{
- struct nand_chip *this = mtd->priv;
- int res = 0, i;
-
- if (td->options & NAND_BBT_PERCHIP) {
- int offs = 0;
- for (i = 0; i < this->numchips; i++) {
- if (chip == -1 || chip == i)
- res = read_bbt(mtd, buf, td->pages[i],
- this->chipsize >> this->bbt_erase_shift,
- td, offs);
- if (res)
- return res;
- offs += this->chipsize >> (this->bbt_erase_shift + 2);
- }
- } else {
- res = read_bbt(mtd, buf, td->pages[0],
- mtd->size >> this->bbt_erase_shift, td, 0);
- if (res)
- return res;
- }
- return 0;
-}
-
-/* BBT marker is in the first page, no OOB */
-static int scan_read_data(struct mtd_info *mtd, uint8_t *buf, loff_t offs,
- struct nand_bbt_descr *td)
-{
- size_t retlen;
- size_t len;
-
- len = td->len;
- if (td->options & NAND_BBT_VERSION)
- len++;
-
- return mtd_read(mtd, offs, len, &retlen, buf);
-}
-
-/**
- * scan_read_oob - [GENERIC] Scan data+OOB region to buffer
- * @mtd: MTD device structure
- * @buf: temporary buffer
- * @offs: offset at which to scan
- * @len: length of data region to read
- *
- * Scan read data from data+OOB. May traverse multiple pages, interleaving
- * page,OOB,page,OOB,... in buf. Completes transfer and returns the "strongest"
- * ECC condition (error or bitflip). May quit on the first (non-ECC) error.
- */
-static int scan_read_oob(struct mtd_info *mtd, uint8_t *buf, loff_t offs,
- size_t len)
-{
- struct mtd_oob_ops ops;
- int res, ret = 0;
-
- ops.mode = MTD_OPS_PLACE_OOB;
- ops.ooboffs = 0;
- ops.ooblen = mtd->oobsize;
-
- while (len > 0) {
- ops.datbuf = buf;
- ops.len = min(len, (size_t)mtd->writesize);
- ops.oobbuf = buf + ops.len;
-
- res = mtd_read_oob(mtd, offs, &ops);
- if (res) {
- if (!mtd_is_bitflip_or_eccerr(res))
- return res;
- else if (mtd_is_eccerr(res) || !ret)
- ret = res;
- }
-
- buf += mtd->oobsize + mtd->writesize;
- len -= mtd->writesize;
- offs += mtd->writesize;
- }
- return ret;
-}
-
-static int scan_read(struct mtd_info *mtd, uint8_t *buf, loff_t offs,
- size_t len, struct nand_bbt_descr *td)
-{
- if (td->options & NAND_BBT_NO_OOB)
- return scan_read_data(mtd, buf, offs, td);
- else
- return scan_read_oob(mtd, buf, offs, len);
-}
-
-/* Scan write data with oob to flash */
-static int scan_write_bbt(struct mtd_info *mtd, loff_t offs, size_t len,
- uint8_t *buf, uint8_t *oob)
-{
- struct mtd_oob_ops ops;
-
- ops.mode = MTD_OPS_PLACE_OOB;
- ops.ooboffs = 0;
- ops.ooblen = mtd->oobsize;
- ops.datbuf = buf;
- ops.oobbuf = oob;
- ops.len = len;
-
- return mtd_write_oob(mtd, offs, &ops);
-}
-
-static u32 bbt_get_ver_offs(struct mtd_info *mtd, struct nand_bbt_descr *td)
-{
- u32 ver_offs = td->veroffs;
-
- if (!(td->options & NAND_BBT_NO_OOB))
- ver_offs += mtd->writesize;
- return ver_offs;
-}
-
-/**
- * read_abs_bbts - [GENERIC] Read the bad block table(s) for all chips starting at a given page
- * @mtd: MTD device structure
- * @buf: temporary buffer
- * @td: descriptor for the bad block table
- * @md: descriptor for the bad block table mirror
- *
- * Read the bad block table(s) for all chips starting at a given page. We
- * assume that the bbt bits are in consecutive order.
- */
-static void read_abs_bbts(struct mtd_info *mtd, uint8_t *buf,
- struct nand_bbt_descr *td, struct nand_bbt_descr *md)
-{
- struct nand_chip *this = mtd->priv;
-
- /* Read the primary version, if available */
- if (td->options & NAND_BBT_VERSION) {
- scan_read(mtd, buf, (loff_t)td->pages[0] << this->page_shift,
- mtd->writesize, td);
- td->version[0] = buf[bbt_get_ver_offs(mtd, td)];
- pr_info("Bad block table at page %d, version 0x%02X\n",
- td->pages[0], td->version[0]);
- }
-
- /* Read the mirror version, if available */
- if (md && (md->options & NAND_BBT_VERSION)) {
- scan_read(mtd, buf, (loff_t)md->pages[0] << this->page_shift,
- mtd->writesize, md);
- md->version[0] = buf[bbt_get_ver_offs(mtd, md)];
- pr_info("Bad block table at page %d, version 0x%02X\n",
- md->pages[0], md->version[0]);
- }
-}
-
-/* Scan a given block full */
-static int scan_block_full(struct mtd_info *mtd, struct nand_bbt_descr *bd,
- loff_t offs, uint8_t *buf, size_t readlen,
- int scanlen, int numpages)
-{
- int ret, j;
-
- ret = scan_read_oob(mtd, buf, offs, readlen);
- /* Ignore ECC errors when checking for BBM */
- if (ret && !mtd_is_bitflip_or_eccerr(ret))
- return ret;
-
- for (j = 0; j < numpages; j++, buf += scanlen) {
- if (check_pattern(buf, scanlen, mtd->writesize, bd))
- return 1;
- }
- return 0;
-}
-
-/* Scan a given block partially */
-static int scan_block_fast(struct mtd_info *mtd, struct nand_bbt_descr *bd,
- loff_t offs, uint8_t *buf, int numpages)
-{
- struct mtd_oob_ops ops;
- int j, ret;
-
- ops.ooblen = mtd->oobsize;
- ops.oobbuf = buf;
- ops.ooboffs = 0;
- ops.datbuf = NULL;
- ops.mode = MTD_OPS_PLACE_OOB;
-
- for (j = 0; j < numpages; j++) {
- /*
- * Read the full oob until read_oob is fixed to handle single
- * byte reads for 16 bit buswidth.
- */
- ret = mtd_read_oob(mtd, offs, &ops);
- /* Ignore ECC errors when checking for BBM */
- if (ret && !mtd_is_bitflip_or_eccerr(ret))
- return ret;
-
- if (check_short_pattern(buf, bd))
- return 1;
-
- offs += mtd->writesize;
- }
- return 0;
-}
-
-/**
- * create_bbt - [GENERIC] Create a bad block table by scanning the device
- * @mtd: MTD device structure
- * @buf: temporary buffer
- * @bd: descriptor for the good/bad block search pattern
- * @chip: create the table for a specific chip, -1 read all chips; applies only
- * if NAND_BBT_PERCHIP option is set
- *
- * Create a bad block table by scanning the device for the given good/bad block
- * identify pattern.
- */
-static int create_bbt(struct mtd_info *mtd, uint8_t *buf,
- struct nand_bbt_descr *bd, int chip)
-{
- struct nand_chip *this = mtd->priv;
- int i, numblocks, numpages, scanlen;
- int startblock;
- loff_t from;
- size_t readlen;
-
- pr_info("Scanning device for bad blocks\n");
-
- if (bd->options & NAND_BBT_SCANALLPAGES)
- numpages = 1 << (this->bbt_erase_shift - this->page_shift);
- else if (bd->options & NAND_BBT_SCAN2NDPAGE)
- numpages = 2;
- else
- numpages = 1;
-
- if (!(bd->options & NAND_BBT_SCANEMPTY)) {
- /* We need only read few bytes from the OOB area */
- scanlen = 0;
- readlen = bd->len;
- } else {
- /* Full page content should be read */
- scanlen = mtd->writesize + mtd->oobsize;
- readlen = numpages * mtd->writesize;
- }
-
- if (chip == -1) {
- /*
- * Note that numblocks is 2 * (real numblocks) here, see i+=2
- * below as it makes shifting and masking less painful
- */
- numblocks = mtd->size >> (this->bbt_erase_shift - 1);
- startblock = 0;
- from = 0;
- } else {
- if (chip >= this->numchips) {
- pr_warn("create_bbt(): chipnr (%d) > available chips (%d)\n",
- chip + 1, this->numchips);
- return -EINVAL;
- }
- numblocks = this->chipsize >> (this->bbt_erase_shift - 1);
- startblock = chip * numblocks;
- numblocks += startblock;
- from = (loff_t)startblock << (this->bbt_erase_shift - 1);
- }
-
- if (this->bbt_options & NAND_BBT_SCANLASTPAGE)
- from += mtd->erasesize - (mtd->writesize * numpages);
-
- for (i = startblock; i < numblocks;) {
- int ret;
-
- BUG_ON(bd->options & NAND_BBT_NO_OOB);
-
- if (bd->options & NAND_BBT_SCANALLPAGES)
- ret = scan_block_full(mtd, bd, from, buf, readlen,
- scanlen, numpages);
- else
- ret = scan_block_fast(mtd, bd, from, buf, numpages);
-
- if (ret < 0)
- return ret;
-
- if (ret) {
- this->bbt[i >> 3] |= 0x03 << (i & 0x6);
- pr_warn("Bad eraseblock %d at 0x%012llx\n",
- i >> 1, (unsigned long long)from);
- mtd->ecc_stats.badblocks++;
- }
-
- i += 2;
- from += (1 << this->bbt_erase_shift);
- }
- return 0;
-}
-
-/**
- * search_bbt - [GENERIC] scan the device for a specific bad block table
- * @mtd: MTD device structure
- * @buf: temporary buffer
- * @td: descriptor for the bad block table
- *
- * Read the bad block table by searching for a given ident pattern. Search is
- * preformed either from the beginning up or from the end of the device
- * downwards. The search starts always at the start of a block. If the option
- * NAND_BBT_PERCHIP is given, each chip is searched for a bbt, which contains
- * the bad block information of this chip. This is necessary to provide support
- * for certain DOC devices.
- *
- * The bbt ident pattern resides in the oob area of the first page in a block.
- */
-static int search_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td)
-{
- struct nand_chip *this = mtd->priv;
- int i, chips;
- int startblock, block, dir;
- int scanlen = mtd->writesize + mtd->oobsize;
- int bbtblocks;
- int blocktopage = this->bbt_erase_shift - this->page_shift;
-
- /* Search direction top -> down? */
- if (td->options & NAND_BBT_LASTBLOCK) {
- startblock = (mtd->size >> this->bbt_erase_shift) - 1;
- dir = -1;
- } else {
- startblock = 0;
- dir = 1;
- }
-
- /* Do we have a bbt per chip? */
- if (td->options & NAND_BBT_PERCHIP) {
- chips = this->numchips;
- bbtblocks = this->chipsize >> this->bbt_erase_shift;
- startblock &= bbtblocks - 1;
- } else {
- chips = 1;
- bbtblocks = mtd->size >> this->bbt_erase_shift;
- }
-
- for (i = 0; i < chips; i++) {
- /* Reset version information */
- td->version[i] = 0;
- td->pages[i] = -1;
- /* Scan the maximum number of blocks */
- for (block = 0; block < td->maxblocks; block++) {
-
- int actblock = startblock + dir * block;
- loff_t offs = (loff_t)actblock << this->bbt_erase_shift;
-
- /* Read first page */
- scan_read(mtd, buf, offs, mtd->writesize, td);
- if (!check_pattern(buf, scanlen, mtd->writesize, td)) {
- td->pages[i] = actblock << blocktopage;
- if (td->options & NAND_BBT_VERSION) {
- offs = bbt_get_ver_offs(mtd, td);
- td->version[i] = buf[offs];
- }
- break;
- }
- }
- startblock += this->chipsize >> this->bbt_erase_shift;
- }
- /* Check, if we found a bbt for each requested chip */
- for (i = 0; i < chips; i++) {
- if (td->pages[i] == -1)
- pr_warn("Bad block table not found for chip %d\n", i);
- else
- pr_info("Bad block table found at page %d, version 0x%02X\n", td->pages[i],
- td->version[i]);
- }
- return 0;
-}
-
-/**
- * search_read_bbts - [GENERIC] scan the device for bad block table(s)
- * @mtd: MTD device structure
- * @buf: temporary buffer
- * @td: descriptor for the bad block table
- * @md: descriptor for the bad block table mirror
- *
- * Search and read the bad block table(s).
- */
-static void search_read_bbts(struct mtd_info *mtd, uint8_t *buf,
- struct nand_bbt_descr *td,
- struct nand_bbt_descr *md)
-{
- /* Search the primary table */
- search_bbt(mtd, buf, td);
-
- /* Search the mirror table */
- if (md)
- search_bbt(mtd, buf, md);
-}
-
-/**
- * write_bbt - [GENERIC] (Re)write the bad block table
- * @mtd: MTD device structure
- * @buf: temporary buffer
- * @td: descriptor for the bad block table
- * @md: descriptor for the bad block table mirror
- * @chipsel: selector for a specific chip, -1 for all
- *
- * (Re)write the bad block table.
- */
-static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
- struct nand_bbt_descr *td, struct nand_bbt_descr *md,
- int chipsel)
-{
- struct nand_chip *this = mtd->priv;
- struct erase_info einfo;
- int i, j, res, chip = 0;
- int bits, startblock, dir, page, offs, numblocks, sft, sftmsk;
- int nrchips, bbtoffs, pageoffs, ooboffs;
- uint8_t msk[4];
- uint8_t rcode = td->reserved_block_code;
- size_t retlen, len = 0;
- loff_t to;
- struct mtd_oob_ops ops;
-
- ops.ooblen = mtd->oobsize;
- ops.ooboffs = 0;
- ops.datbuf = NULL;
- ops.mode = MTD_OPS_PLACE_OOB;
-
- if (!rcode)
- rcode = 0xff;
- /* Write bad block table per chip rather than per device? */
- if (td->options & NAND_BBT_PERCHIP) {
- numblocks = (int)(this->chipsize >> this->bbt_erase_shift);
- /* Full device write or specific chip? */
- if (chipsel == -1) {
- nrchips = this->numchips;
- } else {
- nrchips = chipsel + 1;
- chip = chipsel;
- }
- } else {
- numblocks = (int)(mtd->size >> this->bbt_erase_shift);
- nrchips = 1;
- }
-
- /* Loop through the chips */
- for (; chip < nrchips; chip++) {
- /*
- * There was already a version of the table, reuse the page
- * This applies for absolute placement too, as we have the
- * page nr. in td->pages.
- */
- if (td->pages[chip] != -1) {
- page = td->pages[chip];
- goto write;
- }
-
- /*
- * Automatic placement of the bad block table. Search direction
- * top -> down?
- */
- if (td->options & NAND_BBT_LASTBLOCK) {
- startblock = numblocks * (chip + 1) - 1;
- dir = -1;
- } else {
- startblock = chip * numblocks;
- dir = 1;
- }
-
- for (i = 0; i < td->maxblocks; i++) {
- int block = startblock + dir * i;
- /* Check, if the block is bad */
- switch ((this->bbt[block >> 2] >>
- (2 * (block & 0x03))) & 0x03) {
- case 0x01:
- case 0x03:
- continue;
- }
- page = block <<
- (this->bbt_erase_shift - this->page_shift);
- /* Check, if the block is used by the mirror table */
- if (!md || md->pages[chip] != page)
- goto write;
- }
- pr_err("No space left to write bad block table\n");
- return -ENOSPC;
- write:
-
- /* Set up shift count and masks for the flash table */
- bits = td->options & NAND_BBT_NRBITS_MSK;
- msk[2] = ~rcode;
- switch (bits) {
- case 1: sft = 3; sftmsk = 0x07; msk[0] = 0x00; msk[1] = 0x01;
- msk[3] = 0x01;
- break;
- case 2: sft = 2; sftmsk = 0x06; msk[0] = 0x00; msk[1] = 0x01;
- msk[3] = 0x03;
- break;
- case 4: sft = 1; sftmsk = 0x04; msk[0] = 0x00; msk[1] = 0x0C;
- msk[3] = 0x0f;
- break;
- case 8: sft = 0; sftmsk = 0x00; msk[0] = 0x00; msk[1] = 0x0F;
- msk[3] = 0xff;
- break;
- default: return -EINVAL;
- }
-
- bbtoffs = chip * (numblocks >> 2);
-
- to = ((loff_t)page) << this->page_shift;
-
- /* Must we save the block contents? */
- if (td->options & NAND_BBT_SAVECONTENT) {
- /* Make it block aligned */
- to &= ~((loff_t)((1 << this->bbt_erase_shift) - 1));
- len = 1 << this->bbt_erase_shift;
- res = mtd_read(mtd, to, len, &retlen, buf);
- if (res < 0) {
- if (retlen != len) {
- pr_info("nand_bbt: error reading block "
- "for writing the bad block table\n");
- return res;
- }
- pr_warn("nand_bbt: ECC error while reading "
- "block for writing bad block table\n");
- }
- /* Read oob data */
- ops.ooblen = (len >> this->page_shift) * mtd->oobsize;
- ops.oobbuf = &buf[len];
- res = mtd_read_oob(mtd, to + mtd->writesize, &ops);
- if (res < 0 || ops.oobretlen != ops.ooblen)
- goto outerr;
-
- /* Calc the byte offset in the buffer */
- pageoffs = page - (int)(to >> this->page_shift);
- offs = pageoffs << this->page_shift;
- /* Preset the bbt area with 0xff */
- memset(&buf[offs], 0xff, (size_t)(numblocks >> sft));
- ooboffs = len + (pageoffs * mtd->oobsize);
-
- } else if (td->options & NAND_BBT_NO_OOB) {
- ooboffs = 0;
- offs = td->len;
- /* The version byte */
- if (td->options & NAND_BBT_VERSION)
- offs++;
- /* Calc length */
- len = (size_t)(numblocks >> sft);
- len += offs;
- /* Make it page aligned! */
- len = ALIGN(len, mtd->writesize);
- /* Preset the buffer with 0xff */
- memset(buf, 0xff, len);
- /* Pattern is located at the begin of first page */
- memcpy(buf, td->pattern, td->len);
- } else {
- /* Calc length */
- len = (size_t)(numblocks >> sft);
- /* Make it page aligned! */
- len = ALIGN(len, mtd->writesize);
- /* Preset the buffer with 0xff */
- memset(buf, 0xff, len +
- (len >> this->page_shift)* mtd->oobsize);
- offs = 0;
- ooboffs = len;
- /* Pattern is located in oob area of first page */
- memcpy(&buf[ooboffs + td->offs], td->pattern, td->len);
- }
-
- if (td->options & NAND_BBT_VERSION)
- buf[ooboffs + td->veroffs] = td->version[chip];
-
- /* Walk through the memory table */
- for (i = 0; i < numblocks;) {
- uint8_t dat;
- dat = this->bbt[bbtoffs + (i >> 2)];
- for (j = 0; j < 4; j++, i++) {
- int sftcnt = (i << (3 - sft)) & sftmsk;
- /* Do not store the reserved bbt blocks! */
- buf[offs + (i >> sft)] &=
- ~(msk[dat & 0x03] << sftcnt);
- dat >>= 2;
- }
- }
-
- memset(&einfo, 0, sizeof(einfo));
- einfo.mtd = mtd;
- einfo.addr = to;
- einfo.len = 1 << this->bbt_erase_shift;
- res = nand_erase_nand(mtd, &einfo, 1);
- if (res < 0)
- goto outerr;
-
- res = scan_write_bbt(mtd, to, len, buf,
- td->options & NAND_BBT_NO_OOB ? NULL :
- &buf[len]);
- if (res < 0)
- goto outerr;
-
- pr_info("Bad block table written to 0x%012llx, version 0x%02X\n",
- (unsigned long long)to, td->version[chip]);
-
- /* Mark it as used */
- td->pages[chip] = page;
- }
- return 0;
-
- outerr:
- pr_warn("nand_bbt: error while writing bad block table %d\n", res);
- return res;
-}
-
-/**
- * nand_memory_bbt - [GENERIC] create a memory based bad block table
- * @mtd: MTD device structure
- * @bd: descriptor for the good/bad block search pattern
- *
- * The function creates a memory based bbt by scanning the device for
- * manufacturer / software marked good / bad blocks.
- */
-static inline int nand_memory_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
-{
- struct nand_chip *this = mtd->priv;
-
- bd->options &= ~NAND_BBT_SCANEMPTY;
- return create_bbt(mtd, this->buffers->databuf, bd, -1);
-}
-
-/**
- * check_create - [GENERIC] create and write bbt(s) if necessary
- * @mtd: MTD device structure
- * @buf: temporary buffer
- * @bd: descriptor for the good/bad block search pattern
- *
- * The function checks the results of the previous call to read_bbt and creates
- * / updates the bbt(s) if necessary. Creation is necessary if no bbt was found
- * for the chip/device. Update is necessary if one of the tables is missing or
- * the version nr. of one table is less than the other.
- */
-static int check_create(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *bd)
-{
- int i, chips, writeops, create, chipsel, res, res2;
- struct nand_chip *this = mtd->priv;
- struct nand_bbt_descr *td = this->bbt_td;
- struct nand_bbt_descr *md = this->bbt_md;
- struct nand_bbt_descr *rd, *rd2;
-
- /* Do we have a bbt per chip? */
- if (td->options & NAND_BBT_PERCHIP)
- chips = this->numchips;
- else
- chips = 1;
-
- for (i = 0; i < chips; i++) {
- writeops = 0;
- create = 0;
- rd = NULL;
- rd2 = NULL;
- res = res2 = 0;
- /* Per chip or per device? */
- chipsel = (td->options & NAND_BBT_PERCHIP) ? i : -1;
- /* Mirrored table available? */
- if (md) {
- if (td->pages[i] == -1 && md->pages[i] == -1) {
- create = 1;
- writeops = 0x03;
- } else if (td->pages[i] == -1) {
- rd = md;
- writeops = 0x01;
- } else if (md->pages[i] == -1) {
- rd = td;
- writeops = 0x02;
- } else if (td->version[i] == md->version[i]) {
- rd = td;
- if (!(td->options & NAND_BBT_VERSION))
- rd2 = md;
- } else if (((int8_t)(td->version[i] - md->version[i])) > 0) {
- rd = td;
- writeops = 0x02;
- } else {
- rd = md;
- writeops = 0x01;
- }
- } else {
- if (td->pages[i] == -1) {
- create = 1;
- writeops = 0x01;
- } else {
- rd = td;
- }
- }
-
- if (create) {
- /* Create the bad block table by scanning the device? */
- if (!(td->options & NAND_BBT_CREATE))
- continue;
-
- /* Create the table in memory by scanning the chip(s) */
- if (!(this->bbt_options & NAND_BBT_CREATE_EMPTY))
- create_bbt(mtd, buf, bd, chipsel);
-
- td->version[i] = 1;
- if (md)
- md->version[i] = 1;
- }
-
- /* Read back first? */
- if (rd) {
- res = read_abs_bbt(mtd, buf, rd, chipsel);
- if (mtd_is_eccerr(res)) {
- /* Mark table as invalid */
- rd->pages[i] = -1;
- rd->version[i] = 0;
- i--;
- continue;
- }
- }
- /* If they weren't versioned, read both */
- if (rd2) {
- res2 = read_abs_bbt(mtd, buf, rd2, chipsel);
- if (mtd_is_eccerr(res2)) {
- /* Mark table as invalid */
- rd2->pages[i] = -1;
- rd2->version[i] = 0;
- i--;
- continue;
- }
- }
-
- /* Scrub the flash table(s)? */
- if (mtd_is_bitflip(res) || mtd_is_bitflip(res2))
- writeops = 0x03;
-
- /* Update version numbers before writing */
- if (md) {
- td->version[i] = max(td->version[i], md->version[i]);
- md->version[i] = td->version[i];
- }
-
- /* Write the bad block table to the device? */
- if ((writeops & 0x01) && (td->options & NAND_BBT_WRITE)) {
- res = write_bbt(mtd, buf, td, md, chipsel);
- if (res < 0)
- return res;
- }
-
- /* Write the mirror bad block table to the device? */
- if ((writeops & 0x02) && md && (md->options & NAND_BBT_WRITE)) {
- res = write_bbt(mtd, buf, md, td, chipsel);
- if (res < 0)
- return res;
- }
- }
- return 0;
-}
-
-/**
- * mark_bbt_regions - [GENERIC] mark the bad block table regions
- * @mtd: MTD device structure
- * @td: bad block table descriptor
- *
- * The bad block table regions are marked as "bad" to prevent accidental
- * erasures / writes. The regions are identified by the mark 0x02.
- */
-static void mark_bbt_region(struct mtd_info *mtd, struct nand_bbt_descr *td)
-{
- struct nand_chip *this = mtd->priv;
- int i, j, chips, block, nrblocks, update;
- uint8_t oldval, newval;
-
- /* Do we have a bbt per chip? */
- if (td->options & NAND_BBT_PERCHIP) {
- chips = this->numchips;
- nrblocks = (int)(this->chipsize >> this->bbt_erase_shift);
- } else {
- chips = 1;
- nrblocks = (int)(mtd->size >> this->bbt_erase_shift);
- }
-
- for (i = 0; i < chips; i++) {
- if ((td->options & NAND_BBT_ABSPAGE) ||
- !(td->options & NAND_BBT_WRITE)) {
- if (td->pages[i] == -1)
- continue;
- block = td->pages[i] >> (this->bbt_erase_shift - this->page_shift);
- block <<= 1;
- oldval = this->bbt[(block >> 3)];
- newval = oldval | (0x2 << (block & 0x06));
- this->bbt[(block >> 3)] = newval;
- if ((oldval != newval) && td->reserved_block_code)
- nand_update_bbt(mtd, (loff_t)block << (this->bbt_erase_shift - 1));
- continue;
- }
- update = 0;
- if (td->options & NAND_BBT_LASTBLOCK)
- block = ((i + 1) * nrblocks) - td->maxblocks;
- else
- block = i * nrblocks;
- block <<= 1;
- for (j = 0; j < td->maxblocks; j++) {
- oldval = this->bbt[(block >> 3)];
- newval = oldval | (0x2 << (block & 0x06));
- this->bbt[(block >> 3)] = newval;
- if (oldval != newval)
- update = 1;
- block += 2;
- }
- /*
- * If we want reserved blocks to be recorded to flash, and some
- * new ones have been marked, then we need to update the stored
- * bbts. This should only happen once.
- */
- if (update && td->reserved_block_code)
- nand_update_bbt(mtd, (loff_t)(block - 2) << (this->bbt_erase_shift - 1));
- }
-}
-
-/**
- * verify_bbt_descr - verify the bad block description
- * @mtd: MTD device structure
- * @bd: the table to verify
- *
- * This functions performs a few sanity checks on the bad block description
- * table.
- */
-static void verify_bbt_descr(struct mtd_info *mtd, struct nand_bbt_descr *bd)
-{
- struct nand_chip *this = mtd->priv;
- u32 pattern_len;
- u32 bits;
- u32 table_size;
-
- if (!bd)
- return;
-
- pattern_len = bd->len;
- bits = bd->options & NAND_BBT_NRBITS_MSK;
-
- BUG_ON((this->bbt_options & NAND_BBT_NO_OOB) &&
- !(this->bbt_options & NAND_BBT_USE_FLASH));
- BUG_ON(!bits);
-
- if (bd->options & NAND_BBT_VERSION)
- pattern_len++;
-
- if (bd->options & NAND_BBT_NO_OOB) {
- BUG_ON(!(this->bbt_options & NAND_BBT_USE_FLASH));
- BUG_ON(!(this->bbt_options & NAND_BBT_NO_OOB));
- BUG_ON(bd->offs);
- if (bd->options & NAND_BBT_VERSION)
- BUG_ON(bd->veroffs != bd->len);
- BUG_ON(bd->options & NAND_BBT_SAVECONTENT);
- }
-
- if (bd->options & NAND_BBT_PERCHIP)
- table_size = this->chipsize >> this->bbt_erase_shift;
- else
- table_size = mtd->size >> this->bbt_erase_shift;
- table_size >>= 3;
- table_size *= bits;
- if (bd->options & NAND_BBT_NO_OOB)
- table_size += pattern_len;
- BUG_ON(table_size > (1 << this->bbt_erase_shift));
-}
-
-/**
- * nand_scan_bbt - [NAND Interface] scan, find, read and maybe create bad block table(s)
- * @mtd: MTD device structure
- * @bd: descriptor for the good/bad block search pattern
- *
- * The function checks, if a bad block table(s) is/are already available. If
- * not it scans the device for manufacturer marked good / bad blocks and writes
- * the bad block table(s) to the selected place.
- *
- * The bad block table memory is allocated here. It must be freed by calling
- * the nand_free_bbt function.
- */
-int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
-{
- struct nand_chip *this = mtd->priv;
- int len, res = 0;
- uint8_t *buf;
- struct nand_bbt_descr *td = this->bbt_td;
- struct nand_bbt_descr *md = this->bbt_md;
-
- len = mtd->size >> (this->bbt_erase_shift + 2);
- /*
- * Allocate memory (2bit per block) and clear the memory bad block
- * table.
- */
- this->bbt = kzalloc(len, GFP_KERNEL);
- if (!this->bbt)
- return -ENOMEM;
-
- /*
- * If no primary table decriptor is given, scan the device to build a
- * memory based bad block table.
- */
- if (!td) {
- if ((res = nand_memory_bbt(mtd, bd))) {
- pr_err("nand_bbt: can't scan flash and build the RAM-based BBT\n");
- kfree(this->bbt);
- this->bbt = NULL;
- }
- return res;
- }
- verify_bbt_descr(mtd, td);
- verify_bbt_descr(mtd, md);
-
- /* Allocate a temporary buffer for one eraseblock incl. oob */
- len = (1 << this->bbt_erase_shift);
- len += (len >> this->page_shift) * mtd->oobsize;
- buf = vmalloc(len);
- if (!buf) {
- kfree(this->bbt);
- this->bbt = NULL;
- return -ENOMEM;
- }
-
- /* Is the bbt at a given page? */
- if (td->options & NAND_BBT_ABSPAGE) {
- read_abs_bbts(mtd, buf, td, md);
- } else {
- /* Search the bad block table using a pattern in oob */
- search_read_bbts(mtd, buf, td, md);
- }
-
- res = check_create(mtd, buf, bd);
-
- /* Prevent the bbt regions from erasing / writing */
- mark_bbt_region(mtd, td);
- if (md)
- mark_bbt_region(mtd, md);
-
- vfree(buf);
- return res;
-}
-
-/**
- * nand_update_bbt - [NAND Interface] update bad block table(s)
- * @mtd: MTD device structure
- * @offs: the offset of the newly marked block
- *
- * The function updates the bad block table(s).
- */
-int nand_update_bbt(struct mtd_info *mtd, loff_t offs)
-{
- struct nand_chip *this = mtd->priv;
- int len, res = 0;
- int chip, chipsel;
- uint8_t *buf;
- struct nand_bbt_descr *td = this->bbt_td;
- struct nand_bbt_descr *md = this->bbt_md;
-
- if (!this->bbt || !td)
- return -EINVAL;
-
- /* Allocate a temporary buffer for one eraseblock incl. oob */
- len = (1 << this->bbt_erase_shift);
- len += (len >> this->page_shift) * mtd->oobsize;
- buf = kmalloc(len, GFP_KERNEL);
- if (!buf)
- return -ENOMEM;
-
- /* Do we have a bbt per chip? */
- if (td->options & NAND_BBT_PERCHIP) {
- chip = (int)(offs >> this->chip_shift);
- chipsel = chip;
- } else {
- chip = 0;
- chipsel = -1;
- }
-
- td->version[chip]++;
- if (md)
- md->version[chip]++;
-
- /* Write the bad block table to the device? */
- if (td->options & NAND_BBT_WRITE) {
- res = write_bbt(mtd, buf, td, md, chipsel);
- if (res < 0)
- goto out;
- }
- /* Write the mirror bad block table to the device? */
- if (md && (md->options & NAND_BBT_WRITE)) {
- res = write_bbt(mtd, buf, md, td, chipsel);
- }
-
- out:
- kfree(buf);
- return res;
-}
-
-/*
- * Define some generic bad / good block scan pattern which are used
- * while scanning a device for factory marked good / bad blocks.
- */
-static uint8_t scan_ff_pattern[] = { 0xff, 0xff };
-
-static uint8_t scan_agand_pattern[] = { 0x1C, 0x71, 0xC7, 0x1C, 0x71, 0xC7 };
-
-static struct nand_bbt_descr agand_flashbased = {
- .options = NAND_BBT_SCANEMPTY | NAND_BBT_SCANALLPAGES,
- .offs = 0x20,
- .len = 6,
- .pattern = scan_agand_pattern
-};
-
-/* Generic flash bbt descriptors */
-static uint8_t bbt_pattern[] = {'B', 'b', 't', '0' };
-static uint8_t mirror_pattern[] = {'1', 't', 'b', 'B' };
-
-static struct nand_bbt_descr bbt_main_descr = {
- .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
- | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
- .offs = 8,
- .len = 4,
- .veroffs = 12,
- .maxblocks = NAND_BBT_SCAN_MAXBLOCKS,
- .pattern = bbt_pattern
-};
-
-static struct nand_bbt_descr bbt_mirror_descr = {
- .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
- | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
- .offs = 8,
- .len = 4,
- .veroffs = 12,
- .maxblocks = NAND_BBT_SCAN_MAXBLOCKS,
- .pattern = mirror_pattern
-};
-
-static struct nand_bbt_descr bbt_main_no_oob_descr = {
- .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
- | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP
- | NAND_BBT_NO_OOB,
- .len = 4,
- .veroffs = 4,
- .maxblocks = NAND_BBT_SCAN_MAXBLOCKS,
- .pattern = bbt_pattern
-};
-
-static struct nand_bbt_descr bbt_mirror_no_oob_descr = {
- .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
- | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP
- | NAND_BBT_NO_OOB,
- .len = 4,
- .veroffs = 4,
- .maxblocks = NAND_BBT_SCAN_MAXBLOCKS,
- .pattern = mirror_pattern
-};
-
-#define BADBLOCK_SCAN_MASK (~NAND_BBT_NO_OOB)
-/**
- * nand_create_badblock_pattern - [INTERN] Creates a BBT descriptor structure
- * @this: NAND chip to create descriptor for
- *
- * This function allocates and initializes a nand_bbt_descr for BBM detection
- * based on the properties of @this. The new descriptor is stored in
- * this->badblock_pattern. Thus, this->badblock_pattern should be NULL when
- * passed to this function.
- */
-static int nand_create_badblock_pattern(struct nand_chip *this)
-{
- struct nand_bbt_descr *bd;
- if (this->badblock_pattern) {
- pr_warn("Bad block pattern already allocated; not replacing\n");
- return -EINVAL;
- }
- bd = kzalloc(sizeof(*bd), GFP_KERNEL);
- if (!bd)
- return -ENOMEM;
- bd->options = this->bbt_options & BADBLOCK_SCAN_MASK;
- bd->offs = this->badblockpos;
- bd->len = (this->options & NAND_BUSWIDTH_16) ? 2 : 1;
- bd->pattern = scan_ff_pattern;
- bd->options |= NAND_BBT_DYNAMICSTRUCT;
- this->badblock_pattern = bd;
- return 0;
-}
-
-/**
- * nand_default_bbt - [NAND Interface] Select a default bad block table for the device
- * @mtd: MTD device structure
- *
- * This function selects the default bad block table support for the device and
- * calls the nand_scan_bbt function.
- */
-int nand_default_bbt(struct mtd_info *mtd)
-{
- struct nand_chip *this = mtd->priv;
-
- /*
- * Default for AG-AND. We must use a flash based bad block table as the
- * devices have factory marked _good_ blocks. Erasing those blocks
- * leads to loss of the good / bad information, so we _must_ store this
- * information in a good / bad table during startup.
- */
- if (this->options & NAND_IS_AND) {
- /* Use the default pattern descriptors */
- if (!this->bbt_td) {
- this->bbt_td = &bbt_main_descr;
- this->bbt_md = &bbt_mirror_descr;
- }
- this->bbt_options |= NAND_BBT_USE_FLASH;
- return nand_scan_bbt(mtd, &agand_flashbased);
- }
-
- /* Is a flash based bad block table requested? */
- if (this->bbt_options & NAND_BBT_USE_FLASH) {
- /* Use the default pattern descriptors */
- if (!this->bbt_td) {
- if (this->bbt_options & NAND_BBT_NO_OOB) {
- this->bbt_td = &bbt_main_no_oob_descr;
- this->bbt_md = &bbt_mirror_no_oob_descr;
- } else {
- this->bbt_td = &bbt_main_descr;
- this->bbt_md = &bbt_mirror_descr;
- }
- }
- } else {
- this->bbt_td = NULL;
- this->bbt_md = NULL;
- }
-
- if (!this->badblock_pattern)
- nand_create_badblock_pattern(this);
-
- return nand_scan_bbt(mtd, this->badblock_pattern);
-}
-
-/**
- * nand_isbad_bbt - [NAND Interface] Check if a block is bad
- * @mtd: MTD device structure
- * @offs: offset in the device
- * @allowbbt: allow access to bad block table region
- */
-int nand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt)
-{
- struct nand_chip *this = mtd->priv;
- int block;
- uint8_t res;
-
- /* Get block number * 2 */
- block = (int)(offs >> (this->bbt_erase_shift - 1));
- res = (this->bbt[block >> 3] >> (block & 0x06)) & 0x03;
-
- MTDDEBUG(MTD_DEBUG_LEVEL2, "nand_isbad_bbt(): bbt info for offs 0x%08x: (block %d) 0x%02x\n",
- (unsigned int)offs, block >> 1, res);
-
- switch ((int)res) {
- case 0x00:
- return 0;
- case 0x01:
- return 1;
- case 0x02:
- return allowbbt ? 0 : 1;
- }
- return 1;
-}
diff --git a/qemu/roms/u-boot/drivers/mtd/nand/nand_bch.c b/qemu/roms/u-boot/drivers/mtd/nand/nand_bch.c
deleted file mode 100644
index 35d2140da..000000000
--- a/qemu/roms/u-boot/drivers/mtd/nand/nand_bch.c
+++ /dev/null
@@ -1,224 +0,0 @@
-/*
- * This file provides ECC correction for more than 1 bit per block of data,
- * using binary BCH codes. It relies on the generic BCH library lib/bch.c.
- *
- * Copyright © 2011 Ivan Djelic <ivan.djelic@parrot.com>
- *
- * SPDX-License-Identifier: GPL-2.0+
- */
-
-#include <common.h>
-/*#include <asm/io.h>*/
-#include <linux/types.h>
-
-#include <linux/bitops.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
-#include <linux/mtd/nand_bch.h>
-#include <linux/bch.h>
-#include <malloc.h>
-
-/**
- * struct nand_bch_control - private NAND BCH control structure
- * @bch: BCH control structure
- * @ecclayout: private ecc layout for this BCH configuration
- * @errloc: error location array
- * @eccmask: XOR ecc mask, allows erased pages to be decoded as valid
- */
-struct nand_bch_control {
- struct bch_control *bch;
- struct nand_ecclayout ecclayout;
- unsigned int *errloc;
- unsigned char *eccmask;
-};
-
-/**
- * nand_bch_calculate_ecc - [NAND Interface] Calculate ECC for data block
- * @mtd: MTD block structure
- * @buf: input buffer with raw data
- * @code: output buffer with ECC
- */
-int nand_bch_calculate_ecc(struct mtd_info *mtd, const unsigned char *buf,
- unsigned char *code)
-{
- const struct nand_chip *chip = mtd->priv;
- struct nand_bch_control *nbc = chip->ecc.priv;
- unsigned int i;
-
- memset(code, 0, chip->ecc.bytes);
- encode_bch(nbc->bch, buf, chip->ecc.size, code);
-
- /* apply mask so that an erased page is a valid codeword */
- for (i = 0; i < chip->ecc.bytes; i++)
- code[i] ^= nbc->eccmask[i];
-
- return 0;
-}
-
-/**
- * nand_bch_correct_data - [NAND Interface] Detect and correct bit error(s)
- * @mtd: MTD block structure
- * @buf: raw data read from the chip
- * @read_ecc: ECC from the chip
- * @calc_ecc: the ECC calculated from raw data
- *
- * Detect and correct bit errors for a data byte block
- */
-int nand_bch_correct_data(struct mtd_info *mtd, unsigned char *buf,
- unsigned char *read_ecc, unsigned char *calc_ecc)
-{
- const struct nand_chip *chip = mtd->priv;
- struct nand_bch_control *nbc = chip->ecc.priv;
- unsigned int *errloc = nbc->errloc;
- int i, count;
-
- count = decode_bch(nbc->bch, NULL, chip->ecc.size, read_ecc, calc_ecc,
- NULL, errloc);
- if (count > 0) {
- for (i = 0; i < count; i++) {
- if (errloc[i] < (chip->ecc.size*8))
- /* error is located in data, correct it */
- buf[errloc[i] >> 3] ^= (1 << (errloc[i] & 7));
- /* else error in ecc, no action needed */
-
- MTDDEBUG(MTD_DEBUG_LEVEL0, "%s: corrected bitflip %u\n",
- __func__, errloc[i]);
- }
- } else if (count < 0) {
- printk(KERN_ERR "ecc unrecoverable error\n");
- count = -1;
- }
- return count;
-}
-
-/**
- * nand_bch_init - [NAND Interface] Initialize NAND BCH error correction
- * @mtd: MTD block structure
- * @eccsize: ecc block size in bytes
- * @eccbytes: ecc length in bytes
- * @ecclayout: output default layout
- *
- * Returns:
- * a pointer to a new NAND BCH control structure, or NULL upon failure
- *
- * Initialize NAND BCH error correction. Parameters @eccsize and @eccbytes
- * are used to compute BCH parameters m (Galois field order) and t (error
- * correction capability). @eccbytes should be equal to the number of bytes
- * required to store m*t bits, where m is such that 2^m-1 > @eccsize*8.
- *
- * Example: to configure 4 bit correction per 512 bytes, you should pass
- * @eccsize = 512 (thus, m=13 is the smallest integer such that 2^m-1 > 512*8)
- * @eccbytes = 7 (7 bytes are required to store m*t = 13*4 = 52 bits)
- */
-struct nand_bch_control *
-nand_bch_init(struct mtd_info *mtd, unsigned int eccsize, unsigned int eccbytes,
- struct nand_ecclayout **ecclayout)
-{
- unsigned int m, t, eccsteps, i;
- struct nand_ecclayout *layout;
- struct nand_bch_control *nbc = NULL;
- unsigned char *erased_page;
-
- if (!eccsize || !eccbytes) {
- printk(KERN_WARNING "ecc parameters not supplied\n");
- goto fail;
- }
-
- m = fls(1+8*eccsize);
- t = (eccbytes*8)/m;
-
- nbc = kzalloc(sizeof(*nbc), GFP_KERNEL);
- if (!nbc)
- goto fail;
-
- nbc->bch = init_bch(m, t, 0);
- if (!nbc->bch)
- goto fail;
-
- /* verify that eccbytes has the expected value */
- if (nbc->bch->ecc_bytes != eccbytes) {
- printk(KERN_WARNING "invalid eccbytes %u, should be %u\n",
- eccbytes, nbc->bch->ecc_bytes);
- goto fail;
- }
-
- eccsteps = mtd->writesize/eccsize;
-
- /* if no ecc placement scheme was provided, build one */
- if (!*ecclayout) {
-
- /* handle large page devices only */
- if (mtd->oobsize < 64) {
- printk(KERN_WARNING "must provide an oob scheme for "
- "oobsize %d\n", mtd->oobsize);
- goto fail;
- }
-
- layout = &nbc->ecclayout;
- layout->eccbytes = eccsteps*eccbytes;
-
- /* reserve 2 bytes for bad block marker */
- if (layout->eccbytes+2 > mtd->oobsize) {
- printk(KERN_WARNING "no suitable oob scheme available "
- "for oobsize %d eccbytes %u\n", mtd->oobsize,
- eccbytes);
- goto fail;
- }
- /* put ecc bytes at oob tail */
- for (i = 0; i < layout->eccbytes; i++)
- layout->eccpos[i] = mtd->oobsize-layout->eccbytes+i;
-
- layout->oobfree[0].offset = 2;
- layout->oobfree[0].length = mtd->oobsize-2-layout->eccbytes;
-
- *ecclayout = layout;
- }
-
- /* sanity checks */
- if (8*(eccsize+eccbytes) >= (1 << m)) {
- printk(KERN_WARNING "eccsize %u is too large\n", eccsize);
- goto fail;
- }
- if ((*ecclayout)->eccbytes != (eccsteps*eccbytes)) {
- printk(KERN_WARNING "invalid ecc layout\n");
- goto fail;
- }
-
- nbc->eccmask = kmalloc(eccbytes, GFP_KERNEL);
- nbc->errloc = kmalloc(t*sizeof(*nbc->errloc), GFP_KERNEL);
- if (!nbc->eccmask || !nbc->errloc)
- goto fail;
- /*
- * compute and store the inverted ecc of an erased ecc block
- */
- erased_page = kmalloc(eccsize, GFP_KERNEL);
- if (!erased_page)
- goto fail;
-
- memset(erased_page, 0xff, eccsize);
- memset(nbc->eccmask, 0, eccbytes);
- encode_bch(nbc->bch, erased_page, eccsize, nbc->eccmask);
- kfree(erased_page);
-
- for (i = 0; i < eccbytes; i++)
- nbc->eccmask[i] ^= 0xff;
-
- return nbc;
-fail:
- nand_bch_free(nbc);
- return NULL;
-}
-
-/**
- * nand_bch_free - [NAND Interface] Release NAND BCH ECC resources
- * @nbc: NAND BCH control structure
- */
-void nand_bch_free(struct nand_bch_control *nbc)
-{
- if (nbc) {
- free_bch(nbc->bch);
- kfree(nbc->errloc);
- kfree(nbc->eccmask);
- kfree(nbc);
- }
-}
diff --git a/qemu/roms/u-boot/drivers/mtd/nand/nand_ecc.c b/qemu/roms/u-boot/drivers/mtd/nand/nand_ecc.c
deleted file mode 100644
index 083e0e99e..000000000
--- a/qemu/roms/u-boot/drivers/mtd/nand/nand_ecc.c
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
- * This file contains an ECC algorithm from Toshiba that detects and
- * corrects 1 bit errors in a 256 byte block of data.
- *
- * drivers/mtd/nand/nand_ecc.c
- *
- * Copyright (C) 2000-2004 Steven J. Hill (sjhill@realitydiluted.com)
- * Toshiba America Electronics Components, Inc.
- *
- * Copyright (C) 2006 Thomas Gleixner <tglx@linutronix.de>
- *
- * SPDX-License-Identifier: GPL-2.0+
- *
- * As a special exception, if other files instantiate templates or use
- * macros or inline functions from these files, or you compile these
- * files and link them with other works to produce a work based on these
- * files, these files do not by themselves cause the resulting work to be
- * covered by the GNU General Public License. However the source code for
- * these files must still be made available in accordance with section (3)
- * of the GNU General Public License.
- *
- * This exception does not invalidate any other reasons why a work based on
- * this file might be covered by the GNU General Public License.
- */
-
-#include <common.h>
-
-#include <asm/errno.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/nand_ecc.h>
-
-/* The PPC4xx NDFC uses Smart Media (SMC) bytes order */
-#ifdef CONFIG_NAND_NDFC
-#define CONFIG_MTD_NAND_ECC_SMC
-#endif
-
-/*
- * NAND-SPL has no sofware ECC for now, so don't include nand_calculate_ecc(),
- * only nand_correct_data() is needed
- */
-
-#if !defined(CONFIG_NAND_SPL) || defined(CONFIG_SPL_NAND_SOFTECC)
-/*
- * Pre-calculated 256-way 1 byte column parity
- */
-static const u_char nand_ecc_precalc_table[] = {
- 0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a, 0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00,
- 0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f, 0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65,
- 0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c, 0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66,
- 0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59, 0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03,
- 0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33, 0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69,
- 0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56, 0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c,
- 0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55, 0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f,
- 0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30, 0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a,
- 0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30, 0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a,
- 0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55, 0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f,
- 0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56, 0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c,
- 0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33, 0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69,
- 0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59, 0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03,
- 0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c, 0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66,
- 0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f, 0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65,
- 0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a, 0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00
-};
-
-/**
- * nand_calculate_ecc - [NAND Interface] Calculate 3-byte ECC for 256-byte block
- * @mtd: MTD block structure
- * @dat: raw data
- * @ecc_code: buffer for ECC
- */
-int nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
- u_char *ecc_code)
-{
- uint8_t idx, reg1, reg2, reg3, tmp1, tmp2;
- int i;
-
- /* Initialize variables */
- reg1 = reg2 = reg3 = 0;
-
- /* Build up column parity */
- for(i = 0; i < 256; i++) {
- /* Get CP0 - CP5 from table */
- idx = nand_ecc_precalc_table[*dat++];
- reg1 ^= (idx & 0x3f);
-
- /* All bit XOR = 1 ? */
- if (idx & 0x40) {
- reg3 ^= (uint8_t) i;
- reg2 ^= ~((uint8_t) i);
- }
- }
-
- /* Create non-inverted ECC code from line parity */
- tmp1 = (reg3 & 0x80) >> 0; /* B7 -> B7 */
- tmp1 |= (reg2 & 0x80) >> 1; /* B7 -> B6 */
- tmp1 |= (reg3 & 0x40) >> 1; /* B6 -> B5 */
- tmp1 |= (reg2 & 0x40) >> 2; /* B6 -> B4 */
- tmp1 |= (reg3 & 0x20) >> 2; /* B5 -> B3 */
- tmp1 |= (reg2 & 0x20) >> 3; /* B5 -> B2 */
- tmp1 |= (reg3 & 0x10) >> 3; /* B4 -> B1 */
- tmp1 |= (reg2 & 0x10) >> 4; /* B4 -> B0 */
-
- tmp2 = (reg3 & 0x08) << 4; /* B3 -> B7 */
- tmp2 |= (reg2 & 0x08) << 3; /* B3 -> B6 */
- tmp2 |= (reg3 & 0x04) << 3; /* B2 -> B5 */
- tmp2 |= (reg2 & 0x04) << 2; /* B2 -> B4 */
- tmp2 |= (reg3 & 0x02) << 2; /* B1 -> B3 */
- tmp2 |= (reg2 & 0x02) << 1; /* B1 -> B2 */
- tmp2 |= (reg3 & 0x01) << 1; /* B0 -> B1 */
- tmp2 |= (reg2 & 0x01) << 0; /* B7 -> B0 */
-
- /* Calculate final ECC code */
-#ifdef CONFIG_MTD_NAND_ECC_SMC
- ecc_code[0] = ~tmp2;
- ecc_code[1] = ~tmp1;
-#else
- ecc_code[0] = ~tmp1;
- ecc_code[1] = ~tmp2;
-#endif
- ecc_code[2] = ((~reg1) << 2) | 0x03;
-
- return 0;
-}
-#endif /* CONFIG_NAND_SPL */
-
-static inline int countbits(uint32_t byte)
-{
- int res = 0;
-
- for (;byte; byte >>= 1)
- res += byte & 0x01;
- return res;
-}
-
-/**
- * nand_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 nand_correct_data(struct mtd_info *mtd, u_char *dat,
- u_char *read_ecc, u_char *calc_ecc)
-{
- uint8_t s0, s1, s2;
-
-#ifdef CONFIG_MTD_NAND_ECC_SMC
- s0 = calc_ecc[0] ^ read_ecc[0];
- s1 = calc_ecc[1] ^ read_ecc[1];
- s2 = calc_ecc[2] ^ read_ecc[2];
-#else
- s1 = calc_ecc[0] ^ read_ecc[0];
- s0 = calc_ecc[1] ^ read_ecc[1];
- s2 = calc_ecc[2] ^ read_ecc[2];
-#endif
- if ((s0 | s1 | s2) == 0)
- return 0;
-
- /* Check for a single bit error */
- if( ((s0 ^ (s0 >> 1)) & 0x55) == 0x55 &&
- ((s1 ^ (s1 >> 1)) & 0x55) == 0x55 &&
- ((s2 ^ (s2 >> 1)) & 0x54) == 0x54) {
-
- uint32_t byteoffs, bitnum;
-
- byteoffs = (s1 << 0) & 0x80;
- byteoffs |= (s1 << 1) & 0x40;
- byteoffs |= (s1 << 2) & 0x20;
- byteoffs |= (s1 << 3) & 0x10;
-
- byteoffs |= (s0 >> 4) & 0x08;
- byteoffs |= (s0 >> 3) & 0x04;
- byteoffs |= (s0 >> 2) & 0x02;
- byteoffs |= (s0 >> 1) & 0x01;
-
- bitnum = (s2 >> 5) & 0x04;
- bitnum |= (s2 >> 4) & 0x02;
- bitnum |= (s2 >> 3) & 0x01;
-
- dat[byteoffs] ^= (1 << bitnum);
-
- return 1;
- }
-
- if(countbits(s0 | ((uint32_t)s1 << 8) | ((uint32_t)s2 <<16)) == 1)
- return 1;
-
- return -EBADMSG;
-}
diff --git a/qemu/roms/u-boot/drivers/mtd/nand/nand_ids.c b/qemu/roms/u-boot/drivers/mtd/nand/nand_ids.c
deleted file mode 100644
index f3f0cb676..000000000
--- a/qemu/roms/u-boot/drivers/mtd/nand/nand_ids.c
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * drivers/mtd/nandids.c
- *
- * Copyright (C) 2002 Thomas Gleixner (tglx@linutronix.de)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- */
-
-#include <common.h>
-#include <linux/mtd/nand.h>
-/*
-* Chip ID list
-*
-* Name. ID code, pagesize, chipsize in MegaByte, eraseblock size,
-* options
-*
-* Pagesize; 0, 256, 512
-* 0 get this information from the extended chip ID
-+ 256 256 Byte page size
-* 512 512 Byte page size
-*/
-const struct nand_flash_dev nand_flash_ids[] = {
-
-#ifdef CONFIG_MTD_NAND_MUSEUM_IDS
- {"NAND 1MiB 5V 8-bit", 0x6e, 256, 1, 0x1000, 0},
- {"NAND 2MiB 5V 8-bit", 0x64, 256, 2, 0x1000, 0},
- {"NAND 4MiB 5V 8-bit", 0x6b, 512, 4, 0x2000, 0},
- {"NAND 1MiB 3,3V 8-bit", 0xe8, 256, 1, 0x1000, 0},
- {"NAND 1MiB 3,3V 8-bit", 0xec, 256, 1, 0x1000, 0},
- {"NAND 2MiB 3,3V 8-bit", 0xea, 256, 2, 0x1000, 0},
- {"NAND 4MiB 3,3V 8-bit", 0xd5, 512, 4, 0x2000, 0},
- {"NAND 4MiB 3,3V 8-bit", 0xe3, 512, 4, 0x2000, 0},
- {"NAND 4MiB 3,3V 8-bit", 0xe5, 512, 4, 0x2000, 0},
- {"NAND 8MiB 3,3V 8-bit", 0xd6, 512, 8, 0x2000, 0},
-
- {"NAND 8MiB 1,8V 8-bit", 0x39, 512, 8, 0x2000, 0},
- {"NAND 8MiB 3,3V 8-bit", 0xe6, 512, 8, 0x2000, 0},
- {"NAND 8MiB 1,8V 16-bit", 0x49, 512, 8, 0x2000, NAND_BUSWIDTH_16},
- {"NAND 8MiB 3,3V 16-bit", 0x59, 512, 8, 0x2000, NAND_BUSWIDTH_16},
-#endif
-
- {"NAND 16MiB 1,8V 8-bit", 0x33, 512, 16, 0x4000, 0},
- {"NAND 16MiB 3,3V 8-bit", 0x73, 512, 16, 0x4000, 0},
- {"NAND 16MiB 1,8V 16-bit", 0x43, 512, 16, 0x4000, NAND_BUSWIDTH_16},
- {"NAND 16MiB 3,3V 16-bit", 0x53, 512, 16, 0x4000, NAND_BUSWIDTH_16},
-
- {"NAND 32MiB 1,8V 8-bit", 0x35, 512, 32, 0x4000, 0},
- {"NAND 32MiB 3,3V 8-bit", 0x75, 512, 32, 0x4000, 0},
- {"NAND 32MiB 1,8V 16-bit", 0x45, 512, 32, 0x4000, NAND_BUSWIDTH_16},
- {"NAND 32MiB 3,3V 16-bit", 0x55, 512, 32, 0x4000, NAND_BUSWIDTH_16},
-
- {"NAND 64MiB 1,8V 8-bit", 0x36, 512, 64, 0x4000, 0},
- {"NAND 64MiB 3,3V 8-bit", 0x76, 512, 64, 0x4000, 0},
- {"NAND 64MiB 1,8V 16-bit", 0x46, 512, 64, 0x4000, NAND_BUSWIDTH_16},
- {"NAND 64MiB 3,3V 16-bit", 0x56, 512, 64, 0x4000, NAND_BUSWIDTH_16},
-
- {"NAND 128MiB 1,8V 8-bit", 0x78, 512, 128, 0x4000, 0},
- {"NAND 128MiB 1,8V 8-bit", 0x39, 512, 128, 0x4000, 0},
- {"NAND 128MiB 3,3V 8-bit", 0x79, 512, 128, 0x4000, 0},
- {"NAND 128MiB 1,8V 16-bit", 0x72, 512, 128, 0x4000, NAND_BUSWIDTH_16},
- {"NAND 128MiB 1,8V 16-bit", 0x49, 512, 128, 0x4000, NAND_BUSWIDTH_16},
- {"NAND 128MiB 3,3V 16-bit", 0x74, 512, 128, 0x4000, NAND_BUSWIDTH_16},
- {"NAND 128MiB 3,3V 16-bit", 0x59, 512, 128, 0x4000, NAND_BUSWIDTH_16},
-
- {"NAND 256MiB 3,3V 8-bit", 0x71, 512, 256, 0x4000, 0},
-
- /*
- * These are the new chips with large page size. The pagesize and the
- * erasesize is determined from the extended id bytes
- */
-#define LP_OPTIONS NAND_SAMSUNG_LP_OPTIONS
-#define LP_OPTIONS16 (LP_OPTIONS | NAND_BUSWIDTH_16)
-
- /* 512 Megabit */
- {"NAND 64MiB 1,8V 8-bit", 0xA2, 0, 64, 0, LP_OPTIONS},
- {"NAND 64MiB 1,8V 8-bit", 0xA0, 0, 64, 0, LP_OPTIONS},
- {"NAND 64MiB 3,3V 8-bit", 0xF2, 0, 64, 0, LP_OPTIONS},
- {"NAND 64MiB 3,3V 8-bit", 0xD0, 0, 64, 0, LP_OPTIONS},
- {"NAND 64MiB 3,3V 8-bit", 0xF0, 0, 64, 0, LP_OPTIONS},
- {"NAND 64MiB 1,8V 16-bit", 0xB2, 0, 64, 0, LP_OPTIONS16},
- {"NAND 64MiB 1,8V 16-bit", 0xB0, 0, 64, 0, LP_OPTIONS16},
- {"NAND 64MiB 3,3V 16-bit", 0xC2, 0, 64, 0, LP_OPTIONS16},
- {"NAND 64MiB 3,3V 16-bit", 0xC0, 0, 64, 0, LP_OPTIONS16},
-
- /* 1 Gigabit */
- {"NAND 128MiB 1,8V 8-bit", 0xA1, 0, 128, 0, LP_OPTIONS},
- {"NAND 128MiB 3,3V 8-bit", 0xF1, 0, 128, 0, LP_OPTIONS},
- {"NAND 128MiB 3,3V 8-bit", 0xD1, 0, 128, 0, LP_OPTIONS},
- {"NAND 128MiB 1,8V 16-bit", 0xB1, 0, 128, 0, LP_OPTIONS16},
- {"NAND 128MiB 3,3V 16-bit", 0xC1, 0, 128, 0, LP_OPTIONS16},
- {"NAND 128MiB 1,8V 16-bit", 0xAD, 0, 128, 0, LP_OPTIONS16},
-
- /* 2 Gigabit */
- {"NAND 256MiB 1,8V 8-bit", 0xAA, 0, 256, 0, LP_OPTIONS},
- {"NAND 256MiB 3,3V 8-bit", 0xDA, 0, 256, 0, LP_OPTIONS},
- {"NAND 256MiB 1,8V 16-bit", 0xBA, 0, 256, 0, LP_OPTIONS16},
- {"NAND 256MiB 3,3V 16-bit", 0xCA, 0, 256, 0, LP_OPTIONS16},
-
- /* 4 Gigabit */
- {"NAND 512MiB 1,8V 8-bit", 0xAC, 0, 512, 0, LP_OPTIONS},
- {"NAND 512MiB 3,3V 8-bit", 0xDC, 0, 512, 0, LP_OPTIONS},
- {"NAND 512MiB 1,8V 16-bit", 0xBC, 0, 512, 0, LP_OPTIONS16},
- {"NAND 512MiB 3,3V 16-bit", 0xCC, 0, 512, 0, LP_OPTIONS16},
-
- /* 8 Gigabit */
- {"NAND 1GiB 1,8V 8-bit", 0xA3, 0, 1024, 0, LP_OPTIONS},
- {"NAND 1GiB 3,3V 8-bit", 0xD3, 0, 1024, 0, LP_OPTIONS},
- {"NAND 1GiB 1,8V 16-bit", 0xB3, 0, 1024, 0, LP_OPTIONS16},
- {"NAND 1GiB 3,3V 16-bit", 0xC3, 0, 1024, 0, LP_OPTIONS16},
-
- /* 16 Gigabit */
- {"NAND 2GiB 1,8V 8-bit", 0xA5, 0, 2048, 0, LP_OPTIONS},
- {"NAND 2GiB 3,3V 8-bit", 0xD5, 0, 2048, 0, LP_OPTIONS},
- {"NAND 2GiB 1,8V 16-bit", 0xB5, 0, 2048, 0, LP_OPTIONS16},
- {"NAND 2GiB 3,3V 16-bit", 0xC5, 0, 2048, 0, LP_OPTIONS16},
-
- /* 32 Gigabit */
- {"NAND 4GiB 1,8V 8-bit", 0xA7, 0, 4096, 0, LP_OPTIONS},
- {"NAND 4GiB 3,3V 8-bit", 0xD7, 0, 4096, 0, LP_OPTIONS},
- {"NAND 4GiB 1,8V 16-bit", 0xB7, 0, 4096, 0, LP_OPTIONS16},
- {"NAND 4GiB 3,3V 16-bit", 0xC7, 0, 4096, 0, LP_OPTIONS16},
-
- /* 64 Gigabit */
- {"NAND 8GiB 1,8V 8-bit", 0xAE, 0, 8192, 0, LP_OPTIONS},
- {"NAND 8GiB 3,3V 8-bit", 0xDE, 0, 8192, 0, LP_OPTIONS},
- {"NAND 8GiB 1,8V 16-bit", 0xBE, 0, 8192, 0, LP_OPTIONS16},
- {"NAND 8GiB 3,3V 16-bit", 0xCE, 0, 8192, 0, LP_OPTIONS16},
-
- /* 128 Gigabit */
- {"NAND 16GiB 1,8V 8-bit", 0x1A, 0, 16384, 0, LP_OPTIONS},
- {"NAND 16GiB 3,3V 8-bit", 0x3A, 0, 16384, 0, LP_OPTIONS},
- {"NAND 16GiB 1,8V 16-bit", 0x2A, 0, 16384, 0, LP_OPTIONS16},
- {"NAND 16GiB 3,3V 16-bit", 0x4A, 0, 16384, 0, LP_OPTIONS16},
-
- /* 256 Gigabit */
- {"NAND 32GiB 1,8V 8-bit", 0x1C, 0, 32768, 0, LP_OPTIONS},
- {"NAND 32GiB 3,3V 8-bit", 0x3C, 0, 32768, 0, LP_OPTIONS},
- {"NAND 32GiB 1,8V 16-bit", 0x2C, 0, 32768, 0, LP_OPTIONS16},
- {"NAND 32GiB 3,3V 16-bit", 0x4C, 0, 32768, 0, LP_OPTIONS16},
-
- /* 512 Gigabit */
- {"NAND 64GiB 1,8V 8-bit", 0x1E, 0, 65536, 0, LP_OPTIONS},
- {"NAND 64GiB 3,3V 8-bit", 0x3E, 0, 65536, 0, LP_OPTIONS},
- {"NAND 64GiB 1,8V 16-bit", 0x2E, 0, 65536, 0, LP_OPTIONS16},
- {"NAND 64GiB 3,3V 16-bit", 0x4E, 0, 65536, 0, LP_OPTIONS16},
-
- /*
- * Renesas AND 1 Gigabit. Those chips do not support extended id and
- * have a strange page/block layout ! The chosen minimum erasesize is
- * 4 * 2 * 2048 = 16384 Byte, as those chips have an array of 4 page
- * planes 1 block = 2 pages, but due to plane arrangement the blocks
- * 0-3 consists of page 0 + 4,1 + 5, 2 + 6, 3 + 7 Anyway JFFS2 would
- * increase the eraseblock size so we chose a combined one which can be
- * erased in one go There are more speed improvements for reads and
- * writes possible, but not implemented now
- */
- {"AND 128MiB 3,3V 8-bit", 0x01, 2048, 128, 0x4000,
- NAND_IS_AND | NAND_4PAGE_ARRAY | BBT_AUTO_REFRESH},
-
- {NULL,}
-};
-
-/*
-* Manufacturer ID list
-*/
-const struct nand_manufacturers nand_manuf_ids[] = {
- {NAND_MFR_TOSHIBA, "Toshiba"},
- {NAND_MFR_SAMSUNG, "Samsung"},
- {NAND_MFR_FUJITSU, "Fujitsu"},
- {NAND_MFR_NATIONAL, "National"},
- {NAND_MFR_RENESAS, "Renesas"},
- {NAND_MFR_STMICRO, "ST Micro"},
- {NAND_MFR_HYNIX, "Hynix"},
- {NAND_MFR_MICRON, "Micron"},
- {NAND_MFR_AMD, "AMD/Spansion"},
- {NAND_MFR_MACRONIX, "Macronix"},
- {NAND_MFR_EON, "Eon"},
- {0x0, "Unknown"}
-};
diff --git a/qemu/roms/u-boot/drivers/mtd/nand/nand_plat.c b/qemu/roms/u-boot/drivers/mtd/nand/nand_plat.c
deleted file mode 100644
index 37a0206ad..000000000
--- a/qemu/roms/u-boot/drivers/mtd/nand/nand_plat.c
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Genericish driver for memory mapped NAND devices
- *
- * Copyright (c) 2006-2009 Analog Devices Inc.
- * Licensed under the GPL-2 or later.
- */
-
-/* Your board must implement the following macros:
- * NAND_PLAT_WRITE_CMD(chip, cmd)
- * NAND_PLAT_WRITE_ADR(chip, cmd)
- * NAND_PLAT_INIT()
- *
- * It may also implement the following:
- * NAND_PLAT_DEV_READY(chip)
- */
-
-#include <common.h>
-#include <asm/io.h>
-#ifdef NAND_PLAT_GPIO_DEV_READY
-# include <asm/gpio.h>
-# define NAND_PLAT_DEV_READY(chip) gpio_get_value(NAND_PLAT_GPIO_DEV_READY)
-#endif
-
-#include <nand.h>
-
-static void plat_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
-{
- struct nand_chip *this = mtd->priv;
-
- if (cmd == NAND_CMD_NONE)
- return;
-
- if (ctrl & NAND_CLE)
- NAND_PLAT_WRITE_CMD(this, cmd);
- else
- NAND_PLAT_WRITE_ADR(this, cmd);
-}
-
-#ifdef NAND_PLAT_DEV_READY
-static int plat_dev_ready(struct mtd_info *mtd)
-{
- return NAND_PLAT_DEV_READY((struct nand_chip *)mtd->priv);
-}
-#else
-# define plat_dev_ready NULL
-#endif
-
-int board_nand_init(struct nand_chip *nand)
-{
-#ifdef NAND_PLAT_GPIO_DEV_READY
- gpio_request(NAND_PLAT_GPIO_DEV_READY, "nand-plat");
- gpio_direction_input(NAND_PLAT_GPIO_DEV_READY);
-#endif
-
-#ifdef NAND_PLAT_INIT
- NAND_PLAT_INIT();
-#endif
-
- nand->cmd_ctrl = plat_cmd_ctrl;
- nand->dev_ready = plat_dev_ready;
- nand->ecc.mode = NAND_ECC_SOFT;
-
- return 0;
-}
diff --git a/qemu/roms/u-boot/drivers/mtd/nand/nand_spl_load.c b/qemu/roms/u-boot/drivers/mtd/nand/nand_spl_load.c
deleted file mode 100644
index 5a2564464..000000000
--- a/qemu/roms/u-boot/drivers/mtd/nand/nand_spl_load.c
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2011
- * Heiko Schocher, DENX Software Engineering, hs@denx.de.
- *
- * SPDX-License-Identifier: GPL-2.0+
- */
-
-#include <common.h>
-#include <nand.h>
-
-/*
- * The main entry for NAND booting. It's necessary that SDRAM is already
- * configured and available since this code loads the main U-Boot image
- * from NAND into SDRAM and starts it from there.
- */
-void nand_boot(void)
-{
- __attribute__((noreturn)) void (*uboot)(void);
-
- /*
- * Load U-Boot image from NAND into RAM
- */
- nand_spl_load_image(CONFIG_SYS_NAND_U_BOOT_OFFS,
- CONFIG_SYS_NAND_U_BOOT_SIZE,
- (void *)CONFIG_SYS_NAND_U_BOOT_DST);
-
-#ifdef CONFIG_NAND_ENV_DST
- nand_spl_load_image(CONFIG_ENV_OFFSET, CONFIG_ENV_SIZE,
- (void *)CONFIG_NAND_ENV_DST);
-
-#ifdef CONFIG_ENV_OFFSET_REDUND
- nand_spl_load_image(CONFIG_ENV_OFFSET_REDUND, CONFIG_ENV_SIZE,
- (void *)CONFIG_NAND_ENV_DST + CONFIG_ENV_SIZE);
-#endif
-#endif
-
- /*
- * Jump to U-Boot image
- */
- uboot = (void *)CONFIG_SYS_NAND_U_BOOT_START;
- (*uboot)();
-}
diff --git a/qemu/roms/u-boot/drivers/mtd/nand/nand_spl_simple.c b/qemu/roms/u-boot/drivers/mtd/nand/nand_spl_simple.c
deleted file mode 100644
index cead4b506..000000000
--- a/qemu/roms/u-boot/drivers/mtd/nand/nand_spl_simple.c
+++ /dev/null
@@ -1,270 +0,0 @@
-/*
- * (C) Copyright 2006-2008
- * Stefan Roese, DENX Software Engineering, sr@denx.de.
- *
- * SPDX-License-Identifier: GPL-2.0+
- */
-
-#include <common.h>
-#include <nand.h>
-#include <asm/io.h>
-#include <linux/mtd/nand_ecc.h>
-
-static int nand_ecc_pos[] = CONFIG_SYS_NAND_ECCPOS;
-static nand_info_t mtd;
-static struct nand_chip nand_chip;
-
-#define ECCSTEPS (CONFIG_SYS_NAND_PAGE_SIZE / \
- CONFIG_SYS_NAND_ECCSIZE)
-#define ECCTOTAL (ECCSTEPS * CONFIG_SYS_NAND_ECCBYTES)
-
-
-#if (CONFIG_SYS_NAND_PAGE_SIZE <= 512)
-/*
- * NAND command for small page NAND devices (512)
- */
-static int nand_command(int block, int page, uint32_t offs,
- u8 cmd)
-{
- struct nand_chip *this = mtd.priv;
- int page_addr = page + block * CONFIG_SYS_NAND_PAGE_COUNT;
-
- while (!this->dev_ready(&mtd))
- ;
-
- /* Begin command latch cycle */
- this->cmd_ctrl(&mtd, cmd, NAND_CTRL_CLE | NAND_CTRL_CHANGE);
- /* Set ALE and clear CLE to start address cycle */
- /* Column address */
- this->cmd_ctrl(&mtd, offs, NAND_CTRL_ALE | NAND_CTRL_CHANGE);
- this->cmd_ctrl(&mtd, page_addr & 0xff, NAND_CTRL_ALE); /* A[16:9] */
- this->cmd_ctrl(&mtd, (page_addr >> 8) & 0xff,
- NAND_CTRL_ALE); /* A[24:17] */
-#ifdef CONFIG_SYS_NAND_4_ADDR_CYCLE
- /* One more address cycle for devices > 32MiB */
- this->cmd_ctrl(&mtd, (page_addr >> 16) & 0x0f,
- NAND_CTRL_ALE); /* A[28:25] */
-#endif
- /* Latch in address */
- this->cmd_ctrl(&mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
-
- /*
- * Wait a while for the data to be ready
- */
- while (!this->dev_ready(&mtd))
- ;
-
- return 0;
-}
-#else
-/*
- * NAND command for large page NAND devices (2k)
- */
-static int nand_command(int block, int page, uint32_t offs,
- u8 cmd)
-{
- struct nand_chip *this = mtd.priv;
- int page_addr = page + block * CONFIG_SYS_NAND_PAGE_COUNT;
- void (*hwctrl)(struct mtd_info *mtd, int cmd,
- unsigned int ctrl) = this->cmd_ctrl;
-
- while (!this->dev_ready(&mtd))
- ;
-
- /* Emulate NAND_CMD_READOOB */
- if (cmd == NAND_CMD_READOOB) {
- offs += CONFIG_SYS_NAND_PAGE_SIZE;
- cmd = NAND_CMD_READ0;
- }
-
- /* Shift the offset from byte addressing to word addressing. */
- if (this->options & NAND_BUSWIDTH_16)
- offs >>= 1;
-
- /* Begin command latch cycle */
- hwctrl(&mtd, cmd, NAND_CTRL_CLE | NAND_CTRL_CHANGE);
- /* Set ALE and clear CLE to start address cycle */
- /* Column address */
- hwctrl(&mtd, offs & 0xff,
- NAND_CTRL_ALE | NAND_CTRL_CHANGE); /* A[7:0] */
- hwctrl(&mtd, (offs >> 8) & 0xff, NAND_CTRL_ALE); /* A[11:9] */
- /* Row address */
- hwctrl(&mtd, (page_addr & 0xff), NAND_CTRL_ALE); /* A[19:12] */
- hwctrl(&mtd, ((page_addr >> 8) & 0xff),
- NAND_CTRL_ALE); /* A[27:20] */
-#ifdef CONFIG_SYS_NAND_5_ADDR_CYCLE
- /* One more address cycle for devices > 128MiB */
- hwctrl(&mtd, (page_addr >> 16) & 0x0f,
- NAND_CTRL_ALE); /* A[31:28] */
-#endif
- /* Latch in address */
- hwctrl(&mtd, NAND_CMD_READSTART,
- NAND_CTRL_CLE | NAND_CTRL_CHANGE);
- hwctrl(&mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
-
- /*
- * Wait a while for the data to be ready
- */
- while (!this->dev_ready(&mtd))
- ;
-
- return 0;
-}
-#endif
-
-static int nand_is_bad_block(int block)
-{
- struct nand_chip *this = mtd.priv;
-
- nand_command(block, 0, CONFIG_SYS_NAND_BAD_BLOCK_POS,
- NAND_CMD_READOOB);
-
- /*
- * Read one byte (or two if it's a 16 bit chip).
- */
- if (this->options & NAND_BUSWIDTH_16) {
- if (readw(this->IO_ADDR_R) != 0xffff)
- return 1;
- } else {
- if (readb(this->IO_ADDR_R) != 0xff)
- return 1;
- }
-
- return 0;
-}
-
-#if defined(CONFIG_SYS_NAND_HW_ECC_OOBFIRST)
-static int nand_read_page(int block, int page, uchar *dst)
-{
- struct nand_chip *this = mtd.priv;
- u_char ecc_calc[ECCTOTAL];
- u_char ecc_code[ECCTOTAL];
- u_char oob_data[CONFIG_SYS_NAND_OOBSIZE];
- int i;
- int eccsize = CONFIG_SYS_NAND_ECCSIZE;
- int eccbytes = CONFIG_SYS_NAND_ECCBYTES;
- int eccsteps = ECCSTEPS;
- uint8_t *p = dst;
-
- nand_command(block, page, 0, NAND_CMD_READOOB);
- this->read_buf(&mtd, oob_data, CONFIG_SYS_NAND_OOBSIZE);
- nand_command(block, page, 0, NAND_CMD_READ0);
-
- /* Pick the ECC bytes out of the oob data */
- for (i = 0; i < ECCTOTAL; i++)
- ecc_code[i] = oob_data[nand_ecc_pos[i]];
-
-
- for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
- this->ecc.hwctl(&mtd, NAND_ECC_READ);
- this->read_buf(&mtd, p, eccsize);
- this->ecc.calculate(&mtd, p, &ecc_calc[i]);
- this->ecc.correct(&mtd, p, &ecc_code[i], &ecc_calc[i]);
- }
-
- return 0;
-}
-#else
-static int nand_read_page(int block, int page, void *dst)
-{
- struct nand_chip *this = mtd.priv;
- u_char ecc_calc[ECCTOTAL];
- u_char ecc_code[ECCTOTAL];
- u_char oob_data[CONFIG_SYS_NAND_OOBSIZE];
- int i;
- int eccsize = CONFIG_SYS_NAND_ECCSIZE;
- int eccbytes = CONFIG_SYS_NAND_ECCBYTES;
- int eccsteps = ECCSTEPS;
- uint8_t *p = dst;
-
- nand_command(block, page, 0, NAND_CMD_READ0);
-
- for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
- if (this->ecc.mode != NAND_ECC_SOFT)
- this->ecc.hwctl(&mtd, NAND_ECC_READ);
- this->read_buf(&mtd, p, eccsize);
- this->ecc.calculate(&mtd, p, &ecc_calc[i]);
- }
- this->read_buf(&mtd, oob_data, CONFIG_SYS_NAND_OOBSIZE);
-
- /* Pick the ECC bytes out of the oob data */
- for (i = 0; i < ECCTOTAL; i++)
- ecc_code[i] = oob_data[nand_ecc_pos[i]];
-
- eccsteps = ECCSTEPS;
- p = dst;
-
- for (i = 0 ; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
- /* No chance to do something with the possible error message
- * from correct_data(). We just hope that all possible errors
- * are corrected by this routine.
- */
- this->ecc.correct(&mtd, p, &ecc_code[i], &ecc_calc[i]);
- }
-
- return 0;
-}
-#endif
-
-int nand_spl_load_image(uint32_t offs, unsigned int size, void *dst)
-{
- unsigned int block, lastblock;
- unsigned int page;
-
- /*
- * offs has to be aligned to a page address!
- */
- block = offs / CONFIG_SYS_NAND_BLOCK_SIZE;
- lastblock = (offs + size - 1) / CONFIG_SYS_NAND_BLOCK_SIZE;
- page = (offs % CONFIG_SYS_NAND_BLOCK_SIZE) / CONFIG_SYS_NAND_PAGE_SIZE;
-
- while (block <= lastblock) {
- if (!nand_is_bad_block(block)) {
- /*
- * Skip bad blocks
- */
- while (page < CONFIG_SYS_NAND_PAGE_COUNT) {
- nand_read_page(block, page, dst);
- dst += CONFIG_SYS_NAND_PAGE_SIZE;
- page++;
- }
-
- page = 0;
- } else {
- lastblock++;
- }
-
- block++;
- }
-
- return 0;
-}
-
-/* nand_init() - initialize data to make nand usable by SPL */
-void nand_init(void)
-{
- /*
- * Init board specific nand support
- */
- mtd.priv = &nand_chip;
- nand_chip.IO_ADDR_R = nand_chip.IO_ADDR_W =
- (void __iomem *)CONFIG_SYS_NAND_BASE;
- board_nand_init(&nand_chip);
-
-#ifdef CONFIG_SPL_NAND_SOFTECC
- if (nand_chip.ecc.mode == NAND_ECC_SOFT) {
- nand_chip.ecc.calculate = nand_calculate_ecc;
- nand_chip.ecc.correct = nand_correct_data;
- }
-#endif
-
- if (nand_chip.select_chip)
- nand_chip.select_chip(&mtd, 0);
-}
-
-/* Unselect after operation */
-void nand_deselect(void)
-{
- if (nand_chip.select_chip)
- nand_chip.select_chip(&mtd, -1);
-}
diff --git a/qemu/roms/u-boot/drivers/mtd/nand/nand_util.c b/qemu/roms/u-boot/drivers/mtd/nand/nand_util.c
deleted file mode 100644
index b29282603..000000000
--- a/qemu/roms/u-boot/drivers/mtd/nand/nand_util.c
+++ /dev/null
@@ -1,861 +0,0 @@
-/*
- * drivers/mtd/nand/nand_util.c
- *
- * Copyright (C) 2006 by Weiss-Electronic GmbH.
- * All rights reserved.
- *
- * @author: Guido Classen <clagix@gmail.com>
- * @descr: NAND Flash support
- * @references: borrowed heavily from Linux mtd-utils code:
- * flash_eraseall.c by Arcom Control System Ltd
- * nandwrite.c by Steven J. Hill (sjhill@realitydiluted.com)
- * and Thomas Gleixner (tglx@linutronix.de)
- *
- * Copyright (C) 2008 Nokia Corporation: drop_ffs() function by
- * Artem Bityutskiy <dedekind1@gmail.com> from mtd-utils
- *
- * Copyright 2010 Freescale Semiconductor
- *
- * SPDX-License-Identifier: GPL-2.0
- */
-
-#include <common.h>
-#include <command.h>
-#include <watchdog.h>
-#include <malloc.h>
-#include <div64.h>
-
-#include <asm/errno.h>
-#include <linux/mtd/mtd.h>
-#include <nand.h>
-#include <jffs2/jffs2.h>
-
-typedef struct erase_info erase_info_t;
-typedef struct mtd_info mtd_info_t;
-
-/* support only for native endian JFFS2 */
-#define cpu_to_je16(x) (x)
-#define cpu_to_je32(x) (x)
-
-/**
- * nand_erase_opts: - erase NAND flash with support for various options
- * (jffs2 formatting)
- *
- * @param meminfo NAND device to erase
- * @param opts options, @see struct nand_erase_options
- * @return 0 in case of success
- *
- * This code is ported from flash_eraseall.c from Linux mtd utils by
- * Arcom Control System Ltd.
- */
-int nand_erase_opts(nand_info_t *meminfo, const nand_erase_options_t *opts)
-{
- struct jffs2_unknown_node cleanmarker;
- erase_info_t erase;
- unsigned long erase_length, erased_length; /* in blocks */
- int result;
- int percent_complete = -1;
- const char *mtd_device = meminfo->name;
- struct mtd_oob_ops oob_opts;
- struct nand_chip *chip = meminfo->priv;
-
- if ((opts->offset & (meminfo->erasesize - 1)) != 0) {
- printf("Attempt to erase non block-aligned data\n");
- return -1;
- }
-
- memset(&erase, 0, sizeof(erase));
- memset(&oob_opts, 0, sizeof(oob_opts));
-
- erase.mtd = meminfo;
- erase.len = meminfo->erasesize;
- erase.addr = opts->offset;
- erase_length = lldiv(opts->length + meminfo->erasesize - 1,
- meminfo->erasesize);
-
- cleanmarker.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
- cleanmarker.nodetype = cpu_to_je16(JFFS2_NODETYPE_CLEANMARKER);
- cleanmarker.totlen = cpu_to_je32(8);
-
- /* scrub option allows to erase badblock. To prevent internal
- * check from erase() method, set block check method to dummy
- * and disable bad block table while erasing.
- */
- if (opts->scrub) {
- erase.scrub = opts->scrub;
- /*
- * We don't need the bad block table anymore...
- * after scrub, there are no bad blocks left!
- */
- if (chip->bbt) {
- kfree(chip->bbt);
- }
- chip->bbt = NULL;
- }
-
- for (erased_length = 0;
- erased_length < erase_length;
- erase.addr += meminfo->erasesize) {
-
- WATCHDOG_RESET();
-
- if (opts->lim && (erase.addr >= (opts->offset + opts->lim))) {
- puts("Size of erase exceeds limit\n");
- return -EFBIG;
- }
- if (!opts->scrub) {
- int ret = mtd_block_isbad(meminfo, erase.addr);
- if (ret > 0) {
- if (!opts->quiet)
- printf("\rSkipping bad block at "
- "0x%08llx "
- " \n",
- erase.addr);
-
- if (!opts->spread)
- erased_length++;
-
- continue;
-
- } else if (ret < 0) {
- printf("\n%s: MTD get bad block failed: %d\n",
- mtd_device,
- ret);
- return -1;
- }
- }
-
- erased_length++;
-
- result = mtd_erase(meminfo, &erase);
- if (result != 0) {
- printf("\n%s: MTD Erase failure: %d\n",
- mtd_device, result);
- continue;
- }
-
- /* format for JFFS2 ? */
- if (opts->jffs2 && chip->ecc.layout->oobavail >= 8) {
- struct mtd_oob_ops ops;
- ops.ooblen = 8;
- ops.datbuf = NULL;
- ops.oobbuf = (uint8_t *)&cleanmarker;
- ops.ooboffs = 0;
- ops.mode = MTD_OPS_AUTO_OOB;
-
- result = mtd_write_oob(meminfo,
- erase.addr,
- &ops);
- if (result != 0) {
- printf("\n%s: MTD writeoob failure: %d\n",
- mtd_device, result);
- continue;
- }
- }
-
- if (!opts->quiet) {
- unsigned long long n = erased_length * 100ULL;
- int percent;
-
- do_div(n, erase_length);
- percent = (int)n;
-
- /* output progress message only at whole percent
- * steps to reduce the number of messages printed
- * on (slow) serial consoles
- */
- if (percent != percent_complete) {
- percent_complete = percent;
-
- printf("\rErasing at 0x%llx -- %3d%% complete.",
- erase.addr, percent);
-
- if (opts->jffs2 && result == 0)
- printf(" Cleanmarker written at 0x%llx.",
- erase.addr);
- }
- }
- }
- if (!opts->quiet)
- printf("\n");
-
- if (opts->scrub)
- chip->scan_bbt(meminfo);
-
- return 0;
-}
-
-#ifdef CONFIG_CMD_NAND_LOCK_UNLOCK
-
-/******************************************************************************
- * Support for locking / unlocking operations of some NAND devices
- *****************************************************************************/
-
-/**
- * nand_lock: Set all pages of NAND flash chip to the LOCK or LOCK-TIGHT
- * state
- *
- * @param mtd nand mtd instance
- * @param tight bring device in lock tight mode
- *
- * @return 0 on success, -1 in case of error
- *
- * The lock / lock-tight command only applies to the whole chip. To get some
- * parts of the chip lock and others unlocked use the following sequence:
- *
- * - Lock all pages of the chip using nand_lock(mtd, 0) (or the lockpre pin)
- * - Call nand_unlock() once for each consecutive area to be unlocked
- * - If desired: Bring the chip to the lock-tight state using nand_lock(mtd, 1)
- *
- * If the device is in lock-tight state software can't change the
- * current active lock/unlock state of all pages. nand_lock() / nand_unlock()
- * calls will fail. It is only posible to leave lock-tight state by
- * an hardware signal (low pulse on _WP pin) or by power down.
- */
-int nand_lock(struct mtd_info *mtd, int tight)
-{
- int ret = 0;
- int status;
- struct nand_chip *chip = mtd->priv;
-
- /* select the NAND device */
- chip->select_chip(mtd, 0);
-
- /* check the Lock Tight Status */
- chip->cmdfunc(mtd, NAND_CMD_LOCK_STATUS, -1, 0);
- if (chip->read_byte(mtd) & NAND_LOCK_STATUS_TIGHT) {
- printf("nand_lock: Device is locked tight!\n");
- ret = -1;
- goto out;
- }
-
- chip->cmdfunc(mtd,
- (tight ? NAND_CMD_LOCK_TIGHT : NAND_CMD_LOCK),
- -1, -1);
-
- /* call wait ready function */
- status = chip->waitfunc(mtd, chip);
-
- /* see if device thinks it succeeded */
- if (status & 0x01) {
- ret = -1;
- }
-
- out:
- /* de-select the NAND device */
- chip->select_chip(mtd, -1);
- return ret;
-}
-
-/**
- * nand_get_lock_status: - query current lock state from one page of NAND
- * flash
- *
- * @param mtd nand mtd instance
- * @param offset page address to query (must be page-aligned!)
- *
- * @return -1 in case of error
- * >0 lock status:
- * bitfield with the following combinations:
- * NAND_LOCK_STATUS_TIGHT: page in tight state
- * NAND_LOCK_STATUS_UNLOCK: page unlocked
- *
- */
-int nand_get_lock_status(struct mtd_info *mtd, loff_t offset)
-{
- int ret = 0;
- int chipnr;
- int page;
- struct nand_chip *chip = mtd->priv;
-
- /* select the NAND device */
- chipnr = (int)(offset >> chip->chip_shift);
- chip->select_chip(mtd, chipnr);
-
-
- if ((offset & (mtd->writesize - 1)) != 0) {
- printf("nand_get_lock_status: "
- "Start address must be beginning of "
- "nand page!\n");
- ret = -1;
- goto out;
- }
-
- /* check the Lock Status */
- page = (int)(offset >> chip->page_shift);
- chip->cmdfunc(mtd, NAND_CMD_LOCK_STATUS, -1, page & chip->pagemask);
-
- ret = chip->read_byte(mtd) & (NAND_LOCK_STATUS_TIGHT
- | NAND_LOCK_STATUS_UNLOCK);
-
- out:
- /* de-select the NAND device */
- chip->select_chip(mtd, -1);
- return ret;
-}
-
-/**
- * nand_unlock: - Unlock area of NAND pages
- * only one consecutive area can be unlocked at one time!
- *
- * @param mtd nand mtd instance
- * @param start start byte address
- * @param length number of bytes to unlock (must be a multiple of
- * page size nand->writesize)
- * @param allexcept if set, unlock everything not selected
- *
- * @return 0 on success, -1 in case of error
- */
-int nand_unlock(struct mtd_info *mtd, loff_t start, size_t length,
- int allexcept)
-{
- int ret = 0;
- int chipnr;
- int status;
- int page;
- struct nand_chip *chip = mtd->priv;
-
- debug("nand_unlock%s: start: %08llx, length: %zd!\n",
- allexcept ? " (allexcept)" : "", start, length);
-
- /* select the NAND device */
- chipnr = (int)(start >> chip->chip_shift);
- chip->select_chip(mtd, chipnr);
-
- /* check the WP bit */
- chip->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1);
- if (!(chip->read_byte(mtd) & NAND_STATUS_WP)) {
- printf("nand_unlock: Device is write protected!\n");
- ret = -1;
- goto out;
- }
-
- /* check the Lock Tight Status */
- page = (int)(start >> chip->page_shift);
- chip->cmdfunc(mtd, NAND_CMD_LOCK_STATUS, -1, page & chip->pagemask);
- if (chip->read_byte(mtd) & NAND_LOCK_STATUS_TIGHT) {
- printf("nand_unlock: Device is locked tight!\n");
- ret = -1;
- goto out;
- }
-
- if ((start & (mtd->erasesize - 1)) != 0) {
- printf("nand_unlock: Start address must be beginning of "
- "nand block!\n");
- ret = -1;
- goto out;
- }
-
- if (length == 0 || (length & (mtd->erasesize - 1)) != 0) {
- printf("nand_unlock: Length must be a multiple of nand block "
- "size %08x!\n", mtd->erasesize);
- ret = -1;
- goto out;
- }
-
- /*
- * Set length so that the last address is set to the
- * starting address of the last block
- */
- length -= mtd->erasesize;
-
- /* submit address of first page to unlock */
- chip->cmdfunc(mtd, NAND_CMD_UNLOCK1, -1, page & chip->pagemask);
-
- /* submit ADDRESS of LAST page to unlock */
- page += (int)(length >> chip->page_shift);
-
- /*
- * Page addresses for unlocking are supposed to be block-aligned.
- * At least some NAND chips use the low bit to indicate that the
- * page range should be inverted.
- */
- if (allexcept)
- page |= 1;
-
- chip->cmdfunc(mtd, NAND_CMD_UNLOCK2, -1, page & chip->pagemask);
-
- /* call wait ready function */
- status = chip->waitfunc(mtd, chip);
- /* see if device thinks it succeeded */
- if (status & 0x01) {
- /* there was an error */
- ret = -1;
- goto out;
- }
-
- out:
- /* de-select the NAND device */
- chip->select_chip(mtd, -1);
- return ret;
-}
-#endif
-
-/**
- * check_skip_len
- *
- * Check if there are any bad blocks, and whether length including bad
- * blocks fits into device
- *
- * @param nand NAND device
- * @param offset offset in flash
- * @param length image length
- * @param used length of flash needed for the requested length
- * @return 0 if the image fits and there are no bad blocks
- * 1 if the image fits, but there are bad blocks
- * -1 if the image does not fit
- */
-static int check_skip_len(nand_info_t *nand, loff_t offset, size_t length,
- size_t *used)
-{
- size_t len_excl_bad = 0;
- int ret = 0;
-
- while (len_excl_bad < length) {
- size_t block_len, block_off;
- loff_t block_start;
-
- if (offset >= nand->size)
- return -1;
-
- block_start = offset & ~(loff_t)(nand->erasesize - 1);
- block_off = offset & (nand->erasesize - 1);
- block_len = nand->erasesize - block_off;
-
- if (!nand_block_isbad(nand, block_start))
- len_excl_bad += block_len;
- else
- ret = 1;
-
- offset += block_len;
- *used += block_len;
- }
-
- /* If the length is not a multiple of block_len, adjust. */
- if (len_excl_bad > length)
- *used -= (len_excl_bad - length);
-
- return ret;
-}
-
-#ifdef CONFIG_CMD_NAND_TRIMFFS
-static size_t drop_ffs(const nand_info_t *nand, const u_char *buf,
- const size_t *len)
-{
- size_t l = *len;
- ssize_t i;
-
- for (i = l - 1; i >= 0; i--)
- if (buf[i] != 0xFF)
- break;
-
- /* The resulting length must be aligned to the minimum flash I/O size */
- l = i + 1;
- l = (l + nand->writesize - 1) / nand->writesize;
- l *= nand->writesize;
-
- /*
- * since the input length may be unaligned, prevent access past the end
- * of the buffer
- */
- return min(l, *len);
-}
-#endif
-
-/**
- * nand_write_skip_bad:
- *
- * Write image to NAND flash.
- * Blocks that are marked bad are skipped and the is written to the next
- * block instead as long as the image is short enough to fit even after
- * skipping the bad blocks. Due to bad blocks we may not be able to
- * perform the requested write. In the case where the write would
- * extend beyond the end of the NAND device, both length and actual (if
- * not NULL) are set to 0. In the case where the write would extend
- * beyond the limit we are passed, length is set to 0 and actual is set
- * to the required length.
- *
- * @param nand NAND device
- * @param offset offset in flash
- * @param length buffer length
- * @param actual set to size required to write length worth of
- * buffer or 0 on error, if not NULL
- * @param lim maximum size that actual may be in order to not
- * exceed the buffer
- * @param buffer buffer to read from
- * @param flags flags modifying the behaviour of the write to NAND
- * @return 0 in case of success
- */
-int nand_write_skip_bad(nand_info_t *nand, loff_t offset, size_t *length,
- size_t *actual, loff_t lim, u_char *buffer, int flags)
-{
- int rval = 0, blocksize;
- size_t left_to_write = *length;
- size_t used_for_write = 0;
- u_char *p_buffer = buffer;
- int need_skip;
-
- if (actual)
- *actual = 0;
-
-#ifdef CONFIG_CMD_NAND_YAFFS
- if (flags & WITH_YAFFS_OOB) {
- if (flags & ~WITH_YAFFS_OOB)
- return -EINVAL;
-
- int pages;
- pages = nand->erasesize / nand->writesize;
- blocksize = (pages * nand->oobsize) + nand->erasesize;
- if (*length % (nand->writesize + nand->oobsize)) {
- printf("Attempt to write incomplete page"
- " in yaffs mode\n");
- return -EINVAL;
- }
- } else
-#endif
- {
- blocksize = nand->erasesize;
- }
-
- /*
- * nand_write() handles unaligned, partial page writes.
- *
- * We allow length to be unaligned, for convenience in
- * using the $filesize variable.
- *
- * However, starting at an unaligned offset makes the
- * semantics of bad block skipping ambiguous (really,
- * you should only start a block skipping access at a
- * partition boundary). So don't try to handle that.
- */
- if ((offset & (nand->writesize - 1)) != 0) {
- printf("Attempt to write non page-aligned data\n");
- *length = 0;
- return -EINVAL;
- }
-
- need_skip = check_skip_len(nand, offset, *length, &used_for_write);
-
- if (actual)
- *actual = used_for_write;
-
- if (need_skip < 0) {
- printf("Attempt to write outside the flash area\n");
- *length = 0;
- return -EINVAL;
- }
-
- if (used_for_write > lim) {
- puts("Size of write exceeds partition or device limit\n");
- *length = 0;
- return -EFBIG;
- }
-
- if (!need_skip && !(flags & WITH_DROP_FFS)) {
- rval = nand_write(nand, offset, length, buffer);
- if (rval == 0)
- return 0;
-
- *length = 0;
- printf("NAND write to offset %llx failed %d\n",
- offset, rval);
- return rval;
- }
-
- while (left_to_write > 0) {
- size_t block_offset = offset & (nand->erasesize - 1);
- size_t write_size, truncated_write_size;
-
- WATCHDOG_RESET();
-
- if (nand_block_isbad(nand, offset & ~(nand->erasesize - 1))) {
- printf("Skip bad block 0x%08llx\n",
- offset & ~(nand->erasesize - 1));
- offset += nand->erasesize - block_offset;
- continue;
- }
-
- if (left_to_write < (blocksize - block_offset))
- write_size = left_to_write;
- else
- write_size = blocksize - block_offset;
-
-#ifdef CONFIG_CMD_NAND_YAFFS
- if (flags & WITH_YAFFS_OOB) {
- int page, pages;
- size_t pagesize = nand->writesize;
- size_t pagesize_oob = pagesize + nand->oobsize;
- struct mtd_oob_ops ops;
-
- ops.len = pagesize;
- ops.ooblen = nand->oobsize;
- ops.mode = MTD_OPS_AUTO_OOB;
- ops.ooboffs = 0;
-
- pages = write_size / pagesize_oob;
- for (page = 0; page < pages; page++) {
- WATCHDOG_RESET();
-
- ops.datbuf = p_buffer;
- ops.oobbuf = ops.datbuf + pagesize;
-
- rval = mtd_write_oob(nand, offset, &ops);
- if (rval != 0)
- break;
-
- offset += pagesize;
- p_buffer += pagesize_oob;
- }
- }
- else
-#endif
- {
- truncated_write_size = write_size;
-#ifdef CONFIG_CMD_NAND_TRIMFFS
- if (flags & WITH_DROP_FFS)
- truncated_write_size = drop_ffs(nand, p_buffer,
- &write_size);
-#endif
-
- rval = nand_write(nand, offset, &truncated_write_size,
- p_buffer);
- offset += write_size;
- p_buffer += write_size;
- }
-
- if (rval != 0) {
- printf("NAND write to offset %llx failed %d\n",
- offset, rval);
- *length -= left_to_write;
- return rval;
- }
-
- left_to_write -= write_size;
- }
-
- return 0;
-}
-
-/**
- * nand_read_skip_bad:
- *
- * Read image from NAND flash.
- * Blocks that are marked bad are skipped and the next block is read
- * instead as long as the image is short enough to fit even after
- * skipping the bad blocks. Due to bad blocks we may not be able to
- * perform the requested read. In the case where the read would extend
- * beyond the end of the NAND device, both length and actual (if not
- * NULL) are set to 0. In the case where the read would extend beyond
- * the limit we are passed, length is set to 0 and actual is set to the
- * required length.
- *
- * @param nand NAND device
- * @param offset offset in flash
- * @param length buffer length, on return holds number of read bytes
- * @param actual set to size required to read length worth of buffer or 0
- * on error, if not NULL
- * @param lim maximum size that actual may be in order to not exceed the
- * buffer
- * @param buffer buffer to write to
- * @return 0 in case of success
- */
-int nand_read_skip_bad(nand_info_t *nand, loff_t offset, size_t *length,
- size_t *actual, loff_t lim, u_char *buffer)
-{
- int rval;
- size_t left_to_read = *length;
- size_t used_for_read = 0;
- u_char *p_buffer = buffer;
- int need_skip;
-
- if ((offset & (nand->writesize - 1)) != 0) {
- printf("Attempt to read non page-aligned data\n");
- *length = 0;
- if (actual)
- *actual = 0;
- return -EINVAL;
- }
-
- need_skip = check_skip_len(nand, offset, *length, &used_for_read);
-
- if (actual)
- *actual = used_for_read;
-
- if (need_skip < 0) {
- printf("Attempt to read outside the flash area\n");
- *length = 0;
- return -EINVAL;
- }
-
- if (used_for_read > lim) {
- puts("Size of read exceeds partition or device limit\n");
- *length = 0;
- return -EFBIG;
- }
-
- if (!need_skip) {
- rval = nand_read(nand, offset, length, buffer);
- if (!rval || rval == -EUCLEAN)
- return 0;
-
- *length = 0;
- printf("NAND read from offset %llx failed %d\n",
- offset, rval);
- return rval;
- }
-
- while (left_to_read > 0) {
- size_t block_offset = offset & (nand->erasesize - 1);
- size_t read_length;
-
- WATCHDOG_RESET();
-
- if (nand_block_isbad(nand, offset & ~(nand->erasesize - 1))) {
- printf("Skipping bad block 0x%08llx\n",
- offset & ~(nand->erasesize - 1));
- offset += nand->erasesize - block_offset;
- continue;
- }
-
- if (left_to_read < (nand->erasesize - block_offset))
- read_length = left_to_read;
- else
- read_length = nand->erasesize - block_offset;
-
- rval = nand_read(nand, offset, &read_length, p_buffer);
- if (rval && rval != -EUCLEAN) {
- printf("NAND read from offset %llx failed %d\n",
- offset, rval);
- *length -= left_to_read;
- return rval;
- }
-
- left_to_read -= read_length;
- offset += read_length;
- p_buffer += read_length;
- }
-
- return 0;
-}
-
-#ifdef CONFIG_CMD_NAND_TORTURE
-
-/**
- * check_pattern:
- *
- * Check if buffer contains only a certain byte pattern.
- *
- * @param buf buffer to check
- * @param patt the pattern to check
- * @param size buffer size in bytes
- * @return 1 if there are only patt bytes in buf
- * 0 if something else was found
- */
-static int check_pattern(const u_char *buf, u_char patt, int size)
-{
- int i;
-
- for (i = 0; i < size; i++)
- if (buf[i] != patt)
- return 0;
- return 1;
-}
-
-/**
- * nand_torture:
- *
- * Torture a block of NAND flash.
- * This is useful to determine if a block that caused a write error is still
- * good or should be marked as bad.
- *
- * @param nand NAND device
- * @param offset offset in flash
- * @return 0 if the block is still good
- */
-int nand_torture(nand_info_t *nand, loff_t offset)
-{
- u_char patterns[] = {0xa5, 0x5a, 0x00};
- struct erase_info instr = {
- .mtd = nand,
- .addr = offset,
- .len = nand->erasesize,
- };
- size_t retlen;
- int err, ret = -1, i, patt_count;
- u_char *buf;
-
- if ((offset & (nand->erasesize - 1)) != 0) {
- puts("Attempt to torture a block at a non block-aligned offset\n");
- return -EINVAL;
- }
-
- if (offset + nand->erasesize > nand->size) {
- puts("Attempt to torture a block outside the flash area\n");
- return -EINVAL;
- }
-
- patt_count = ARRAY_SIZE(patterns);
-
- buf = malloc(nand->erasesize);
- if (buf == NULL) {
- puts("Out of memory for erase block buffer\n");
- return -ENOMEM;
- }
-
- for (i = 0; i < patt_count; i++) {
- err = nand->erase(nand, &instr);
- if (err) {
- printf("%s: erase() failed for block at 0x%llx: %d\n",
- nand->name, instr.addr, err);
- goto out;
- }
-
- /* Make sure the block contains only 0xff bytes */
- err = nand->read(nand, offset, nand->erasesize, &retlen, buf);
- if ((err && err != -EUCLEAN) || retlen != nand->erasesize) {
- printf("%s: read() failed for block at 0x%llx: %d\n",
- nand->name, instr.addr, err);
- goto out;
- }
-
- err = check_pattern(buf, 0xff, nand->erasesize);
- if (!err) {
- printf("Erased block at 0x%llx, but a non-0xff byte was found\n",
- offset);
- ret = -EIO;
- goto out;
- }
-
- /* Write a pattern and check it */
- memset(buf, patterns[i], nand->erasesize);
- err = nand->write(nand, offset, nand->erasesize, &retlen, buf);
- if (err || retlen != nand->erasesize) {
- printf("%s: write() failed for block at 0x%llx: %d\n",
- nand->name, instr.addr, err);
- goto out;
- }
-
- err = nand->read(nand, offset, nand->erasesize, &retlen, buf);
- if ((err && err != -EUCLEAN) || retlen != nand->erasesize) {
- printf("%s: read() failed for block at 0x%llx: %d\n",
- nand->name, instr.addr, err);
- goto out;
- }
-
- err = check_pattern(buf, patterns[i], nand->erasesize);
- if (!err) {
- printf("Pattern 0x%.2x checking failed for block at "
- "0x%llx\n", patterns[i], offset);
- ret = -EIO;
- goto out;
- }
- }
-
- ret = 0;
-
-out:
- free(buf);
- return ret;
-}
-
-#endif
diff --git a/qemu/roms/u-boot/drivers/mtd/nand/ndfc.c b/qemu/roms/u-boot/drivers/mtd/nand/ndfc.c
deleted file mode 100644
index 5510b13c0..000000000
--- a/qemu/roms/u-boot/drivers/mtd/nand/ndfc.c
+++ /dev/null
@@ -1,214 +0,0 @@
-/*
- * Overview:
- * Platform independend driver for NDFC (NanD Flash Controller)
- * integrated into IBM/AMCC PPC4xx cores
- *
- * (C) Copyright 2006-2009
- * Stefan Roese, DENX Software Engineering, sr@denx.de.
- *
- * Based on original work by
- * Thomas Gleixner
- * Copyright 2006 IBM
- *
- * SPDX-License-Identifier: GPL-2.0+
- */
-
-#include <common.h>
-#include <nand.h>
-#include <linux/mtd/ndfc.h>
-#include <linux/mtd/nand_ecc.h>
-#include <asm/processor.h>
-#include <asm/io.h>
-#include <asm/ppc4xx.h>
-
-#ifndef CONFIG_SYS_NAND_BCR
-#define CONFIG_SYS_NAND_BCR 0x80002222
-#endif
-#ifndef CONFIG_SYS_NDFC_EBC0_CFG
-#define CONFIG_SYS_NDFC_EBC0_CFG 0xb8400000
-#endif
-
-/*
- * We need to store the info, which chip-select (CS) is used for the
- * chip number. For example on Sequoia NAND chip #0 uses
- * CS #3.
- */
-static int ndfc_cs[NDFC_MAX_BANKS];
-
-static void ndfc_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
-{
- struct nand_chip *this = mtd->priv;
- ulong base = (ulong) this->IO_ADDR_W & 0xffffff00;
-
- if (cmd == NAND_CMD_NONE)
- return;
-
- if (ctrl & NAND_CLE)
- out_8((u8 *)(base + NDFC_CMD), cmd & 0xFF);
- else
- out_8((u8 *)(base + NDFC_ALE), cmd & 0xFF);
-}
-
-static int ndfc_dev_ready(struct mtd_info *mtdinfo)
-{
- struct nand_chip *this = mtdinfo->priv;
- ulong base = (ulong) this->IO_ADDR_W & 0xffffff00;
-
- return (in_be32((u32 *)(base + NDFC_STAT)) & NDFC_STAT_IS_READY);
-}
-
-static void ndfc_enable_hwecc(struct mtd_info *mtdinfo, int mode)
-{
- struct nand_chip *this = mtdinfo->priv;
- ulong base = (ulong) this->IO_ADDR_W & 0xffffff00;
- u32 ccr;
-
- ccr = in_be32((u32 *)(base + NDFC_CCR));
- ccr |= NDFC_CCR_RESET_ECC;
- out_be32((u32 *)(base + NDFC_CCR), ccr);
-}
-
-static int ndfc_calculate_ecc(struct mtd_info *mtdinfo,
- const u_char *dat, u_char *ecc_code)
-{
- struct nand_chip *this = mtdinfo->priv;
- ulong base = (ulong) this->IO_ADDR_W & 0xffffff00;
- u32 ecc;
- u8 *p = (u8 *)&ecc;
-
- ecc = in_be32((u32 *)(base + NDFC_ECC));
-
- /* The NDFC uses Smart Media (SMC) bytes order
- */
- ecc_code[0] = p[1];
- ecc_code[1] = p[2];
- ecc_code[2] = p[3];
-
- return 0;
-}
-
-/*
- * Speedups for buffer read/write/verify
- *
- * NDFC allows 32bit read/write of data. So we can speed up the buffer
- * functions. No further checking, as nand_base will always read/write
- * page aligned.
- */
-static void ndfc_read_buf(struct mtd_info *mtdinfo, uint8_t *buf, int len)
-{
- struct nand_chip *this = mtdinfo->priv;
- ulong base = (ulong) this->IO_ADDR_W & 0xffffff00;
- uint32_t *p = (uint32_t *) buf;
-
- for (;len > 0; len -= 4)
- *p++ = in_be32((u32 *)(base + NDFC_DATA));
-}
-
-/*
- * Don't use these speedup functions in NAND boot image, since the image
- * has to fit into 4kByte.
- */
-static void ndfc_write_buf(struct mtd_info *mtdinfo, const uint8_t *buf, int len)
-{
- struct nand_chip *this = mtdinfo->priv;
- ulong base = (ulong) this->IO_ADDR_W & 0xffffff00;
- uint32_t *p = (uint32_t *) buf;
-
- for (; len > 0; len -= 4)
- out_be32((u32 *)(base + NDFC_DATA), *p++);
-}
-
-static int ndfc_verify_buf(struct mtd_info *mtdinfo, const uint8_t *buf, int len)
-{
- struct nand_chip *this = mtdinfo->priv;
- ulong base = (ulong) this->IO_ADDR_W & 0xffffff00;
- uint32_t *p = (uint32_t *) buf;
-
- for (; len > 0; len -= 4)
- if (*p++ != in_be32((u32 *)(base + NDFC_DATA)))
- return -1;
-
- return 0;
-}
-
-/*
- * Read a byte from the NDFC.
- */
-static uint8_t ndfc_read_byte(struct mtd_info *mtd)
-{
-
- struct nand_chip *chip = mtd->priv;
-
-#ifdef CONFIG_SYS_NAND_BUSWIDTH_16BIT
- return (uint8_t) readw(chip->IO_ADDR_R);
-#else
- return readb(chip->IO_ADDR_R);
-#endif
-
-}
-
-void board_nand_select_device(struct nand_chip *nand, int chip)
-{
- /*
- * Don't use "chip" to address the NAND device,
- * generate the cs from the address where it is encoded.
- */
- ulong base = (ulong)nand->IO_ADDR_W & 0xffffff00;
- int cs = ndfc_cs[chip];
-
- /* Set NandFlash Core Configuration Register */
- /* 1 col x 2 rows */
- out_be32((u32 *)(base + NDFC_CCR), 0x00000000 | (cs << 24));
- out_be32((u32 *)(base + NDFC_BCFG0 + (cs << 2)), CONFIG_SYS_NAND_BCR);
-}
-
-static void ndfc_select_chip(struct mtd_info *mtd, int chip)
-{
- /*
- * Nothing to do here!
- */
-}
-
-int board_nand_init(struct nand_chip *nand)
-{
- int cs = (ulong)nand->IO_ADDR_W & 0x00000003;
- ulong base = (ulong)nand->IO_ADDR_W & 0xffffff00;
- static int chip = 0;
-
- /*
- * Save chip-select for this chip #
- */
- ndfc_cs[chip] = cs;
-
- /*
- * Select required NAND chip in NDFC
- */
- board_nand_select_device(nand, chip);
-
- nand->IO_ADDR_R = (void __iomem *)(base + NDFC_DATA);
- nand->IO_ADDR_W = (void __iomem *)(base + NDFC_DATA);
- nand->cmd_ctrl = ndfc_hwcontrol;
- nand->chip_delay = 50;
- nand->read_buf = ndfc_read_buf;
- nand->dev_ready = ndfc_dev_ready;
- nand->ecc.correct = nand_correct_data;
- nand->ecc.hwctl = ndfc_enable_hwecc;
- nand->ecc.calculate = ndfc_calculate_ecc;
- nand->ecc.mode = NAND_ECC_HW;
- nand->ecc.size = 256;
- nand->ecc.bytes = 3;
- nand->ecc.strength = 1;
- nand->select_chip = ndfc_select_chip;
-
-#ifdef CONFIG_SYS_NAND_BUSWIDTH_16BIT
- nand->options |= NAND_BUSWIDTH_16;
-#endif
-
- nand->write_buf = ndfc_write_buf;
- nand->verify_buf = ndfc_verify_buf;
- nand->read_byte = ndfc_read_byte;
-
- chip++;
-
- return 0;
-}
diff --git a/qemu/roms/u-boot/drivers/mtd/nand/nomadik.c b/qemu/roms/u-boot/drivers/mtd/nand/nomadik.c
deleted file mode 100644
index a7cee5138..000000000
--- a/qemu/roms/u-boot/drivers/mtd/nand/nomadik.c
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- * (C) Copyright 2007 STMicroelectronics, <www.st.com>
- * (C) Copyright 2009 Alessandro Rubini <rubini@unipv.it>
- *
- * SPDX-License-Identifier: GPL-2.0+
- */
-
-#include <common.h>
-#include <nand.h>
-#include <asm/io.h>
-
-static inline int parity(int b) /* b is really a byte; returns 0 or ~0 */
-{
- __asm__ __volatile__(
- "eor %0, %0, %0, lsr #4\n\t"
- "eor %0, %0, %0, lsr #2\n\t"
- "eor %0, %0, %0, lsr #1\n\t"
- "ands %0, %0, #1\n\t"
- "subne %0, %0, #2\t"
- : "=r" (b) : "0" (b));
- return b;
-}
-
-/*
- * This is the ECC routine used in hardware, according to the manual.
- * HW claims to make the calculation but not the correction; so we must
- * recalculate the bytes for a comparison.
- */
-static int ecc512(const unsigned char *data, unsigned char *ecc)
-{
- int gpar = 0;
- int i, val, par;
- int pbits = 0; /* P8, P16, ... P2048 */
- int pprime = 0; /* P8', P16', ... P2048' */
- int lowbits; /* P1, P2, P4 and primes */
-
- for (i = 0; i < 512; i++) {
- par = parity((val = data[i]));
- gpar ^= val;
- pbits ^= (i & par);
- }
- /*
- * Ok, now gpar is global parity (xor of all bytes)
- * pbits are all the parity bits (non-prime ones)
- */
- par = parity(gpar);
- pprime = pbits ^ par;
- /* Put low bits in the right position for ecc[2] (bits 7..2) */
- lowbits = 0
- | (parity(gpar & 0xf0) & 0x80) /* P4 */
- | (parity(gpar & 0x0f) & 0x40) /* P4' */
- | (parity(gpar & 0xcc) & 0x20) /* P2 */
- | (parity(gpar & 0x33) & 0x10) /* P2' */
- | (parity(gpar & 0xaa) & 0x08) /* P1 */
- | (parity(gpar & 0x55) & 0x04); /* P1' */
-
- ecc[2] = ~(lowbits | ((pbits & 0x100) >> 7) | ((pprime & 0x100) >> 8));
- /* now intermix bits for ecc[1] (P1024..P128') and ecc[0] (P64..P8') */
- ecc[1] = ~( (pbits & 0x80) >> 0 | ((pprime & 0x80) >> 1)
- | ((pbits & 0x40) >> 1) | ((pprime & 0x40) >> 2)
- | ((pbits & 0x20) >> 2) | ((pprime & 0x20) >> 3)
- | ((pbits & 0x10) >> 3) | ((pprime & 0x10) >> 4));
-
- ecc[0] = ~( (pbits & 0x8) << 4 | ((pprime & 0x8) << 3)
- | ((pbits & 0x4) << 3) | ((pprime & 0x4) << 2)
- | ((pbits & 0x2) << 2) | ((pprime & 0x2) << 1)
- | ((pbits & 0x1) << 1) | ((pprime & 0x1) << 0));
- return 0;
-}
-
-/* This is the method in the chip->ecc field */
-static int nomadik_ecc_calculate(struct mtd_info *mtd, const uint8_t *dat,
- uint8_t *ecc_code)
-{
- return ecc512(dat, ecc_code);
-}
-
-static int nomadik_ecc_correct(struct mtd_info *mtd, uint8_t *dat,
- uint8_t *r_ecc, uint8_t *c_ecc)
-{
- struct nand_chip *chip = mtd->priv;
- uint32_t r, c, d, diff; /*read, calculated, xor of them */
-
- if (!memcmp(r_ecc, c_ecc, chip->ecc.bytes))
- return 0;
-
- /* Reorder the bytes into ascending-order 24 bits -- see manual */
- r = r_ecc[2] << 22 | r_ecc[1] << 14 | r_ecc[0] << 6 | r_ecc[2] >> 2;
- c = c_ecc[2] << 22 | c_ecc[1] << 14 | c_ecc[0] << 6 | c_ecc[2] >> 2;
- diff = (r ^ c) & ((1<<24)-1); /* use 24 bits only */
-
- /* If 12 bits are different, one per pair, it's correctable */
- if (((diff | (diff>>1)) & 0x555555) == 0x555555) {
- int bit = ((diff & 2) >> 1)
- | ((diff & 0x8) >> 2) | ((diff & 0x20) >> 3);
- int byte;
-
- d = diff >> 6; /* remove bit-order info */
- byte = ((d & 2) >> 1)
- | ((d & 0x8) >> 2) | ((d & 0x20) >> 3)
- | ((d & 0x80) >> 4) | ((d & 0x200) >> 5)
- | ((d & 0x800) >> 6) | ((d & 0x2000) >> 7)
- | ((d & 0x8000) >> 8) | ((d & 0x20000) >> 9);
- /* correct the single bit */
- dat[byte] ^= 1<<bit;
- return 0;
- }
- /* If 1 bit only differs, it's one bit error in ECC, ignore */
- if ((diff ^ (1 << (ffs(diff) - 1))) == 0)
- return 0;
- /* Otherwise, uncorrectable */
- return -1;
-}
-
-static void nomadik_ecc_hwctl(struct mtd_info *mtd, int mode)
-{ /* mandatory in the structure but not used here */ }
-
-
-/* This is the layout used by older installations, we keep compatible */
-struct nand_ecclayout nomadik_ecc_layout = {
- .eccbytes = 3 * 4,
- .eccpos = { /* each subpage has 16 bytes: pos 2,3,4 hosts ECC */
- 0x02, 0x03, 0x04,
- 0x12, 0x13, 0x14,
- 0x22, 0x23, 0x24,
- 0x32, 0x33, 0x34},
- .oobfree = { {0x08, 0x08}, {0x18, 0x08}, {0x28, 0x08}, {0x38, 0x08} },
-};
-
-#define MASK_ALE (1 << 24) /* our ALE is AD21 */
-#define MASK_CLE (1 << 23) /* our CLE is AD22 */
-
-/* This is copied from the AT91SAM9 devices (Stelian Pop, Lead Tech Design) */
-static void nomadik_nand_hwcontrol(struct mtd_info *mtd,
- int cmd, unsigned int ctrl)
-{
- struct nand_chip *this = mtd->priv;
- u32 pcr0 = readl(REG_FSMC_PCR0);
-
- if (ctrl & NAND_CTRL_CHANGE) {
- ulong IO_ADDR_W = (ulong) this->IO_ADDR_W;
- IO_ADDR_W &= ~(MASK_ALE | MASK_CLE);
-
- if (ctrl & NAND_CLE)
- IO_ADDR_W |= MASK_CLE;
- if (ctrl & NAND_ALE)
- IO_ADDR_W |= MASK_ALE;
-
- if (ctrl & NAND_NCE)
- writel(pcr0 | 0x4, REG_FSMC_PCR0);
- else
- writel(pcr0 & ~0x4, REG_FSMC_PCR0);
-
- this->IO_ADDR_W = (void *) IO_ADDR_W;
- this->IO_ADDR_R = (void *) IO_ADDR_W;
- }
-
- if (cmd != NAND_CMD_NONE)
- writeb(cmd, this->IO_ADDR_W);
-}
-
-/* Returns 1 when ready; upper layers timeout at 20ms with timer routines */
-static int nomadik_nand_ready(struct mtd_info *mtd)
-{
- return 1; /* The ready bit is handled in hardware */
-}
-
-/* Copy a buffer 32bits at a time: faster than defualt method which is 8bit */
-static void nomadik_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
-{
- int i;
- struct nand_chip *chip = mtd->priv;
- u32 *p = (u32 *) buf;
-
- len >>= 2;
- writel(0, REG_FSMC_ECCR0);
- for (i = 0; i < len; i++)
- p[i] = readl(chip->IO_ADDR_R);
-}
-
-int board_nand_init(struct nand_chip *chip)
-{
- /* Set up the FSMC_PCR0 for nand access*/
- writel(0x0000004a, REG_FSMC_PCR0);
- /* Set up FSMC_PMEM0, FSMC_PATT0 with timing data for access */
- writel(0x00020401, REG_FSMC_PMEM0);
- writel(0x00020404, REG_FSMC_PATT0);
-
- chip->options = NAND_COPYBACK | NAND_CACHEPRG | NAND_NO_PADDING;
- chip->cmd_ctrl = nomadik_nand_hwcontrol;
- chip->dev_ready = nomadik_nand_ready;
- /* The chip allows 32bit reads, so avoid the default 8bit copy */
- chip->read_buf = nomadik_nand_read_buf;
-
- /* ECC: follow the hardware-defined rulse, but do it in sw */
- chip->ecc.mode = NAND_ECC_HW;
- chip->ecc.bytes = 3;
- chip->ecc.size = 512;
- chip->ecc.strength = 1;
- chip->ecc.layout = &nomadik_ecc_layout;
- chip->ecc.calculate = nomadik_ecc_calculate;
- chip->ecc.hwctl = nomadik_ecc_hwctl;
- chip->ecc.correct = nomadik_ecc_correct;
-
- return 0;
-}
diff --git a/qemu/roms/u-boot/drivers/mtd/nand/omap_elm.c b/qemu/roms/u-boot/drivers/mtd/nand/omap_elm.c
deleted file mode 100644
index 47b1f1bfe..000000000
--- a/qemu/roms/u-boot/drivers/mtd/nand/omap_elm.c
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
- * (C) Copyright 2010-2011 Texas Instruments, <www.ti.com>
- * Mansoor Ahamed <mansoor.ahamed@ti.com>
- *
- * BCH Error Location Module (ELM) support.
- *
- * NOTE:
- * 1. Supports only continuous mode. Dont see need for page mode in uboot
- * 2. Supports only syndrome polynomial 0. i.e. poly local variable is
- * always set to ELM_DEFAULT_POLY. Dont see need for other polynomial
- * sets in uboot
- *
- * SPDX-License-Identifier: GPL-2.0+
- */
-
-#include <common.h>
-#include <asm/io.h>
-#include <asm/errno.h>
-#include <linux/mtd/omap_gpmc.h>
-#include <linux/mtd/omap_elm.h>
-#include <asm/arch/hardware.h>
-
-#define ELM_DEFAULT_POLY (0)
-
-struct elm *elm_cfg;
-
-/**
- * elm_load_syndromes - Load BCH syndromes based on nibble selection
- * @syndrome: BCH syndrome
- * @nibbles:
- * @poly: Syndrome Polynomial set to use
- *
- * Load BCH syndromes based on nibble selection
- */
-static void elm_load_syndromes(u8 *syndrome, u32 nibbles, u8 poly)
-{
- u32 *ptr;
- u32 val;
-
- /* reg 0 */
- ptr = &elm_cfg->syndrome_fragments[poly].syndrome_fragment_x[0];
- val = syndrome[0] | (syndrome[1] << 8) | (syndrome[2] << 16) |
- (syndrome[3] << 24);
- writel(val, ptr);
- /* reg 1 */
- ptr = &elm_cfg->syndrome_fragments[poly].syndrome_fragment_x[1];
- val = syndrome[4] | (syndrome[5] << 8) | (syndrome[6] << 16) |
- (syndrome[7] << 24);
- writel(val, ptr);
-
- /* BCH 8-bit with 26 nibbles (4*8=32) */
- if (nibbles > 13) {
- /* reg 2 */
- ptr = &elm_cfg->syndrome_fragments[poly].syndrome_fragment_x[2];
- val = syndrome[8] | (syndrome[9] << 8) | (syndrome[10] << 16) |
- (syndrome[11] << 24);
- writel(val, ptr);
- /* reg 3 */
- ptr = &elm_cfg->syndrome_fragments[poly].syndrome_fragment_x[3];
- val = syndrome[12] | (syndrome[13] << 8) |
- (syndrome[14] << 16) | (syndrome[15] << 24);
- writel(val, ptr);
- }
-
- /* BCH 16-bit with 52 nibbles (7*8=56) */
- if (nibbles > 26) {
- /* reg 4 */
- ptr = &elm_cfg->syndrome_fragments[poly].syndrome_fragment_x[4];
- val = syndrome[16] | (syndrome[17] << 8) |
- (syndrome[18] << 16) | (syndrome[19] << 24);
- writel(val, ptr);
-
- /* reg 5 */
- ptr = &elm_cfg->syndrome_fragments[poly].syndrome_fragment_x[5];
- val = syndrome[20] | (syndrome[21] << 8) |
- (syndrome[22] << 16) | (syndrome[23] << 24);
- writel(val, ptr);
-
- /* reg 6 */
- ptr = &elm_cfg->syndrome_fragments[poly].syndrome_fragment_x[6];
- val = syndrome[24] | (syndrome[25] << 8) |
- (syndrome[26] << 16) | (syndrome[27] << 24);
- writel(val, ptr);
- }
-}
-
-/**
- * elm_check_errors - Check for BCH errors and return error locations
- * @syndrome: BCH syndrome
- * @nibbles:
- * @error_count: Returns number of errrors in the syndrome
- * @error_locations: Returns error locations (in decimal) in this array
- *
- * Check the provided syndrome for BCH errors and return error count
- * and locations in the array passed. Returns -1 if error is not correctable,
- * else returns 0
- */
-int elm_check_error(u8 *syndrome, u32 nibbles, u32 *error_count,
- u32 *error_locations)
-{
- u8 poly = ELM_DEFAULT_POLY;
- s8 i;
- u32 location_status;
-
- elm_load_syndromes(syndrome, nibbles, poly);
-
- /* start processing */
- writel((readl(&elm_cfg->syndrome_fragments[poly].syndrome_fragment_x[6])
- | ELM_SYNDROME_FRAGMENT_6_SYNDROME_VALID),
- &elm_cfg->syndrome_fragments[poly].syndrome_fragment_x[6]);
-
- /* wait for processing to complete */
- while ((readl(&elm_cfg->irqstatus) & (0x1 << poly)) != 0x1)
- ;
- /* clear status */
- writel((readl(&elm_cfg->irqstatus) | (0x1 << poly)),
- &elm_cfg->irqstatus);
-
- /* check if correctable */
- location_status = readl(&elm_cfg->error_location[poly].location_status);
- if (!(location_status & ELM_LOCATION_STATUS_ECC_CORRECTABLE_MASK))
- return -1;
-
- /* get error count */
- *error_count = readl(&elm_cfg->error_location[poly].location_status) &
- ELM_LOCATION_STATUS_ECC_NB_ERRORS_MASK;
-
- for (i = 0; i < *error_count; i++) {
- error_locations[i] =
- readl(&elm_cfg->error_location[poly].error_location_x[i]);
- }
-
- return 0;
-}
-
-
-/**
- * elm_config - Configure ELM module
- * @level: 4 / 8 / 16 bit BCH
- *
- * Configure ELM module based on BCH level.
- * Set mode as continuous mode.
- * Currently we are using only syndrome 0 and syndromes 1 to 6 are not used.
- * Also, the mode is set only for syndrome 0
- */
-int elm_config(enum bch_level level)
-{
- u32 val;
- u8 poly = ELM_DEFAULT_POLY;
- u32 buffer_size = 0x7FF;
-
- /* config size and level */
- val = (u32)(level) & ELM_LOCATION_CONFIG_ECC_BCH_LEVEL_MASK;
- val |= ((buffer_size << ELM_LOCATION_CONFIG_ECC_SIZE_POS) &
- ELM_LOCATION_CONFIG_ECC_SIZE_MASK);
- writel(val, &elm_cfg->location_config);
-
- /* config continous mode */
- /* enable interrupt generation for syndrome polynomial set */
- writel((readl(&elm_cfg->irqenable) | (0x1 << poly)),
- &elm_cfg->irqenable);
- /* set continuous mode for the syndrome polynomial set */
- writel((readl(&elm_cfg->page_ctrl) & ~(0x1 << poly)),
- &elm_cfg->page_ctrl);
-
- return 0;
-}
-
-/**
- * elm_reset - Do a soft reset of ELM
- *
- * Perform a soft reset of ELM and return after reset is done.
- */
-void elm_reset(void)
-{
- /* initiate reset */
- writel((readl(&elm_cfg->sysconfig) | ELM_SYSCONFIG_SOFTRESET),
- &elm_cfg->sysconfig);
-
- /* wait for reset complete and normal operation */
- while ((readl(&elm_cfg->sysstatus) & ELM_SYSSTATUS_RESETDONE) !=
- ELM_SYSSTATUS_RESETDONE)
- ;
-}
-
-/**
- * elm_init - Initialize ELM module
- *
- * Initialize ELM support. Currently it does only base address init
- * and ELM reset.
- */
-void elm_init(void)
-{
- elm_cfg = (struct elm *)ELM_BASE;
- elm_reset();
-}
diff --git a/qemu/roms/u-boot/drivers/mtd/nand/omap_gpmc.c b/qemu/roms/u-boot/drivers/mtd/nand/omap_gpmc.c
deleted file mode 100644
index 881a63618..000000000
--- a/qemu/roms/u-boot/drivers/mtd/nand/omap_gpmc.c
+++ /dev/null
@@ -1,836 +0,0 @@
-/*
- * (C) Copyright 2004-2008 Texas Instruments, <www.ti.com>
- * Rohit Choraria <rohitkc@ti.com>
- *
- * SPDX-License-Identifier: GPL-2.0+
- */
-
-#include <common.h>
-#include <asm/io.h>
-#include <asm/errno.h>
-#include <asm/arch/mem.h>
-#include <linux/mtd/omap_gpmc.h>
-#include <linux/mtd/nand_ecc.h>
-#include <linux/bch.h>
-#include <linux/compiler.h>
-#include <nand.h>
-#include <linux/mtd/omap_elm.h>
-
-#define BADBLOCK_MARKER_LENGTH 2
-#define SECTOR_BYTES 512
-#define ECCCLEAR (0x1 << 8)
-#define ECCRESULTREG1 (0x1 << 0)
-/* 4 bit padding to make byte aligned, 56 = 52 + 4 */
-#define BCH4_BIT_PAD 4
-
-#ifdef CONFIG_BCH
-static u8 bch8_polynomial[] = {0xef, 0x51, 0x2e, 0x09, 0xed, 0x93, 0x9a, 0xc2,
- 0x97, 0x79, 0xe5, 0x24, 0xb5};
-#endif
-static uint8_t cs;
-static __maybe_unused struct nand_ecclayout omap_ecclayout;
-
-/*
- * omap_nand_hwcontrol - Set the address pointers corretly for the
- * following address/data/command operation
- */
-static void omap_nand_hwcontrol(struct mtd_info *mtd, int32_t cmd,
- uint32_t ctrl)
-{
- register struct nand_chip *this = mtd->priv;
-
- /*
- * Point the IO_ADDR to DATA and ADDRESS registers instead
- * of chip address
- */
- switch (ctrl) {
- case NAND_CTRL_CHANGE | NAND_CTRL_CLE:
- this->IO_ADDR_W = (void __iomem *)&gpmc_cfg->cs[cs].nand_cmd;
- break;
- case NAND_CTRL_CHANGE | NAND_CTRL_ALE:
- this->IO_ADDR_W = (void __iomem *)&gpmc_cfg->cs[cs].nand_adr;
- break;
- case NAND_CTRL_CHANGE | NAND_NCE:
- this->IO_ADDR_W = (void __iomem *)&gpmc_cfg->cs[cs].nand_dat;
- break;
- }
-
- if (cmd != NAND_CMD_NONE)
- writeb(cmd, this->IO_ADDR_W);
-}
-
-#ifdef CONFIG_SPL_BUILD
-/* Check wait pin as dev ready indicator */
-int omap_spl_dev_ready(struct mtd_info *mtd)
-{
- return gpmc_cfg->status & (1 << 8);
-}
-#endif
-
-
-/*
- * gen_true_ecc - This function will generate true ECC value, which
- * can be used when correcting data read from NAND flash memory core
- *
- * @ecc_buf: buffer to store ecc code
- *
- * @return: re-formatted ECC value
- */
-static uint32_t gen_true_ecc(uint8_t *ecc_buf)
-{
- return ecc_buf[0] | (ecc_buf[1] << 16) | ((ecc_buf[2] & 0xF0) << 20) |
- ((ecc_buf[2] & 0x0F) << 8);
-}
-
-/*
- * omap_correct_data - Compares the ecc read from nand spare area with ECC
- * registers values and corrects one bit error if it has occured
- * Further details can be had from OMAP TRM and the following selected links:
- * http://en.wikipedia.org/wiki/Hamming_code
- * http://www.cs.utexas.edu/users/plaxton/c/337/05f/slides/ErrorCorrection-4.pdf
- *
- * @mtd: MTD device structure
- * @dat: page data
- * @read_ecc: ecc read from nand flash
- * @calc_ecc: ecc read from ECC registers
- *
- * @return 0 if data is OK or corrected, else returns -1
- */
-static int __maybe_unused omap_correct_data(struct mtd_info *mtd, uint8_t *dat,
- uint8_t *read_ecc, uint8_t *calc_ecc)
-{
- uint32_t orig_ecc, new_ecc, res, hm;
- uint16_t parity_bits, byte;
- uint8_t bit;
-
- /* Regenerate the orginal ECC */
- orig_ecc = gen_true_ecc(read_ecc);
- new_ecc = gen_true_ecc(calc_ecc);
- /* Get the XOR of real ecc */
- res = orig_ecc ^ new_ecc;
- if (res) {
- /* Get the hamming width */
- hm = hweight32(res);
- /* Single bit errors can be corrected! */
- if (hm == 12) {
- /* Correctable data! */
- parity_bits = res >> 16;
- bit = (parity_bits & 0x7);
- byte = (parity_bits >> 3) & 0x1FF;
- /* Flip the bit to correct */
- dat[byte] ^= (0x1 << bit);
- } else if (hm == 1) {
- printf("Error: Ecc is wrong\n");
- /* ECC itself is corrupted */
- return 2;
- } else {
- /*
- * hm distance != parity pairs OR one, could mean 2 bit
- * error OR potentially be on a blank page..
- * orig_ecc: contains spare area data from nand flash.
- * new_ecc: generated ecc while reading data area.
- * Note: if the ecc = 0, all data bits from which it was
- * generated are 0xFF.
- * The 3 byte(24 bits) ecc is generated per 512byte
- * chunk of a page. If orig_ecc(from spare area)
- * is 0xFF && new_ecc(computed now from data area)=0x0,
- * this means that data area is 0xFF and spare area is
- * 0xFF. A sure sign of a erased page!
- */
- if ((orig_ecc == 0x0FFF0FFF) && (new_ecc == 0x00000000))
- return 0;
- printf("Error: Bad compare! failed\n");
- /* detected 2 bit error */
- return -1;
- }
- }
- return 0;
-}
-
-/*
- * Generic BCH interface
- */
-struct nand_bch_priv {
- uint8_t mode;
- uint8_t type;
- uint8_t nibbles;
- struct bch_control *control;
- enum omap_ecc ecc_scheme;
-};
-
-/* bch types */
-#define ECC_BCH4 0
-#define ECC_BCH8 1
-#define ECC_BCH16 2
-
-/* BCH nibbles for diff bch levels */
-#define ECC_BCH4_NIBBLES 13
-#define ECC_BCH8_NIBBLES 26
-#define ECC_BCH16_NIBBLES 52
-
-/*
- * This can be a single instance cause all current users have only one NAND
- * with nearly the same setup (BCH8, some with ELM and others with sw BCH
- * library).
- * When some users with other BCH strength will exists this have to change!
- */
-static __maybe_unused struct nand_bch_priv bch_priv = {
- .type = ECC_BCH8,
- .nibbles = ECC_BCH8_NIBBLES,
- .control = NULL
-};
-
-/*
- * omap_reverse_list - re-orders list elements in reverse order [internal]
- * @list: pointer to start of list
- * @length: length of list
-*/
-void omap_reverse_list(u8 *list, unsigned int length)
-{
- unsigned int i, j;
- unsigned int half_length = length / 2;
- u8 tmp;
- for (i = 0, j = length - 1; i < half_length; i++, j--) {
- tmp = list[i];
- list[i] = list[j];
- list[j] = tmp;
- }
-}
-
-/*
- * omap_enable_hwecc - configures GPMC as per ECC scheme before read/write
- * @mtd: MTD device structure
- * @mode: Read/Write mode
- */
-__maybe_unused
-static void omap_enable_hwecc(struct mtd_info *mtd, int32_t mode)
-{
- struct nand_chip *nand = mtd->priv;
- struct nand_bch_priv *bch = nand->priv;
- unsigned int dev_width = (nand->options & NAND_BUSWIDTH_16) ? 1 : 0;
- unsigned int ecc_algo = 0;
- unsigned int bch_type = 0;
- unsigned int eccsize1 = 0x00, eccsize0 = 0x00, bch_wrapmode = 0x00;
- u32 ecc_size_config_val = 0;
- u32 ecc_config_val = 0;
-
- /* configure GPMC for specific ecc-scheme */
- switch (bch->ecc_scheme) {
- case OMAP_ECC_HAM1_CODE_SW:
- return;
- case OMAP_ECC_HAM1_CODE_HW:
- ecc_algo = 0x0;
- bch_type = 0x0;
- bch_wrapmode = 0x00;
- eccsize0 = 0xFF;
- eccsize1 = 0xFF;
- break;
- case OMAP_ECC_BCH8_CODE_HW_DETECTION_SW:
- case OMAP_ECC_BCH8_CODE_HW:
- ecc_algo = 0x1;
- bch_type = 0x1;
- if (mode == NAND_ECC_WRITE) {
- bch_wrapmode = 0x01;
- eccsize0 = 0; /* extra bits in nibbles per sector */
- eccsize1 = 28; /* OOB bits in nibbles per sector */
- } else {
- bch_wrapmode = 0x01;
- eccsize0 = 26; /* ECC bits in nibbles per sector */
- eccsize1 = 2; /* non-ECC bits in nibbles per sector */
- }
- break;
- default:
- return;
- }
- /* Clear ecc and enable bits */
- writel(ECCCLEAR | ECCRESULTREG1, &gpmc_cfg->ecc_control);
- /* Configure ecc size for BCH */
- ecc_size_config_val = (eccsize1 << 22) | (eccsize0 << 12);
- writel(ecc_size_config_val, &gpmc_cfg->ecc_size_config);
-
- /* Configure device details for BCH engine */
- ecc_config_val = ((ecc_algo << 16) | /* HAM1 | BCHx */
- (bch_type << 12) | /* BCH4/BCH8/BCH16 */
- (bch_wrapmode << 8) | /* wrap mode */
- (dev_width << 7) | /* bus width */
- (0x0 << 4) | /* number of sectors */
- (cs << 1) | /* ECC CS */
- (0x1)); /* enable ECC */
- writel(ecc_config_val, &gpmc_cfg->ecc_config);
-}
-
-/*
- * omap_calculate_ecc - Read ECC result
- * @mtd: MTD structure
- * @dat: unused
- * @ecc_code: ecc_code buffer
- * Using noninverted ECC can be considered ugly since writing a blank
- * page ie. padding will clear the ECC bytes. This is no problem as
- * long nobody is trying to write data on the seemingly unused page.
- * Reading an erased page will produce an ECC mismatch between
- * generated and read ECC bytes that has to be dealt with separately.
- * E.g. if page is 0xFF (fresh erased), and if HW ECC engine within GPMC
- * is used, the result of read will be 0x0 while the ECC offsets of the
- * spare area will be 0xFF which will result in an ECC mismatch.
- */
-static int omap_calculate_ecc(struct mtd_info *mtd, const uint8_t *dat,
- uint8_t *ecc_code)
-{
- struct nand_chip *chip = mtd->priv;
- struct nand_bch_priv *bch = chip->priv;
- uint32_t *ptr, val = 0;
- int8_t i = 0, j;
-
- switch (bch->ecc_scheme) {
- case OMAP_ECC_HAM1_CODE_HW:
- val = readl(&gpmc_cfg->ecc1_result);
- ecc_code[0] = val & 0xFF;
- ecc_code[1] = (val >> 16) & 0xFF;
- ecc_code[2] = ((val >> 8) & 0x0F) | ((val >> 20) & 0xF0);
- break;
-#ifdef CONFIG_BCH
- case OMAP_ECC_BCH8_CODE_HW_DETECTION_SW:
-#endif
- case OMAP_ECC_BCH8_CODE_HW:
- ptr = &gpmc_cfg->bch_result_0_3[0].bch_result_x[3];
- val = readl(ptr);
- ecc_code[i++] = (val >> 0) & 0xFF;
- ptr--;
- for (j = 0; j < 3; j++) {
- val = readl(ptr);
- ecc_code[i++] = (val >> 24) & 0xFF;
- ecc_code[i++] = (val >> 16) & 0xFF;
- ecc_code[i++] = (val >> 8) & 0xFF;
- ecc_code[i++] = (val >> 0) & 0xFF;
- ptr--;
- }
- break;
- default:
- return -EINVAL;
- }
- /* ECC scheme specific syndrome customizations */
- switch (bch->ecc_scheme) {
- case OMAP_ECC_HAM1_CODE_HW:
- break;
-#ifdef CONFIG_BCH
- case OMAP_ECC_BCH8_CODE_HW_DETECTION_SW:
-
- for (i = 0; i < chip->ecc.bytes; i++)
- *(ecc_code + i) = *(ecc_code + i) ^
- bch8_polynomial[i];
- break;
-#endif
- case OMAP_ECC_BCH8_CODE_HW:
- ecc_code[chip->ecc.bytes - 1] = 0x00;
- break;
- default:
- return -EINVAL;
- }
- return 0;
-}
-
-#ifdef CONFIG_NAND_OMAP_ELM
-/*
- * omap_correct_data_bch - Compares the ecc read from nand spare area
- * with ECC registers values and corrects one bit error if it has occured
- *
- * @mtd: MTD device structure
- * @dat: page data
- * @read_ecc: ecc read from nand flash (ignored)
- * @calc_ecc: ecc read from ECC registers
- *
- * @return 0 if data is OK or corrected, else returns -1
- */
-static int omap_correct_data_bch(struct mtd_info *mtd, uint8_t *dat,
- uint8_t *read_ecc, uint8_t *calc_ecc)
-{
- struct nand_chip *chip = mtd->priv;
- struct nand_bch_priv *bch = chip->priv;
- uint32_t eccbytes = chip->ecc.bytes;
- uint32_t error_count = 0, error_max;
- uint32_t error_loc[8];
- uint32_t i, ecc_flag = 0;
- uint8_t count, err = 0;
- uint32_t byte_pos, bit_pos;
-
- /* check calculated ecc */
- for (i = 0; i < chip->ecc.bytes && !ecc_flag; i++) {
- if (calc_ecc[i] != 0x00)
- ecc_flag = 1;
- }
- if (!ecc_flag)
- return 0;
-
- /* check for whether its a erased-page */
- ecc_flag = 0;
- for (i = 0; i < chip->ecc.bytes && !ecc_flag; i++) {
- if (read_ecc[i] != 0xff)
- ecc_flag = 1;
- }
- if (!ecc_flag)
- return 0;
-
- /*
- * while reading ECC result we read it in big endian.
- * Hence while loading to ELM we have rotate to get the right endian.
- */
- switch (bch->ecc_scheme) {
- case OMAP_ECC_BCH8_CODE_HW:
- omap_reverse_list(calc_ecc, eccbytes - 1);
- break;
- default:
- return -EINVAL;
- }
- /* use elm module to check for errors */
- elm_config((enum bch_level)(bch->type));
- if (elm_check_error(calc_ecc, bch->nibbles, &error_count, error_loc)) {
- printf("nand: error: uncorrectable ECC errors\n");
- return -EINVAL;
- }
- /* correct bch error */
- for (count = 0; count < error_count; count++) {
- switch (bch->type) {
- case ECC_BCH8:
- /* 14th byte in ECC is reserved to match ROM layout */
- error_max = SECTOR_BYTES + (eccbytes - 1);
- break;
- default:
- return -EINVAL;
- }
- byte_pos = error_max - (error_loc[count] / 8) - 1;
- bit_pos = error_loc[count] % 8;
- if (byte_pos < SECTOR_BYTES) {
- dat[byte_pos] ^= 1 << bit_pos;
- printf("nand: bit-flip corrected @data=%d\n", byte_pos);
- } else if (byte_pos < error_max) {
- read_ecc[byte_pos - SECTOR_BYTES] = 1 << bit_pos;
- printf("nand: bit-flip corrected @oob=%d\n", byte_pos -
- SECTOR_BYTES);
- } else {
- err = -EBADMSG;
- printf("nand: error: invalid bit-flip location\n");
- }
- }
- return (err) ? err : error_count;
-}
-
-/**
- * omap_read_page_bch - hardware ecc based page read function
- * @mtd: mtd info structure
- * @chip: nand chip info structure
- * @buf: buffer to store read data
- * @oob_required: caller expects OOB data read to chip->oob_poi
- * @page: page number to read
- *
- */
-static int omap_read_page_bch(struct mtd_info *mtd, struct nand_chip *chip,
- uint8_t *buf, int oob_required, int page)
-{
- int i, eccsize = chip->ecc.size;
- int eccbytes = chip->ecc.bytes;
- int eccsteps = chip->ecc.steps;
- 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;
- uint8_t *oob = chip->oob_poi;
- uint32_t data_pos;
- uint32_t oob_pos;
-
- data_pos = 0;
- /* oob area start */
- oob_pos = (eccsize * eccsteps) + chip->ecc.layout->eccpos[0];
- oob += chip->ecc.layout->eccpos[0];
-
- for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize,
- oob += eccbytes) {
- chip->ecc.hwctl(mtd, NAND_ECC_READ);
- /* read data */
- chip->cmdfunc(mtd, NAND_CMD_RNDOUT, data_pos, page);
- chip->read_buf(mtd, p, eccsize);
-
- /* read respective ecc from oob area */
- chip->cmdfunc(mtd, NAND_CMD_RNDOUT, oob_pos, page);
- chip->read_buf(mtd, oob, eccbytes);
- /* read syndrome */
- chip->ecc.calculate(mtd, p, &ecc_calc[i]);
-
- data_pos += eccsize;
- oob_pos += eccbytes;
- }
-
- for (i = 0; i < chip->ecc.total; i++)
- ecc_code[i] = chip->oob_poi[eccpos[i]];
-
- eccsteps = chip->ecc.steps;
- p = buf;
-
- for (i = 0 ; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
- int stat;
-
- stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]);
- if (stat < 0)
- mtd->ecc_stats.failed++;
- else
- mtd->ecc_stats.corrected += stat;
- }
- return 0;
-}
-#endif /* CONFIG_NAND_OMAP_ELM */
-
-/*
- * OMAP3 BCH8 support (with BCH library)
- */
-#ifdef CONFIG_BCH
-/**
- * omap_correct_data_bch_sw - Decode received data and correct errors
- * @mtd: MTD device structure
- * @data: page data
- * @read_ecc: ecc read from nand flash
- * @calc_ecc: ecc read from HW ECC registers
- */
-static int omap_correct_data_bch_sw(struct mtd_info *mtd, u_char *data,
- u_char *read_ecc, u_char *calc_ecc)
-{
- int i, count;
- /* cannot correct more than 8 errors */
- unsigned int errloc[8];
- struct nand_chip *chip = mtd->priv;
- struct nand_bch_priv *chip_priv = chip->priv;
- struct bch_control *bch = chip_priv->control;
-
- count = decode_bch(bch, NULL, 512, read_ecc, calc_ecc, NULL, errloc);
- if (count > 0) {
- /* correct errors */
- for (i = 0; i < count; i++) {
- /* correct data only, not ecc bytes */
- if (errloc[i] < 8*512)
- data[errloc[i]/8] ^= 1 << (errloc[i] & 7);
- printf("corrected bitflip %u\n", errloc[i]);
-#ifdef DEBUG
- puts("read_ecc: ");
- /*
- * BCH8 have 13 bytes of ECC; BCH4 needs adoption
- * here!
- */
- for (i = 0; i < 13; i++)
- printf("%02x ", read_ecc[i]);
- puts("\n");
- puts("calc_ecc: ");
- for (i = 0; i < 13; i++)
- printf("%02x ", calc_ecc[i]);
- puts("\n");
-#endif
- }
- } else if (count < 0) {
- puts("ecc unrecoverable error\n");
- }
- return count;
-}
-
-/**
- * omap_free_bch - Release BCH ecc resources
- * @mtd: MTD device structure
- */
-static void __maybe_unused omap_free_bch(struct mtd_info *mtd)
-{
- struct nand_chip *chip = mtd->priv;
- struct nand_bch_priv *chip_priv = chip->priv;
- struct bch_control *bch = NULL;
-
- if (chip_priv)
- bch = chip_priv->control;
-
- if (bch) {
- free_bch(bch);
- chip_priv->control = NULL;
- }
-}
-#endif /* CONFIG_BCH */
-
-/**
- * omap_select_ecc_scheme - configures driver for particular ecc-scheme
- * @nand: NAND chip device structure
- * @ecc_scheme: ecc scheme to configure
- * @pagesize: number of main-area bytes per page of NAND device
- * @oobsize: number of OOB/spare bytes per page of NAND device
- */
-static int omap_select_ecc_scheme(struct nand_chip *nand,
- enum omap_ecc ecc_scheme, unsigned int pagesize, unsigned int oobsize) {
- struct nand_bch_priv *bch = nand->priv;
- struct nand_ecclayout *ecclayout = &omap_ecclayout;
- int eccsteps = pagesize / SECTOR_BYTES;
- int i;
-
- switch (ecc_scheme) {
- case OMAP_ECC_HAM1_CODE_SW:
- debug("nand: selected OMAP_ECC_HAM1_CODE_SW\n");
- /* For this ecc-scheme, ecc.bytes, ecc.layout, ... are
- * initialized in nand_scan_tail(), so just set ecc.mode */
- bch_priv.control = NULL;
- bch_priv.type = 0;
- nand->ecc.mode = NAND_ECC_SOFT;
- nand->ecc.layout = NULL;
- nand->ecc.size = 0;
- bch->ecc_scheme = OMAP_ECC_HAM1_CODE_SW;
- break;
-
- case OMAP_ECC_HAM1_CODE_HW:
- debug("nand: selected OMAP_ECC_HAM1_CODE_HW\n");
- /* check ecc-scheme requirements before updating ecc info */
- if ((3 * eccsteps) + BADBLOCK_MARKER_LENGTH > oobsize) {
- printf("nand: error: insufficient OOB: require=%d\n", (
- (3 * eccsteps) + BADBLOCK_MARKER_LENGTH));
- return -EINVAL;
- }
- bch_priv.control = NULL;
- bch_priv.type = 0;
- /* populate ecc specific fields */
- memset(&nand->ecc, 0, sizeof(struct nand_ecc_ctrl));
- nand->ecc.mode = NAND_ECC_HW;
- nand->ecc.strength = 1;
- nand->ecc.size = SECTOR_BYTES;
- nand->ecc.bytes = 3;
- nand->ecc.hwctl = omap_enable_hwecc;
- nand->ecc.correct = omap_correct_data;
- nand->ecc.calculate = omap_calculate_ecc;
- /* define ecc-layout */
- ecclayout->eccbytes = nand->ecc.bytes * eccsteps;
- for (i = 0; i < ecclayout->eccbytes; i++) {
- if (nand->options & NAND_BUSWIDTH_16)
- ecclayout->eccpos[i] = i + 2;
- else
- ecclayout->eccpos[i] = i + 1;
- }
- ecclayout->oobfree[0].offset = i + BADBLOCK_MARKER_LENGTH;
- ecclayout->oobfree[0].length = oobsize - ecclayout->eccbytes -
- BADBLOCK_MARKER_LENGTH;
- bch->ecc_scheme = OMAP_ECC_HAM1_CODE_HW;
- break;
-
- case OMAP_ECC_BCH8_CODE_HW_DETECTION_SW:
-#ifdef CONFIG_BCH
- debug("nand: selected OMAP_ECC_BCH8_CODE_HW_DETECTION_SW\n");
- /* check ecc-scheme requirements before updating ecc info */
- if ((13 * eccsteps) + BADBLOCK_MARKER_LENGTH > oobsize) {
- printf("nand: error: insufficient OOB: require=%d\n", (
- (13 * eccsteps) + BADBLOCK_MARKER_LENGTH));
- return -EINVAL;
- }
- /* check if BCH S/W library can be used for error detection */
- bch_priv.control = init_bch(13, 8, 0x201b);
- if (!bch_priv.control) {
- printf("nand: error: could not init_bch()\n");
- return -ENODEV;
- }
- bch_priv.type = ECC_BCH8;
- /* populate ecc specific fields */
- memset(&nand->ecc, 0, sizeof(struct nand_ecc_ctrl));
- nand->ecc.mode = NAND_ECC_HW;
- nand->ecc.strength = 8;
- nand->ecc.size = SECTOR_BYTES;
- nand->ecc.bytes = 13;
- nand->ecc.hwctl = omap_enable_hwecc;
- nand->ecc.correct = omap_correct_data_bch_sw;
- nand->ecc.calculate = omap_calculate_ecc;
- /* define ecc-layout */
- ecclayout->eccbytes = nand->ecc.bytes * eccsteps;
- ecclayout->eccpos[0] = BADBLOCK_MARKER_LENGTH;
- for (i = 1; i < ecclayout->eccbytes; i++) {
- if (i % nand->ecc.bytes)
- ecclayout->eccpos[i] =
- ecclayout->eccpos[i - 1] + 1;
- else
- ecclayout->eccpos[i] =
- ecclayout->eccpos[i - 1] + 2;
- }
- ecclayout->oobfree[0].offset = i + BADBLOCK_MARKER_LENGTH;
- ecclayout->oobfree[0].length = oobsize - ecclayout->eccbytes -
- BADBLOCK_MARKER_LENGTH;
- bch->ecc_scheme = OMAP_ECC_BCH8_CODE_HW_DETECTION_SW;
- break;
-#else
- printf("nand: error: CONFIG_BCH required for ECC\n");
- return -EINVAL;
-#endif
-
- case OMAP_ECC_BCH8_CODE_HW:
-#ifdef CONFIG_NAND_OMAP_ELM
- debug("nand: selected OMAP_ECC_BCH8_CODE_HW\n");
- /* check ecc-scheme requirements before updating ecc info */
- if ((14 * eccsteps) + BADBLOCK_MARKER_LENGTH > oobsize) {
- printf("nand: error: insufficient OOB: require=%d\n", (
- (14 * eccsteps) + BADBLOCK_MARKER_LENGTH));
- return -EINVAL;
- }
- /* intialize ELM for ECC error detection */
- elm_init();
- bch_priv.type = ECC_BCH8;
- /* populate ecc specific fields */
- memset(&nand->ecc, 0, sizeof(struct nand_ecc_ctrl));
- nand->ecc.mode = NAND_ECC_HW;
- nand->ecc.strength = 8;
- nand->ecc.size = SECTOR_BYTES;
- nand->ecc.bytes = 14;
- nand->ecc.hwctl = omap_enable_hwecc;
- nand->ecc.correct = omap_correct_data_bch;
- nand->ecc.calculate = omap_calculate_ecc;
- nand->ecc.read_page = omap_read_page_bch;
- /* define ecc-layout */
- ecclayout->eccbytes = nand->ecc.bytes * eccsteps;
- for (i = 0; i < ecclayout->eccbytes; i++)
- ecclayout->eccpos[i] = i + BADBLOCK_MARKER_LENGTH;
- ecclayout->oobfree[0].offset = i + BADBLOCK_MARKER_LENGTH;
- ecclayout->oobfree[0].length = oobsize - ecclayout->eccbytes -
- BADBLOCK_MARKER_LENGTH;
- bch->ecc_scheme = OMAP_ECC_BCH8_CODE_HW;
- break;
-#else
- printf("nand: error: CONFIG_NAND_OMAP_ELM required for ECC\n");
- return -EINVAL;
-#endif
-
- default:
- debug("nand: error: ecc scheme not enabled or supported\n");
- return -EINVAL;
- }
-
- /* nand_scan_tail() sets ham1 sw ecc; hw ecc layout is set by driver */
- if (ecc_scheme != OMAP_ECC_HAM1_CODE_SW)
- nand->ecc.layout = ecclayout;
-
- return 0;
-}
-
-#ifndef CONFIG_SPL_BUILD
-/*
- * omap_nand_switch_ecc - switch the ECC operation between different engines
- * (h/w and s/w) and different algorithms (hamming and BCHx)
- *
- * @hardware - true if one of the HW engines should be used
- * @eccstrength - the number of bits that could be corrected
- * (1 - hamming, 4 - BCH4, 8 - BCH8, 16 - BCH16)
- */
-int __maybe_unused omap_nand_switch_ecc(uint32_t hardware, uint32_t eccstrength)
-{
- struct nand_chip *nand;
- struct mtd_info *mtd;
- int err = 0;
-
- if (nand_curr_device < 0 ||
- nand_curr_device >= CONFIG_SYS_MAX_NAND_DEVICE ||
- !nand_info[nand_curr_device].name) {
- printf("nand: error: no NAND devices found\n");
- return -ENODEV;
- }
-
- mtd = &nand_info[nand_curr_device];
- nand = mtd->priv;
- nand->options |= NAND_OWN_BUFFERS;
- nand->options &= ~NAND_SUBPAGE_READ;
- /* Setup the ecc configurations again */
- if (hardware) {
- if (eccstrength == 1) {
- err = omap_select_ecc_scheme(nand,
- OMAP_ECC_HAM1_CODE_HW,
- mtd->writesize, mtd->oobsize);
- } else if (eccstrength == 8) {
- err = omap_select_ecc_scheme(nand,
- OMAP_ECC_BCH8_CODE_HW,
- mtd->writesize, mtd->oobsize);
- } else {
- printf("nand: error: unsupported ECC scheme\n");
- return -EINVAL;
- }
- } else {
- err = omap_select_ecc_scheme(nand, OMAP_ECC_HAM1_CODE_SW,
- mtd->writesize, mtd->oobsize);
- }
-
- /* Update NAND handling after ECC mode switch */
- if (!err)
- err = nand_scan_tail(mtd);
- return err;
-}
-#endif /* CONFIG_SPL_BUILD */
-
-/*
- * Board-specific NAND initialization. The following members of the
- * argument are board-specific:
- * - IO_ADDR_R: address to read the 8 I/O lines of the flash device
- * - IO_ADDR_W: address to write the 8 I/O lines of the flash device
- * - cmd_ctrl: hardwarespecific function for accesing control-lines
- * - waitfunc: hardwarespecific function for accesing device ready/busy line
- * - ecc.hwctl: function to enable (reset) hardware ecc generator
- * - ecc.mode: mode of ecc, see defines
- * - chip_delay: chip dependent delay for transfering data from array to
- * read regs (tR)
- * - options: various chip options. They can partly be set to inform
- * nand_scan about special functionality. See the defines for further
- * explanation
- */
-int board_nand_init(struct nand_chip *nand)
-{
- int32_t gpmc_config = 0;
- cs = 0;
- int err = 0;
- /*
- * xloader/Uboot's gpmc configuration would have configured GPMC for
- * nand type of memory. The following logic scans and latches on to the
- * first CS with NAND type memory.
- * TBD: need to make this logic generic to handle multiple CS NAND
- * devices.
- */
- while (cs < GPMC_MAX_CS) {
- /* Check if NAND type is set */
- if ((readl(&gpmc_cfg->cs[cs].config1) & 0xC00) == 0x800) {
- /* Found it!! */
- break;
- }
- cs++;
- }
- if (cs >= GPMC_MAX_CS) {
- printf("nand: error: Unable to find NAND settings in "
- "GPMC Configuration - quitting\n");
- return -ENODEV;
- }
-
- gpmc_config = readl(&gpmc_cfg->config);
- /* Disable Write protect */
- gpmc_config |= 0x10;
- writel(gpmc_config, &gpmc_cfg->config);
-
- nand->IO_ADDR_R = (void __iomem *)&gpmc_cfg->cs[cs].nand_dat;
- nand->IO_ADDR_W = (void __iomem *)&gpmc_cfg->cs[cs].nand_cmd;
- nand->priv = &bch_priv;
- nand->cmd_ctrl = omap_nand_hwcontrol;
- nand->options |= NAND_NO_PADDING | NAND_CACHEPRG;
- /* If we are 16 bit dev, our gpmc config tells us that */
- if ((readl(&gpmc_cfg->cs[cs].config1) & 0x3000) == 0x1000)
- nand->options |= NAND_BUSWIDTH_16;
-
- nand->chip_delay = 100;
- nand->ecc.layout = &omap_ecclayout;
-
- /* select ECC scheme */
-#if defined(CONFIG_NAND_OMAP_ECCSCHEME)
- err = omap_select_ecc_scheme(nand, CONFIG_NAND_OMAP_ECCSCHEME,
- CONFIG_SYS_NAND_PAGE_SIZE, CONFIG_SYS_NAND_OOBSIZE);
-#else
- /* pagesize and oobsize are not required to configure sw ecc-scheme */
- err = omap_select_ecc_scheme(nand, OMAP_ECC_HAM1_CODE_SW,
- 0, 0);
-#endif
- if (err)
- return err;
-
-#ifdef CONFIG_SPL_BUILD
- if (nand->options & NAND_BUSWIDTH_16)
- nand->read_buf = nand_read_buf16;
- else
- nand->read_buf = nand_read_buf;
- nand->dev_ready = omap_spl_dev_ready;
-#endif
-
- return 0;
-}
diff --git a/qemu/roms/u-boot/drivers/mtd/nand/s3c2410_nand.c b/qemu/roms/u-boot/drivers/mtd/nand/s3c2410_nand.c
deleted file mode 100644
index db87d0726..000000000
--- a/qemu/roms/u-boot/drivers/mtd/nand/s3c2410_nand.c
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- * (C) Copyright 2006 OpenMoko, Inc.
- * Author: Harald Welte <laforge@openmoko.org>
- *
- * SPDX-License-Identifier: GPL-2.0+
- */
-
-#include <common.h>
-
-#include <nand.h>
-#include <asm/arch/s3c24x0_cpu.h>
-#include <asm/io.h>
-
-#define S3C2410_NFCONF_EN (1<<15)
-#define S3C2410_NFCONF_512BYTE (1<<14)
-#define S3C2410_NFCONF_4STEP (1<<13)
-#define S3C2410_NFCONF_INITECC (1<<12)
-#define S3C2410_NFCONF_nFCE (1<<11)
-#define S3C2410_NFCONF_TACLS(x) ((x)<<8)
-#define S3C2410_NFCONF_TWRPH0(x) ((x)<<4)
-#define S3C2410_NFCONF_TWRPH1(x) ((x)<<0)
-
-#define S3C2410_ADDR_NALE 4
-#define S3C2410_ADDR_NCLE 8
-
-#ifdef CONFIG_NAND_SPL
-
-/* in the early stage of NAND flash booting, printf() is not available */
-#define printf(fmt, args...)
-
-static void nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
-{
- int i;
- struct nand_chip *this = mtd->priv;
-
- for (i = 0; i < len; i++)
- buf[i] = readb(this->IO_ADDR_R);
-}
-#endif
-
-static void s3c2410_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
-{
- struct nand_chip *chip = mtd->priv;
- struct s3c2410_nand *nand = s3c2410_get_base_nand();
-
- debug("hwcontrol(): 0x%02x 0x%02x\n", cmd, ctrl);
-
- if (ctrl & NAND_CTRL_CHANGE) {
- ulong IO_ADDR_W = (ulong)nand;
-
- if (!(ctrl & NAND_CLE))
- IO_ADDR_W |= S3C2410_ADDR_NCLE;
- if (!(ctrl & NAND_ALE))
- IO_ADDR_W |= S3C2410_ADDR_NALE;
-
- chip->IO_ADDR_W = (void *)IO_ADDR_W;
-
- if (ctrl & NAND_NCE)
- writel(readl(&nand->nfconf) & ~S3C2410_NFCONF_nFCE,
- &nand->nfconf);
- else
- writel(readl(&nand->nfconf) | S3C2410_NFCONF_nFCE,
- &nand->nfconf);
- }
-
- if (cmd != NAND_CMD_NONE)
- writeb(cmd, chip->IO_ADDR_W);
-}
-
-static int s3c2410_dev_ready(struct mtd_info *mtd)
-{
- struct s3c2410_nand *nand = s3c2410_get_base_nand();
- debug("dev_ready\n");
- return readl(&nand->nfstat) & 0x01;
-}
-
-#ifdef CONFIG_S3C2410_NAND_HWECC
-void s3c2410_nand_enable_hwecc(struct mtd_info *mtd, int mode)
-{
- struct s3c2410_nand *nand = s3c2410_get_base_nand();
- debug("s3c2410_nand_enable_hwecc(%p, %d)\n", mtd, mode);
- writel(readl(&nand->nfconf) | S3C2410_NFCONF_INITECC, &nand->nfconf);
-}
-
-static int s3c2410_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
- u_char *ecc_code)
-{
- struct s3c2410_nand *nand = s3c2410_get_base_nand();
- ecc_code[0] = readb(&nand->nfecc);
- ecc_code[1] = readb(&nand->nfecc + 1);
- ecc_code[2] = readb(&nand->nfecc + 2);
- debug("s3c2410_nand_calculate_hwecc(%p,): 0x%02x 0x%02x 0x%02x\n",
- mtd , ecc_code[0], ecc_code[1], ecc_code[2]);
-
- return 0;
-}
-
-static int s3c2410_nand_correct_data(struct mtd_info *mtd, u_char *dat,
- u_char *read_ecc, u_char *calc_ecc)
-{
- if (read_ecc[0] == calc_ecc[0] &&
- read_ecc[1] == calc_ecc[1] &&
- read_ecc[2] == calc_ecc[2])
- return 0;
-
- printf("s3c2410_nand_correct_data: not implemented\n");
- return -1;
-}
-#endif
-
-int board_nand_init(struct nand_chip *nand)
-{
- u_int32_t cfg;
- u_int8_t tacls, twrph0, twrph1;
- struct s3c24x0_clock_power *clk_power = s3c24x0_get_base_clock_power();
- struct s3c2410_nand *nand_reg = s3c2410_get_base_nand();
-
- debug("board_nand_init()\n");
-
- writel(readl(&clk_power->clkcon) | (1 << 4), &clk_power->clkcon);
-
- /* initialize hardware */
-#if defined(CONFIG_S3C24XX_CUSTOM_NAND_TIMING)
- tacls = CONFIG_S3C24XX_TACLS;
- twrph0 = CONFIG_S3C24XX_TWRPH0;
- twrph1 = CONFIG_S3C24XX_TWRPH1;
-#else
- tacls = 4;
- twrph0 = 8;
- twrph1 = 8;
-#endif
-
- cfg = S3C2410_NFCONF_EN;
- cfg |= S3C2410_NFCONF_TACLS(tacls - 1);
- cfg |= S3C2410_NFCONF_TWRPH0(twrph0 - 1);
- cfg |= S3C2410_NFCONF_TWRPH1(twrph1 - 1);
- writel(cfg, &nand_reg->nfconf);
-
- /* initialize nand_chip data structure */
- nand->IO_ADDR_R = (void *)&nand_reg->nfdata;
- nand->IO_ADDR_W = (void *)&nand_reg->nfdata;
-
- nand->select_chip = NULL;
-
- /* read_buf and write_buf are default */
- /* read_byte and write_byte are default */
-#ifdef CONFIG_NAND_SPL
- nand->read_buf = nand_read_buf;
-#endif
-
- /* hwcontrol always must be implemented */
- nand->cmd_ctrl = s3c2410_hwcontrol;
-
- nand->dev_ready = s3c2410_dev_ready;
-
-#ifdef CONFIG_S3C2410_NAND_HWECC
- nand->ecc.hwctl = s3c2410_nand_enable_hwecc;
- nand->ecc.calculate = s3c2410_nand_calculate_ecc;
- nand->ecc.correct = s3c2410_nand_correct_data;
- nand->ecc.mode = NAND_ECC_HW;
- nand->ecc.size = CONFIG_SYS_NAND_ECCSIZE;
- nand->ecc.bytes = CONFIG_SYS_NAND_ECCBYTES;
- nand->ecc.strength = 1;
-#else
- nand->ecc.mode = NAND_ECC_SOFT;
-#endif
-
-#ifdef CONFIG_S3C2410_NAND_BBT
- nand->bbt_options |= NAND_BBT_USE_FLASH;
-#endif
-
- debug("end of nand_init\n");
-
- return 0;
-}
diff --git a/qemu/roms/u-boot/drivers/mtd/nand/tegra_nand.c b/qemu/roms/u-boot/drivers/mtd/nand/tegra_nand.c
deleted file mode 100644
index 163cf29a3..000000000
--- a/qemu/roms/u-boot/drivers/mtd/nand/tegra_nand.c
+++ /dev/null
@@ -1,1041 +0,0 @@
-/*
- * Copyright (c) 2011 The Chromium OS Authors.
- * (C) Copyright 2011 NVIDIA Corporation <www.nvidia.com>
- * (C) Copyright 2006 Detlev Zundel, dzu@denx.de
- * (C) Copyright 2006 DENX Software Engineering
- *
- * SPDX-License-Identifier: GPL-2.0+
- */
-
-#include <common.h>
-#include <asm/io.h>
-#include <nand.h>
-#include <asm/arch/clock.h>
-#include <asm/arch/funcmux.h>
-#include <asm/arch-tegra/clk_rst.h>
-#include <asm/errno.h>
-#include <asm/gpio.h>
-#include <fdtdec.h>
-#include "tegra_nand.h"
-
-DECLARE_GLOBAL_DATA_PTR;
-
-#define NAND_CMD_TIMEOUT_MS 10
-
-#define SKIPPED_SPARE_BYTES 4
-
-/* ECC bytes to be generated for tag data */
-#define TAG_ECC_BYTES 4
-
-/* 64 byte oob block info for large page (== 2KB) device
- *
- * OOB flash layout for Tegra with Reed-Solomon 4 symbol correct ECC:
- * Skipped bytes(4)
- * Main area Ecc(36)
- * Tag data(20)
- * Tag data Ecc(4)
- *
- * Yaffs2 will use 16 tag bytes.
- */
-static struct nand_ecclayout eccoob = {
- .eccbytes = 36,
- .eccpos = {
- 4, 5, 6, 7, 8, 9, 10, 11, 12,
- 13, 14, 15, 16, 17, 18, 19, 20, 21,
- 22, 23, 24, 25, 26, 27, 28, 29, 30,
- 31, 32, 33, 34, 35, 36, 37, 38, 39,
- },
- .oobavail = 20,
- .oobfree = {
- {
- .offset = 40,
- .length = 20,
- },
- }
-};
-
-enum {
- ECC_OK,
- ECC_TAG_ERROR = 1 << 0,
- ECC_DATA_ERROR = 1 << 1
-};
-
-/* Timing parameters */
-enum {
- FDT_NAND_MAX_TRP_TREA,
- FDT_NAND_TWB,
- FDT_NAND_MAX_TCR_TAR_TRR,
- FDT_NAND_TWHR,
- FDT_NAND_MAX_TCS_TCH_TALS_TALH,
- FDT_NAND_TWH,
- FDT_NAND_TWP,
- FDT_NAND_TRH,
- FDT_NAND_TADL,
-
- FDT_NAND_TIMING_COUNT
-};
-
-/* Information about an attached NAND chip */
-struct fdt_nand {
- struct nand_ctlr *reg;
- int enabled; /* 1 to enable, 0 to disable */
- struct fdt_gpio_state wp_gpio; /* write-protect GPIO */
- s32 width; /* bit width, normally 8 */
- u32 timing[FDT_NAND_TIMING_COUNT];
-};
-
-struct nand_drv {
- struct nand_ctlr *reg;
-
- /*
- * When running in PIO mode to get READ ID bytes from register
- * RESP_0, we need this variable as an index to know which byte in
- * register RESP_0 should be read.
- * Because common code in nand_base.c invokes read_byte function two
- * times for NAND_CMD_READID.
- * And our controller returns 4 bytes at once in register RESP_0.
- */
- int pio_byte_index;
- struct fdt_nand config;
-};
-
-static struct nand_drv nand_ctrl;
-static struct mtd_info *our_mtd;
-static struct nand_chip nand_chip[CONFIG_SYS_MAX_NAND_DEVICE];
-
-#ifdef CONFIG_SYS_DCACHE_OFF
-static inline void dma_prepare(void *start, unsigned long length,
- int is_writing)
-{
-}
-#else
-/**
- * Prepare for a DMA transaction
- *
- * For a write we flush out our data. For a read we invalidate, since we
- * need to do this before we read from the buffer after the DMA has
- * completed, so may as well do it now.
- *
- * @param start Start address for DMA buffer (should be cache-aligned)
- * @param length Length of DMA buffer in bytes
- * @param is_writing 0 if reading, non-zero if writing
- */
-static void dma_prepare(void *start, unsigned long length, int is_writing)
-{
- unsigned long addr = (unsigned long)start;
-
- length = ALIGN(length, ARCH_DMA_MINALIGN);
- if (is_writing)
- flush_dcache_range(addr, addr + length);
- else
- invalidate_dcache_range(addr, addr + length);
-}
-#endif
-
-/**
- * Wait for command completion
- *
- * @param reg nand_ctlr structure
- * @return
- * 1 - Command completed
- * 0 - Timeout
- */
-static int nand_waitfor_cmd_completion(struct nand_ctlr *reg)
-{
- u32 reg_val;
- int running;
- int i;
-
- for (i = 0; i < NAND_CMD_TIMEOUT_MS * 1000; i++) {
- if ((readl(&reg->command) & CMD_GO) ||
- !(readl(&reg->status) & STATUS_RBSY0) ||
- !(readl(&reg->isr) & ISR_IS_CMD_DONE)) {
- udelay(1);
- continue;
- }
- reg_val = readl(&reg->dma_mst_ctrl);
- /*
- * If DMA_MST_CTRL_EN_A_ENABLE or DMA_MST_CTRL_EN_B_ENABLE
- * is set, that means DMA engine is running.
- *
- * Then we have to wait until DMA_MST_CTRL_IS_DMA_DONE
- * is cleared, indicating DMA transfer completion.
- */
- running = reg_val & (DMA_MST_CTRL_EN_A_ENABLE |
- DMA_MST_CTRL_EN_B_ENABLE);
- if (!running || (reg_val & DMA_MST_CTRL_IS_DMA_DONE))
- return 1;
- udelay(1);
- }
- return 0;
-}
-
-/**
- * Read one byte from the chip
- *
- * @param mtd MTD device structure
- * @return data byte
- *
- * Read function for 8bit bus-width
- */
-static uint8_t read_byte(struct mtd_info *mtd)
-{
- struct nand_chip *chip = mtd->priv;
- u32 dword_read;
- struct nand_drv *info;
-
- info = (struct nand_drv *)chip->priv;
-
- /* In PIO mode, only 4 bytes can be transferred with single CMD_GO. */
- if (info->pio_byte_index > 3) {
- info->pio_byte_index = 0;
- writel(CMD_GO | CMD_PIO
- | CMD_RX | CMD_CE0,
- &info->reg->command);
- if (!nand_waitfor_cmd_completion(info->reg))
- printf("Command timeout\n");
- }
-
- dword_read = readl(&info->reg->resp);
- dword_read = dword_read >> (8 * info->pio_byte_index);
- info->pio_byte_index++;
- return (uint8_t)dword_read;
-}
-
-/**
- * Read len bytes from the chip into a buffer
- *
- * @param mtd MTD device structure
- * @param buf buffer to store data to
- * @param len number of bytes to read
- *
- * Read function for 8bit bus-width
- */
-static void read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
-{
- int i, s;
- unsigned int reg;
- struct nand_chip *chip = mtd->priv;
- struct nand_drv *info = (struct nand_drv *)chip->priv;
-
- for (i = 0; i < len; i += 4) {
- s = (len - i) > 4 ? 4 : len - i;
- writel(CMD_PIO | CMD_RX | CMD_A_VALID | CMD_CE0 |
- ((s - 1) << CMD_TRANS_SIZE_SHIFT) | CMD_GO,
- &info->reg->command);
- if (!nand_waitfor_cmd_completion(info->reg))
- puts("Command timeout during read_buf\n");
- reg = readl(&info->reg->resp);
- memcpy(buf + i, &reg, s);
- }
-}
-
-/**
- * Check NAND status to see if it is ready or not
- *
- * @param mtd MTD device structure
- * @return
- * 1 - ready
- * 0 - not ready
- */
-static int nand_dev_ready(struct mtd_info *mtd)
-{
- struct nand_chip *chip = mtd->priv;
- int reg_val;
- struct nand_drv *info;
-
- info = (struct nand_drv *)chip->priv;
-
- reg_val = readl(&info->reg->status);
- if (reg_val & STATUS_RBSY0)
- return 1;
- else
- return 0;
-}
-
-/* Dummy implementation: we don't support multiple chips */
-static void nand_select_chip(struct mtd_info *mtd, int chipnr)
-{
- switch (chipnr) {
- case -1:
- case 0:
- break;
-
- default:
- BUG();
- }
-}
-
-/**
- * Clear all interrupt status bits
- *
- * @param reg nand_ctlr structure
- */
-static void nand_clear_interrupt_status(struct nand_ctlr *reg)
-{
- u32 reg_val;
-
- /* Clear interrupt status */
- reg_val = readl(&reg->isr);
- writel(reg_val, &reg->isr);
-}
-
-/**
- * Send command to NAND device
- *
- * @param mtd MTD device structure
- * @param command the command to be sent
- * @param column the column address for this command, -1 if none
- * @param page_addr the page address for this command, -1 if none
- */
-static void nand_command(struct mtd_info *mtd, unsigned int command,
- int column, int page_addr)
-{
- struct nand_chip *chip = mtd->priv;
- struct nand_drv *info;
-
- info = (struct nand_drv *)chip->priv;
-
- /*
- * Write out the command to the device.
- *
- * Only command NAND_CMD_RESET or NAND_CMD_READID will come
- * here before mtd->writesize is initialized.
- */
-
- /* Emulate NAND_CMD_READOOB */
- if (command == NAND_CMD_READOOB) {
- assert(mtd->writesize != 0);
- column += mtd->writesize;
- command = NAND_CMD_READ0;
- }
-
- /* Adjust columns for 16 bit bus-width */
- if (column != -1 && (chip->options & NAND_BUSWIDTH_16))
- column >>= 1;
-
- nand_clear_interrupt_status(info->reg);
-
- /* Stop DMA engine, clear DMA completion status */
- writel(DMA_MST_CTRL_EN_A_DISABLE
- | DMA_MST_CTRL_EN_B_DISABLE
- | DMA_MST_CTRL_IS_DMA_DONE,
- &info->reg->dma_mst_ctrl);
-
- /*
- * Program and erase have their own busy handlers
- * status and sequential in needs no delay
- */
- switch (command) {
- case NAND_CMD_READID:
- writel(NAND_CMD_READID, &info->reg->cmd_reg1);
- writel(column & 0xFF, &info->reg->addr_reg1);
- writel(CMD_GO | CMD_CLE | CMD_ALE | CMD_PIO
- | CMD_RX |
- ((4 - 1) << CMD_TRANS_SIZE_SHIFT)
- | CMD_CE0,
- &info->reg->command);
- info->pio_byte_index = 0;
- break;
- case NAND_CMD_PARAM:
- writel(NAND_CMD_PARAM, &info->reg->cmd_reg1);
- writel(column & 0xFF, &info->reg->addr_reg1);
- writel(CMD_GO | CMD_CLE | CMD_ALE | CMD_CE0,
- &info->reg->command);
- break;
- case NAND_CMD_READ0:
- writel(NAND_CMD_READ0, &info->reg->cmd_reg1);
- writel(NAND_CMD_READSTART, &info->reg->cmd_reg2);
- writel((page_addr << 16) | (column & 0xFFFF),
- &info->reg->addr_reg1);
- writel(page_addr >> 16, &info->reg->addr_reg2);
- return;
- case NAND_CMD_SEQIN:
- writel(NAND_CMD_SEQIN, &info->reg->cmd_reg1);
- writel(NAND_CMD_PAGEPROG, &info->reg->cmd_reg2);
- writel((page_addr << 16) | (column & 0xFFFF),
- &info->reg->addr_reg1);
- writel(page_addr >> 16,
- &info->reg->addr_reg2);
- return;
- case NAND_CMD_PAGEPROG:
- return;
- case NAND_CMD_ERASE1:
- writel(NAND_CMD_ERASE1, &info->reg->cmd_reg1);
- writel(NAND_CMD_ERASE2, &info->reg->cmd_reg2);
- writel(page_addr, &info->reg->addr_reg1);
- writel(CMD_GO | CMD_CLE | CMD_ALE |
- CMD_SEC_CMD | CMD_CE0 | CMD_ALE_BYTES3,
- &info->reg->command);
- break;
- case NAND_CMD_ERASE2:
- return;
- case NAND_CMD_STATUS:
- writel(NAND_CMD_STATUS, &info->reg->cmd_reg1);
- writel(CMD_GO | CMD_CLE | CMD_PIO | CMD_RX
- | ((1 - 0) << CMD_TRANS_SIZE_SHIFT)
- | CMD_CE0,
- &info->reg->command);
- info->pio_byte_index = 0;
- break;
- case NAND_CMD_RESET:
- writel(NAND_CMD_RESET, &info->reg->cmd_reg1);
- writel(CMD_GO | CMD_CLE | CMD_CE0,
- &info->reg->command);
- break;
- case NAND_CMD_RNDOUT:
- default:
- printf("%s: Unsupported command %d\n", __func__, command);
- return;
- }
- if (!nand_waitfor_cmd_completion(info->reg))
- printf("Command 0x%02X timeout\n", command);
-}
-
-/**
- * Check whether the pointed buffer are all 0xff (blank).
- *
- * @param buf data buffer for blank check
- * @param len length of the buffer in byte
- * @return
- * 1 - blank
- * 0 - non-blank
- */
-static int blank_check(u8 *buf, int len)
-{
- int i;
-
- for (i = 0; i < len; i++)
- if (buf[i] != 0xFF)
- return 0;
- return 1;
-}
-
-/**
- * After a DMA transfer for read, we call this function to see whether there
- * is any uncorrectable error on the pointed data buffer or oob buffer.
- *
- * @param reg nand_ctlr structure
- * @param databuf data buffer
- * @param a_len data buffer length
- * @param oobbuf oob buffer
- * @param b_len oob buffer length
- * @return
- * ECC_OK - no ECC error or correctable ECC error
- * ECC_TAG_ERROR - uncorrectable tag ECC error
- * ECC_DATA_ERROR - uncorrectable data ECC error
- * ECC_DATA_ERROR + ECC_TAG_ERROR - uncorrectable data+tag ECC error
- */
-static int check_ecc_error(struct nand_ctlr *reg, u8 *databuf,
- int a_len, u8 *oobbuf, int b_len)
-{
- int return_val = ECC_OK;
- u32 reg_val;
-
- if (!(readl(&reg->isr) & ISR_IS_ECC_ERR))
- return ECC_OK;
-
- /*
- * Area A is used for the data block (databuf). Area B is used for
- * the spare block (oobbuf)
- */
- reg_val = readl(&reg->dec_status);
- if ((reg_val & DEC_STATUS_A_ECC_FAIL) && databuf) {
- reg_val = readl(&reg->bch_dec_status_buf);
- /*
- * If uncorrectable error occurs on data area, then see whether
- * they are all FF. If all are FF, it's a blank page.
- * Not error.
- */
- if ((reg_val & BCH_DEC_STATUS_FAIL_SEC_FLAG_MASK) &&
- !blank_check(databuf, a_len))
- return_val |= ECC_DATA_ERROR;
- }
-
- if ((reg_val & DEC_STATUS_B_ECC_FAIL) && oobbuf) {
- reg_val = readl(&reg->bch_dec_status_buf);
- /*
- * If uncorrectable error occurs on tag area, then see whether
- * they are all FF. If all are FF, it's a blank page.
- * Not error.
- */
- if ((reg_val & BCH_DEC_STATUS_FAIL_TAG_MASK) &&
- !blank_check(oobbuf, b_len))
- return_val |= ECC_TAG_ERROR;
- }
-
- return return_val;
-}
-
-/**
- * Set GO bit to send command to device
- *
- * @param reg nand_ctlr structure
- */
-static void start_command(struct nand_ctlr *reg)
-{
- u32 reg_val;
-
- reg_val = readl(&reg->command);
- reg_val |= CMD_GO;
- writel(reg_val, &reg->command);
-}
-
-/**
- * Clear command GO bit, DMA GO bit, and DMA completion status
- *
- * @param reg nand_ctlr structure
- */
-static void stop_command(struct nand_ctlr *reg)
-{
- /* Stop command */
- writel(0, &reg->command);
-
- /* Stop DMA engine and clear DMA completion status */
- writel(DMA_MST_CTRL_GO_DISABLE
- | DMA_MST_CTRL_IS_DMA_DONE,
- &reg->dma_mst_ctrl);
-}
-
-/**
- * Set up NAND bus width and page size
- *
- * @param info nand_info structure
- * @param *reg_val address of reg_val
- * @return 0 if ok, -1 on error
- */
-static int set_bus_width_page_size(struct fdt_nand *config,
- u32 *reg_val)
-{
- if (config->width == 8)
- *reg_val = CFG_BUS_WIDTH_8BIT;
- else if (config->width == 16)
- *reg_val = CFG_BUS_WIDTH_16BIT;
- else {
- debug("%s: Unsupported bus width %d\n", __func__,
- config->width);
- return -1;
- }
-
- if (our_mtd->writesize == 512)
- *reg_val |= CFG_PAGE_SIZE_512;
- else if (our_mtd->writesize == 2048)
- *reg_val |= CFG_PAGE_SIZE_2048;
- else if (our_mtd->writesize == 4096)
- *reg_val |= CFG_PAGE_SIZE_4096;
- else {
- debug("%s: Unsupported page size %d\n", __func__,
- our_mtd->writesize);
- return -1;
- }
-
- return 0;
-}
-
-/**
- * Page read/write function
- *
- * @param mtd mtd info structure
- * @param chip nand chip info structure
- * @param buf data buffer
- * @param page page number
- * @param with_ecc 1 to enable ECC, 0 to disable ECC
- * @param is_writing 0 for read, 1 for write
- * @return 0 when successfully completed
- * -EIO when command timeout
- */
-static int nand_rw_page(struct mtd_info *mtd, struct nand_chip *chip,
- uint8_t *buf, int page, int with_ecc, int is_writing)
-{
- u32 reg_val;
- int tag_size;
- struct nand_oobfree *free = chip->ecc.layout->oobfree;
- /* 4*128=512 (byte) is the value that our HW can support. */
- ALLOC_CACHE_ALIGN_BUFFER(u32, tag_buf, 128);
- char *tag_ptr;
- struct nand_drv *info;
- struct fdt_nand *config;
-
- if ((uintptr_t)buf & 0x03) {
- printf("buf %p has to be 4-byte aligned\n", buf);
- return -EINVAL;
- }
-
- info = (struct nand_drv *)chip->priv;
- config = &info->config;
- if (set_bus_width_page_size(config, &reg_val))
- return -EINVAL;
-
- /* Need to be 4-byte aligned */
- tag_ptr = (char *)tag_buf;
-
- stop_command(info->reg);
-
- writel((1 << chip->page_shift) - 1, &info->reg->dma_cfg_a);
- writel(virt_to_phys(buf), &info->reg->data_block_ptr);
-
- if (with_ecc) {
- writel(virt_to_phys(tag_ptr), &info->reg->tag_ptr);
- if (is_writing)
- memcpy(tag_ptr, chip->oob_poi + free->offset,
- chip->ecc.layout->oobavail +
- TAG_ECC_BYTES);
- } else {
- writel(virt_to_phys(chip->oob_poi), &info->reg->tag_ptr);
- }
-
- /* Set ECC selection, configure ECC settings */
- if (with_ecc) {
- tag_size = chip->ecc.layout->oobavail + TAG_ECC_BYTES;
- reg_val |= (CFG_SKIP_SPARE_SEL_4
- | CFG_SKIP_SPARE_ENABLE
- | CFG_HW_ECC_CORRECTION_ENABLE
- | CFG_ECC_EN_TAG_DISABLE
- | CFG_HW_ECC_SEL_RS
- | CFG_HW_ECC_ENABLE
- | CFG_TVAL4
- | (tag_size - 1));
-
- if (!is_writing)
- tag_size += SKIPPED_SPARE_BYTES;
- dma_prepare(tag_ptr, tag_size, is_writing);
- } else {
- tag_size = mtd->oobsize;
- reg_val |= (CFG_SKIP_SPARE_DISABLE
- | CFG_HW_ECC_CORRECTION_DISABLE
- | CFG_ECC_EN_TAG_DISABLE
- | CFG_HW_ECC_DISABLE
- | (tag_size - 1));
- dma_prepare(chip->oob_poi, tag_size, is_writing);
- }
- writel(reg_val, &info->reg->config);
-
- dma_prepare(buf, 1 << chip->page_shift, is_writing);
-
- writel(BCH_CONFIG_BCH_ECC_DISABLE, &info->reg->bch_config);
-
- writel(tag_size - 1, &info->reg->dma_cfg_b);
-
- nand_clear_interrupt_status(info->reg);
-
- reg_val = CMD_CLE | CMD_ALE
- | CMD_SEC_CMD
- | (CMD_ALE_BYTES5 << CMD_ALE_BYTE_SIZE_SHIFT)
- | CMD_A_VALID
- | CMD_B_VALID
- | (CMD_TRANS_SIZE_PAGE << CMD_TRANS_SIZE_SHIFT)
- | CMD_CE0;
- if (!is_writing)
- reg_val |= (CMD_AFT_DAT_DISABLE | CMD_RX);
- else
- reg_val |= (CMD_AFT_DAT_ENABLE | CMD_TX);
- writel(reg_val, &info->reg->command);
-
- /* Setup DMA engine */
- reg_val = DMA_MST_CTRL_GO_ENABLE
- | DMA_MST_CTRL_BURST_8WORDS
- | DMA_MST_CTRL_EN_A_ENABLE
- | DMA_MST_CTRL_EN_B_ENABLE;
-
- if (!is_writing)
- reg_val |= DMA_MST_CTRL_DIR_READ;
- else
- reg_val |= DMA_MST_CTRL_DIR_WRITE;
-
- writel(reg_val, &info->reg->dma_mst_ctrl);
-
- start_command(info->reg);
-
- if (!nand_waitfor_cmd_completion(info->reg)) {
- if (!is_writing)
- printf("Read Page 0x%X timeout ", page);
- else
- printf("Write Page 0x%X timeout ", page);
- if (with_ecc)
- printf("with ECC");
- else
- printf("without ECC");
- printf("\n");
- return -EIO;
- }
-
- if (with_ecc && !is_writing) {
- memcpy(chip->oob_poi, tag_ptr,
- SKIPPED_SPARE_BYTES);
- memcpy(chip->oob_poi + free->offset,
- tag_ptr + SKIPPED_SPARE_BYTES,
- chip->ecc.layout->oobavail);
- reg_val = (u32)check_ecc_error(info->reg, (u8 *)buf,
- 1 << chip->page_shift,
- (u8 *)(tag_ptr + SKIPPED_SPARE_BYTES),
- chip->ecc.layout->oobavail);
- if (reg_val & ECC_TAG_ERROR)
- printf("Read Page 0x%X tag ECC error\n", page);
- if (reg_val & ECC_DATA_ERROR)
- printf("Read Page 0x%X data ECC error\n",
- page);
- if (reg_val & (ECC_DATA_ERROR | ECC_TAG_ERROR))
- return -EIO;
- }
- return 0;
-}
-
-/**
- * Hardware ecc based page read function
- *
- * @param mtd mtd info structure
- * @param chip nand chip info structure
- * @param buf buffer to store read data
- * @param page page number to read
- * @return 0 when successfully completed
- * -EIO when command timeout
- */
-static int nand_read_page_hwecc(struct mtd_info *mtd,
- struct nand_chip *chip, uint8_t *buf, int oob_required, int page)
-{
- return nand_rw_page(mtd, chip, buf, page, 1, 0);
-}
-
-/**
- * Hardware ecc based page write function
- *
- * @param mtd mtd info structure
- * @param chip nand chip info structure
- * @param buf data buffer
- */
-static int nand_write_page_hwecc(struct mtd_info *mtd,
- struct nand_chip *chip, const uint8_t *buf, int oob_required)
-{
- int page;
- struct nand_drv *info;
-
- info = (struct nand_drv *)chip->priv;
-
- page = (readl(&info->reg->addr_reg1) >> 16) |
- (readl(&info->reg->addr_reg2) << 16);
-
- nand_rw_page(mtd, chip, (uint8_t *)buf, page, 1, 1);
- return 0;
-}
-
-
-/**
- * Read raw page data without ecc
- *
- * @param mtd mtd info structure
- * @param chip nand chip info structure
- * @param buf buffer to store read data
- * @param page page number to read
- * @return 0 when successfully completed
- * -EINVAL when chip->oob_poi is not double-word aligned
- * -EIO when command timeout
- */
-static int nand_read_page_raw(struct mtd_info *mtd,
- struct nand_chip *chip, uint8_t *buf, int oob_required, int page)
-{
- return nand_rw_page(mtd, chip, buf, page, 0, 0);
-}
-
-/**
- * Raw page write function
- *
- * @param mtd mtd info structure
- * @param chip nand chip info structure
- * @param buf data buffer
- */
-static int nand_write_page_raw(struct mtd_info *mtd,
- struct nand_chip *chip, const uint8_t *buf, int oob_required)
-{
- int page;
- struct nand_drv *info;
-
- info = (struct nand_drv *)chip->priv;
- page = (readl(&info->reg->addr_reg1) >> 16) |
- (readl(&info->reg->addr_reg2) << 16);
-
- nand_rw_page(mtd, chip, (uint8_t *)buf, page, 0, 1);
- return 0;
-}
-
-/**
- * OOB data read/write function
- *
- * @param mtd mtd info structure
- * @param chip nand chip info structure
- * @param page page number to read
- * @param with_ecc 1 to enable ECC, 0 to disable ECC
- * @param is_writing 0 for read, 1 for write
- * @return 0 when successfully completed
- * -EINVAL when chip->oob_poi is not double-word aligned
- * -EIO when command timeout
- */
-static int nand_rw_oob(struct mtd_info *mtd, struct nand_chip *chip,
- int page, int with_ecc, int is_writing)
-{
- u32 reg_val;
- int tag_size;
- struct nand_oobfree *free = chip->ecc.layout->oobfree;
- struct nand_drv *info;
-
- if (((int)chip->oob_poi) & 0x03)
- return -EINVAL;
- info = (struct nand_drv *)chip->priv;
- if (set_bus_width_page_size(&info->config, &reg_val))
- return -EINVAL;
-
- stop_command(info->reg);
-
- writel(virt_to_phys(chip->oob_poi), &info->reg->tag_ptr);
-
- /* Set ECC selection */
- tag_size = mtd->oobsize;
- if (with_ecc)
- reg_val |= CFG_ECC_EN_TAG_ENABLE;
- else
- reg_val |= (CFG_ECC_EN_TAG_DISABLE);
-
- reg_val |= ((tag_size - 1) |
- CFG_SKIP_SPARE_DISABLE |
- CFG_HW_ECC_CORRECTION_DISABLE |
- CFG_HW_ECC_DISABLE);
- writel(reg_val, &info->reg->config);
-
- dma_prepare(chip->oob_poi, tag_size, is_writing);
-
- writel(BCH_CONFIG_BCH_ECC_DISABLE, &info->reg->bch_config);
-
- if (is_writing && with_ecc)
- tag_size -= TAG_ECC_BYTES;
-
- writel(tag_size - 1, &info->reg->dma_cfg_b);
-
- nand_clear_interrupt_status(info->reg);
-
- reg_val = CMD_CLE | CMD_ALE
- | CMD_SEC_CMD
- | (CMD_ALE_BYTES5 << CMD_ALE_BYTE_SIZE_SHIFT)
- | CMD_B_VALID
- | CMD_CE0;
- if (!is_writing)
- reg_val |= (CMD_AFT_DAT_DISABLE | CMD_RX);
- else
- reg_val |= (CMD_AFT_DAT_ENABLE | CMD_TX);
- writel(reg_val, &info->reg->command);
-
- /* Setup DMA engine */
- reg_val = DMA_MST_CTRL_GO_ENABLE
- | DMA_MST_CTRL_BURST_8WORDS
- | DMA_MST_CTRL_EN_B_ENABLE;
- if (!is_writing)
- reg_val |= DMA_MST_CTRL_DIR_READ;
- else
- reg_val |= DMA_MST_CTRL_DIR_WRITE;
-
- writel(reg_val, &info->reg->dma_mst_ctrl);
-
- start_command(info->reg);
-
- if (!nand_waitfor_cmd_completion(info->reg)) {
- if (!is_writing)
- printf("Read OOB of Page 0x%X timeout\n", page);
- else
- printf("Write OOB of Page 0x%X timeout\n", page);
- return -EIO;
- }
-
- if (with_ecc && !is_writing) {
- reg_val = (u32)check_ecc_error(info->reg, 0, 0,
- (u8 *)(chip->oob_poi + free->offset),
- chip->ecc.layout->oobavail);
- if (reg_val & ECC_TAG_ERROR)
- printf("Read OOB of Page 0x%X tag ECC error\n", page);
- }
- return 0;
-}
-
-/**
- * OOB data read function
- *
- * @param mtd mtd info structure
- * @param chip nand chip info structure
- * @param page page number to read
- */
-static int nand_read_oob(struct mtd_info *mtd, struct nand_chip *chip,
- int page)
-{
- chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page);
- nand_rw_oob(mtd, chip, page, 0, 0);
- return 0;
-}
-
-/**
- * OOB data write function
- *
- * @param mtd mtd info structure
- * @param chip nand chip info structure
- * @param page page number to write
- * @return 0 when successfully completed
- * -EINVAL when chip->oob_poi is not double-word aligned
- * -EIO when command timeout
- */
-static int nand_write_oob(struct mtd_info *mtd, struct nand_chip *chip,
- int page)
-{
- chip->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize, page);
-
- return nand_rw_oob(mtd, chip, page, 0, 1);
-}
-
-/**
- * Set up NAND memory timings according to the provided parameters
- *
- * @param timing Timing parameters
- * @param reg NAND controller register address
- */
-static void setup_timing(unsigned timing[FDT_NAND_TIMING_COUNT],
- struct nand_ctlr *reg)
-{
- u32 reg_val, clk_rate, clk_period, time_val;
-
- clk_rate = (u32)clock_get_periph_rate(PERIPH_ID_NDFLASH,
- CLOCK_ID_PERIPH) / 1000000;
- clk_period = 1000 / clk_rate;
- reg_val = ((timing[FDT_NAND_MAX_TRP_TREA] / clk_period) <<
- TIMING_TRP_RESP_CNT_SHIFT) & TIMING_TRP_RESP_CNT_MASK;
- reg_val |= ((timing[FDT_NAND_TWB] / clk_period) <<
- TIMING_TWB_CNT_SHIFT) & TIMING_TWB_CNT_MASK;
- time_val = timing[FDT_NAND_MAX_TCR_TAR_TRR] / clk_period;
- if (time_val > 2)
- reg_val |= ((time_val - 2) << TIMING_TCR_TAR_TRR_CNT_SHIFT) &
- TIMING_TCR_TAR_TRR_CNT_MASK;
- reg_val |= ((timing[FDT_NAND_TWHR] / clk_period) <<
- TIMING_TWHR_CNT_SHIFT) & TIMING_TWHR_CNT_MASK;
- time_val = timing[FDT_NAND_MAX_TCS_TCH_TALS_TALH] / clk_period;
- if (time_val > 1)
- reg_val |= ((time_val - 1) << TIMING_TCS_CNT_SHIFT) &
- TIMING_TCS_CNT_MASK;
- reg_val |= ((timing[FDT_NAND_TWH] / clk_period) <<
- TIMING_TWH_CNT_SHIFT) & TIMING_TWH_CNT_MASK;
- reg_val |= ((timing[FDT_NAND_TWP] / clk_period) <<
- TIMING_TWP_CNT_SHIFT) & TIMING_TWP_CNT_MASK;
- reg_val |= ((timing[FDT_NAND_TRH] / clk_period) <<
- TIMING_TRH_CNT_SHIFT) & TIMING_TRH_CNT_MASK;
- reg_val |= ((timing[FDT_NAND_MAX_TRP_TREA] / clk_period) <<
- TIMING_TRP_CNT_SHIFT) & TIMING_TRP_CNT_MASK;
- writel(reg_val, &reg->timing);
-
- reg_val = 0;
- time_val = timing[FDT_NAND_TADL] / clk_period;
- if (time_val > 2)
- reg_val = (time_val - 2) & TIMING2_TADL_CNT_MASK;
- writel(reg_val, &reg->timing2);
-}
-
-/**
- * Decode NAND parameters from the device tree
- *
- * @param blob Device tree blob
- * @param node Node containing "nand-flash" compatble node
- * @return 0 if ok, -ve on error (FDT_ERR_...)
- */
-static int fdt_decode_nand(const void *blob, int node, struct fdt_nand *config)
-{
- int err;
-
- config->reg = (struct nand_ctlr *)fdtdec_get_addr(blob, node, "reg");
- config->enabled = fdtdec_get_is_enabled(blob, node);
- config->width = fdtdec_get_int(blob, node, "nvidia,nand-width", 8);
- err = fdtdec_decode_gpio(blob, node, "nvidia,wp-gpios",
- &config->wp_gpio);
- if (err)
- return err;
- err = fdtdec_get_int_array(blob, node, "nvidia,timing",
- config->timing, FDT_NAND_TIMING_COUNT);
- if (err < 0)
- return err;
-
- /* Now look up the controller and decode that */
- node = fdt_next_node(blob, node, NULL);
- if (node < 0)
- return node;
-
- return 0;
-}
-
-/**
- * Board-specific NAND initialization
- *
- * @param nand nand chip info structure
- * @return 0, after initialized, -1 on error
- */
-int tegra_nand_init(struct nand_chip *nand, int devnum)
-{
- struct nand_drv *info = &nand_ctrl;
- struct fdt_nand *config = &info->config;
- int node, ret;
-
- node = fdtdec_next_compatible(gd->fdt_blob, 0,
- COMPAT_NVIDIA_TEGRA20_NAND);
- if (node < 0)
- return -1;
- if (fdt_decode_nand(gd->fdt_blob, node, config)) {
- printf("Could not decode nand-flash in device tree\n");
- return -1;
- }
- if (!config->enabled)
- return -1;
- info->reg = config->reg;
- nand->ecc.mode = NAND_ECC_HW;
- nand->ecc.layout = &eccoob;
-
- nand->options = LP_OPTIONS;
- nand->cmdfunc = nand_command;
- nand->read_byte = read_byte;
- nand->read_buf = read_buf;
- nand->ecc.read_page = nand_read_page_hwecc;
- nand->ecc.write_page = nand_write_page_hwecc;
- nand->ecc.read_page_raw = nand_read_page_raw;
- nand->ecc.write_page_raw = nand_write_page_raw;
- nand->ecc.read_oob = nand_read_oob;
- nand->ecc.write_oob = nand_write_oob;
- nand->ecc.strength = 1;
- nand->select_chip = nand_select_chip;
- nand->dev_ready = nand_dev_ready;
- nand->priv = &nand_ctrl;
-
- /* Adjust controller clock rate */
- clock_start_periph_pll(PERIPH_ID_NDFLASH, CLOCK_ID_PERIPH, 52000000);
-
- /* Adjust timing for NAND device */
- setup_timing(config->timing, info->reg);
-
- fdtdec_setup_gpio(&config->wp_gpio);
- gpio_direction_output(config->wp_gpio.gpio, 1);
-
- our_mtd = &nand_info[devnum];
- our_mtd->priv = nand;
- ret = nand_scan_ident(our_mtd, CONFIG_SYS_NAND_MAX_CHIPS, NULL);
- if (ret)
- return ret;
-
- nand->ecc.size = our_mtd->writesize;
- nand->ecc.bytes = our_mtd->oobsize;
-
- ret = nand_scan_tail(our_mtd);
- if (ret)
- return ret;
-
- ret = nand_register(devnum);
- if (ret)
- return ret;
-
- return 0;
-}
-
-void board_nand_init(void)
-{
- struct nand_chip *nand = &nand_chip[0];
-
- if (tegra_nand_init(nand, 0))
- puts("Tegra NAND init failed\n");
-}
diff --git a/qemu/roms/u-boot/drivers/mtd/nand/tegra_nand.h b/qemu/roms/u-boot/drivers/mtd/nand/tegra_nand.h
deleted file mode 100644
index ded9d7104..000000000
--- a/qemu/roms/u-boot/drivers/mtd/nand/tegra_nand.h
+++ /dev/null
@@ -1,241 +0,0 @@
-/*
- * (C) Copyright 2011 NVIDIA Corporation <www.nvidia.com>
- *
- * SPDX-License-Identifier: GPL-2.0+
- */
-
-/* register offset */
-#define COMMAND_0 0x00
-#define CMD_GO (1 << 31)
-#define CMD_CLE (1 << 30)
-#define CMD_ALE (1 << 29)
-#define CMD_PIO (1 << 28)
-#define CMD_TX (1 << 27)
-#define CMD_RX (1 << 26)
-#define CMD_SEC_CMD (1 << 25)
-#define CMD_AFT_DAT_MASK (1 << 24)
-#define CMD_AFT_DAT_DISABLE 0
-#define CMD_AFT_DAT_ENABLE (1 << 24)
-#define CMD_TRANS_SIZE_SHIFT 20
-#define CMD_TRANS_SIZE_PAGE 8
-#define CMD_A_VALID (1 << 19)
-#define CMD_B_VALID (1 << 18)
-#define CMD_RD_STATUS_CHK (1 << 17)
-#define CMD_R_BSY_CHK (1 << 16)
-#define CMD_CE7 (1 << 15)
-#define CMD_CE6 (1 << 14)
-#define CMD_CE5 (1 << 13)
-#define CMD_CE4 (1 << 12)
-#define CMD_CE3 (1 << 11)
-#define CMD_CE2 (1 << 10)
-#define CMD_CE1 (1 << 9)
-#define CMD_CE0 (1 << 8)
-#define CMD_CLE_BYTE_SIZE_SHIFT 4
-enum {
- CMD_CLE_BYTES1 = 0,
- CMD_CLE_BYTES2,
- CMD_CLE_BYTES3,
- CMD_CLE_BYTES4,
-};
-#define CMD_ALE_BYTE_SIZE_SHIFT 0
-enum {
- CMD_ALE_BYTES1 = 0,
- CMD_ALE_BYTES2,
- CMD_ALE_BYTES3,
- CMD_ALE_BYTES4,
- CMD_ALE_BYTES5,
- CMD_ALE_BYTES6,
- CMD_ALE_BYTES7,
- CMD_ALE_BYTES8
-};
-
-#define STATUS_0 0x04
-#define STATUS_RBSY0 (1 << 8)
-
-#define ISR_0 0x08
-#define ISR_IS_CMD_DONE (1 << 5)
-#define ISR_IS_ECC_ERR (1 << 4)
-
-#define IER_0 0x0C
-
-#define CFG_0 0x10
-#define CFG_HW_ECC_MASK (1 << 31)
-#define CFG_HW_ECC_DISABLE 0
-#define CFG_HW_ECC_ENABLE (1 << 31)
-#define CFG_HW_ECC_SEL_MASK (1 << 30)
-#define CFG_HW_ECC_SEL_HAMMING 0
-#define CFG_HW_ECC_SEL_RS (1 << 30)
-#define CFG_HW_ECC_CORRECTION_MASK (1 << 29)
-#define CFG_HW_ECC_CORRECTION_DISABLE 0
-#define CFG_HW_ECC_CORRECTION_ENABLE (1 << 29)
-#define CFG_PIPELINE_EN_MASK (1 << 28)
-#define CFG_PIPELINE_EN_DISABLE 0
-#define CFG_PIPELINE_EN_ENABLE (1 << 28)
-#define CFG_ECC_EN_TAG_MASK (1 << 27)
-#define CFG_ECC_EN_TAG_DISABLE 0
-#define CFG_ECC_EN_TAG_ENABLE (1 << 27)
-#define CFG_TVALUE_MASK (3 << 24)
-enum {
- CFG_TVAL4 = 0 << 24,
- CFG_TVAL6 = 1 << 24,
- CFG_TVAL8 = 2 << 24
-};
-#define CFG_SKIP_SPARE_MASK (1 << 23)
-#define CFG_SKIP_SPARE_DISABLE 0
-#define CFG_SKIP_SPARE_ENABLE (1 << 23)
-#define CFG_COM_BSY_MASK (1 << 22)
-#define CFG_COM_BSY_DISABLE 0
-#define CFG_COM_BSY_ENABLE (1 << 22)
-#define CFG_BUS_WIDTH_MASK (1 << 21)
-#define CFG_BUS_WIDTH_8BIT 0
-#define CFG_BUS_WIDTH_16BIT (1 << 21)
-#define CFG_LPDDR1_MODE_MASK (1 << 20)
-#define CFG_LPDDR1_MODE_DISABLE 0
-#define CFG_LPDDR1_MODE_ENABLE (1 << 20)
-#define CFG_EDO_MODE_MASK (1 << 19)
-#define CFG_EDO_MODE_DISABLE 0
-#define CFG_EDO_MODE_ENABLE (1 << 19)
-#define CFG_PAGE_SIZE_SEL_MASK (7 << 16)
-enum {
- CFG_PAGE_SIZE_256 = 0 << 16,
- CFG_PAGE_SIZE_512 = 1 << 16,
- CFG_PAGE_SIZE_1024 = 2 << 16,
- CFG_PAGE_SIZE_2048 = 3 << 16,
- CFG_PAGE_SIZE_4096 = 4 << 16
-};
-#define CFG_SKIP_SPARE_SEL_MASK (3 << 14)
-enum {
- CFG_SKIP_SPARE_SEL_4 = 0 << 14,
- CFG_SKIP_SPARE_SEL_8 = 1 << 14,
- CFG_SKIP_SPARE_SEL_12 = 2 << 14,
- CFG_SKIP_SPARE_SEL_16 = 3 << 14
-};
-#define CFG_TAG_BYTE_SIZE_MASK 0x1FF
-
-#define TIMING_0 0x14
-#define TIMING_TRP_RESP_CNT_SHIFT 28
-#define TIMING_TRP_RESP_CNT_MASK (0xf << TIMING_TRP_RESP_CNT_SHIFT)
-#define TIMING_TWB_CNT_SHIFT 24
-#define TIMING_TWB_CNT_MASK (0xf << TIMING_TWB_CNT_SHIFT)
-#define TIMING_TCR_TAR_TRR_CNT_SHIFT 20
-#define TIMING_TCR_TAR_TRR_CNT_MASK (0xf << TIMING_TCR_TAR_TRR_CNT_SHIFT)
-#define TIMING_TWHR_CNT_SHIFT 16
-#define TIMING_TWHR_CNT_MASK (0xf << TIMING_TWHR_CNT_SHIFT)
-#define TIMING_TCS_CNT_SHIFT 14
-#define TIMING_TCS_CNT_MASK (3 << TIMING_TCS_CNT_SHIFT)
-#define TIMING_TWH_CNT_SHIFT 12
-#define TIMING_TWH_CNT_MASK (3 << TIMING_TWH_CNT_SHIFT)
-#define TIMING_TWP_CNT_SHIFT 8
-#define TIMING_TWP_CNT_MASK (0xf << TIMING_TWP_CNT_SHIFT)
-#define TIMING_TRH_CNT_SHIFT 4
-#define TIMING_TRH_CNT_MASK (3 << TIMING_TRH_CNT_SHIFT)
-#define TIMING_TRP_CNT_SHIFT 0
-#define TIMING_TRP_CNT_MASK (0xf << TIMING_TRP_CNT_SHIFT)
-
-#define RESP_0 0x18
-
-#define TIMING2_0 0x1C
-#define TIMING2_TADL_CNT_SHIFT 0
-#define TIMING2_TADL_CNT_MASK (0xf << TIMING2_TADL_CNT_SHIFT)
-
-#define CMD_REG1_0 0x20
-#define CMD_REG2_0 0x24
-#define ADDR_REG1_0 0x28
-#define ADDR_REG2_0 0x2C
-
-#define DMA_MST_CTRL_0 0x30
-#define DMA_MST_CTRL_GO_MASK (1 << 31)
-#define DMA_MST_CTRL_GO_DISABLE 0
-#define DMA_MST_CTRL_GO_ENABLE (1 << 31)
-#define DMA_MST_CTRL_DIR_MASK (1 << 30)
-#define DMA_MST_CTRL_DIR_READ 0
-#define DMA_MST_CTRL_DIR_WRITE (1 << 30)
-#define DMA_MST_CTRL_PERF_EN_MASK (1 << 29)
-#define DMA_MST_CTRL_PERF_EN_DISABLE 0
-#define DMA_MST_CTRL_PERF_EN_ENABLE (1 << 29)
-#define DMA_MST_CTRL_REUSE_BUFFER_MASK (1 << 27)
-#define DMA_MST_CTRL_REUSE_BUFFER_DISABLE 0
-#define DMA_MST_CTRL_REUSE_BUFFER_ENABLE (1 << 27)
-#define DMA_MST_CTRL_BURST_SIZE_SHIFT 24
-#define DMA_MST_CTRL_BURST_SIZE_MASK (7 << DMA_MST_CTRL_BURST_SIZE_SHIFT)
-enum {
- DMA_MST_CTRL_BURST_1WORDS = 2 << DMA_MST_CTRL_BURST_SIZE_SHIFT,
- DMA_MST_CTRL_BURST_4WORDS = 3 << DMA_MST_CTRL_BURST_SIZE_SHIFT,
- DMA_MST_CTRL_BURST_8WORDS = 4 << DMA_MST_CTRL_BURST_SIZE_SHIFT,
- DMA_MST_CTRL_BURST_16WORDS = 5 << DMA_MST_CTRL_BURST_SIZE_SHIFT
-};
-#define DMA_MST_CTRL_IS_DMA_DONE (1 << 20)
-#define DMA_MST_CTRL_EN_A_MASK (1 << 2)
-#define DMA_MST_CTRL_EN_A_DISABLE 0
-#define DMA_MST_CTRL_EN_A_ENABLE (1 << 2)
-#define DMA_MST_CTRL_EN_B_MASK (1 << 1)
-#define DMA_MST_CTRL_EN_B_DISABLE 0
-#define DMA_MST_CTRL_EN_B_ENABLE (1 << 1)
-
-#define DMA_CFG_A_0 0x34
-#define DMA_CFG_B_0 0x38
-#define FIFO_CTRL_0 0x3C
-#define DATA_BLOCK_PTR_0 0x40
-#define TAG_PTR_0 0x44
-#define ECC_PTR_0 0x48
-
-#define DEC_STATUS_0 0x4C
-#define DEC_STATUS_A_ECC_FAIL (1 << 1)
-#define DEC_STATUS_B_ECC_FAIL (1 << 0)
-
-#define BCH_CONFIG_0 0xCC
-#define BCH_CONFIG_BCH_TVALUE_SHIFT 4
-#define BCH_CONFIG_BCH_TVALUE_MASK (3 << BCH_CONFIG_BCH_TVALUE_SHIFT)
-enum {
- BCH_CONFIG_BCH_TVAL4 = 0 << BCH_CONFIG_BCH_TVALUE_SHIFT,
- BCH_CONFIG_BCH_TVAL8 = 1 << BCH_CONFIG_BCH_TVALUE_SHIFT,
- BCH_CONFIG_BCH_TVAL14 = 2 << BCH_CONFIG_BCH_TVALUE_SHIFT,
- BCH_CONFIG_BCH_TVAL16 = 3 << BCH_CONFIG_BCH_TVALUE_SHIFT
-};
-#define BCH_CONFIG_BCH_ECC_MASK (1 << 0)
-#define BCH_CONFIG_BCH_ECC_DISABLE 0
-#define BCH_CONFIG_BCH_ECC_ENABLE (1 << 0)
-
-#define BCH_DEC_RESULT_0 0xD0
-#define BCH_DEC_RESULT_CORRFAIL_ERR_MASK (1 << 8)
-#define BCH_DEC_RESULT_PAGE_COUNT_MASK 0xFF
-
-#define BCH_DEC_STATUS_BUF_0 0xD4
-#define BCH_DEC_STATUS_FAIL_SEC_FLAG_MASK 0xFF000000
-#define BCH_DEC_STATUS_CORR_SEC_FLAG_MASK 0x00FF0000
-#define BCH_DEC_STATUS_FAIL_TAG_MASK (1 << 14)
-#define BCH_DEC_STATUS_CORR_TAG_MASK (1 << 13)
-#define BCH_DEC_STATUS_MAX_CORR_CNT_MASK (0x1f << 8)
-#define BCH_DEC_STATUS_PAGE_NUMBER_MASK 0xFF
-
-#define LP_OPTIONS 0
-
-struct nand_ctlr {
- u32 command; /* offset 00h */
- u32 status; /* offset 04h */
- u32 isr; /* offset 08h */
- u32 ier; /* offset 0Ch */
- u32 config; /* offset 10h */
- u32 timing; /* offset 14h */
- u32 resp; /* offset 18h */
- u32 timing2; /* offset 1Ch */
- u32 cmd_reg1; /* offset 20h */
- u32 cmd_reg2; /* offset 24h */
- u32 addr_reg1; /* offset 28h */
- u32 addr_reg2; /* offset 2Ch */
- u32 dma_mst_ctrl; /* offset 30h */
- u32 dma_cfg_a; /* offset 34h */
- u32 dma_cfg_b; /* offset 38h */
- u32 fifo_ctrl; /* offset 3Ch */
- u32 data_block_ptr; /* offset 40h */
- u32 tag_ptr; /* offset 44h */
- u32 resv1; /* offset 48h */
- u32 dec_status; /* offset 4Ch */
- u32 hwstatus_cmd; /* offset 50h */
- u32 hwstatus_mask; /* offset 54h */
- u32 resv2[29];
- u32 bch_config; /* offset CCh */
- u32 bch_dec_result; /* offset D0h */
- u32 bch_dec_status_buf;
- /* offset D4h */
-};