RFC on large number of hacks in mtd core files
Mason
slash.tmp at free.fr
Fri Jan 22 07:34:58 PST 2016
Hello everyone,
As I've mentioned in a previous thread, I'm supposed to port a NAND
controller driver from 3.4 to 4.4. But this is complicated by the
fact that several core files have been modified along the way.
Here's the full picture:
$ git diff --stat v3.4.39 custom-3.4 drivers/mtd
drivers/mtd/Kconfig | 15 +-
drivers/mtd/chips/cfi_cmdset_0002.c | 129 ++-
drivers/mtd/devices/Kconfig | 6 +
drivers/mtd/devices/Makefile | 3 +-
drivers/mtd/devices/m25p80.c | 100 +-
drivers/mtd/devices/spiflash.c | 2131 +++++++++++++++++++++++++++++++++++
drivers/mtd/maps/Kconfig | 11 +-
drivers/mtd/maps/physmap.c | 202 +++-
drivers/mtd/mtdchar.c | 54 +
drivers/mtd/mtdcore.c | 63 +-
drivers/mtd/mtdpart.c | 9 +
drivers/mtd/nand/Kconfig | 46 +-
drivers/mtd/nand/Makefile | 11 +-
drivers/mtd/nand/monza_nand.c | 614 ++++++++++
drivers/mtd/nand/nand_base.c | 1226 +++++++++++++++++++-
drivers/mtd/nand/nand_bch_ecc.c | 311 +++++
drivers/mtd/nand/nand_bch_ecc.h | 11 +
drivers/mtd/nand/nand_ids.c | 253 ++++-
drivers/mtd/nand/nandsim.c | 2 +-
drivers/mtd/nand/smp8xxx_nand.c | 2009 +++++++++++++++++++++++++++++++++
drivers/mtd/ubi/misc.c | 7 +
21 files changed, 7164 insertions(+), 49 deletions(-)
Here's the actual diff, with non-core changes omitted.
I have also deleted two irrelevant large diff blocks in nand_base.c
CONFIG_VENDOR_DTV can be ignored, it's an unrelated project.
AFAICT, most of this code should not be in core files.
diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig
index 27143e042af5..f50826842364 100644
--- a/drivers/mtd/Kconfig
+++ b/drivers/mtd/Kconfig
@@ -1,6 +1,7 @@
menuconfig MTD
tristate "Memory Technology Device (MTD) support"
depends on GENERIC_IO
+ depends on (!VENDOR_DTV || (VENDOR_DTV_ROM_SLC || VENDOR_DTV_ROM_MLC))
help
Memory Technology Devices are flash, RAM and similar chips, often
used for solid state file systems on embedded devices. This option
@@ -22,9 +23,21 @@ config MTD_TESTS
WARNING: some of the tests will ERASE entire MTD device which they
test. Do not use these tests unless you really know what you do.
+config MTD_PARTITIONS
+ bool "MTD partitioning support"
+ help
+ If you have a device which needs to divide its flash chip(s) up
+ into multiple 'partitions', each of which appears to the user as
+ a separate MTD device, you require this option to be enabled. If
+ unsure, say 'Y'.
+
+ Note, however, that you don't need this option for the DiskOnChip
+ devices. Partitioning on NFTL 'devices' is a different - that's the
+ 'normal' form of partitioning used on a block device.
config MTD_REDBOOT_PARTS
tristate "RedBoot partition table parsing"
+ depends on !TANGOX
---help---
RedBoot is a ROM monitor and bootloader which deals with multiple
'images' in flash devices by putting a table one of the erase
@@ -75,7 +88,7 @@ endif # MTD_REDBOOT_PARTS
config MTD_CMDLINE_PARTS
bool "Command line partition table parsing"
- depends on MTD = "y"
+ depends on MTD = "y" && !XENV_PARTITION
---help---
Allow generic configuration of the MTD partition tables via the kernel
command line. Multiple flash resources are supported for hardware where
diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c
index d02592e6a0f0..eb70d2eca02d 100644
--- a/drivers/mtd/chips/cfi_cmdset_0002.c
+++ b/drivers/mtd/chips/cfi_cmdset_0002.c
@@ -345,6 +345,16 @@ static struct cfi_fixup cfi_nopri_fixup_table[] = {
{ 0, 0, NULL }
};
+static void fixup_M29W128G_write_buffer(struct mtd_info *mtd)
+{
+ struct map_info *map = mtd->priv;
+ struct cfi_private *cfi = map->fldrv_priv;
+ if (cfi->cfiq->BufWriteTimeoutTyp) {
+ pr_warning("Don't use write buffer on ST flash M29W128G\n");
+ cfi->cfiq->BufWriteTimeoutTyp = 0;
+ }
+}
+
static struct cfi_fixup cfi_fixup_table[] = {
{ CFI_MFR_ATMEL, CFI_ID_ANY, fixup_convert_atmel_pri },
#ifdef AMD_BOOTLOC_BUG
@@ -362,6 +372,7 @@ static struct cfi_fixup cfi_fixup_table[] = {
{ CFI_MFR_AMD, 0x1301, fixup_s29gl064n_sectors },
{ CFI_MFR_AMD, 0x1a00, fixup_s29gl032n_sectors },
{ CFI_MFR_AMD, 0x1a01, fixup_s29gl032n_sectors },
+ { CFI_MFR_ST, 0x227E, fixup_M29W128G_write_buffer },
{ CFI_MFR_SST, 0x536a, fixup_sst38vf640x_sectorsize }, /* SST38VF6402 */
{ CFI_MFR_SST, 0x536b, fixup_sst38vf640x_sectorsize }, /* SST38VF6401 */
{ CFI_MFR_SST, 0x536c, fixup_sst38vf640x_sectorsize }, /* SST38VF6404 */
@@ -616,6 +627,22 @@ static struct mtd_info *cfi_amdstd_setup(struct mtd_info *mtd)
* correctly and is therefore not done (particularly with interleaved chips
* as each chip must be checked independently of the others).
*/
+#ifdef CONFIG_TANGOX
+/* For TANGOX, verify content in start address as well */
+static int __xipram chip_ready(struct map_info *map, unsigned long addr, unsigned long start, map_word z_val)
+{
+ map_word d, t, z;
+
+ d = map_read(map, addr);
+ mb();
+ t = map_read(map, addr);
+ mb();
+ z = map_read(map, start);
+ mb();
+
+ return map_word_equal(map, d, t) && map_word_equal(map, z, z_val);
+}
+#else
static int __xipram chip_ready(struct map_info *map, unsigned long addr)
{
map_word d, t;
@@ -625,6 +652,7 @@ static int __xipram chip_ready(struct map_info *map, unsigned long addr)
return map_word_equal(map, d, t);
}
+#endif
/*
* Return true if the chip is ready and has the correct value.
@@ -658,6 +686,9 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr
struct cfi_private *cfi = map->fldrv_priv;
unsigned long timeo;
struct cfi_pri_amdstd *cfip = (struct cfi_pri_amdstd *)cfi->cmdset_priv;
+#ifdef CONFIG_TANGOX
+ map_word z_val = map_read(map, chip->start);
+#endif
resettime:
timeo = jiffies + HZ;
@@ -666,8 +697,13 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr
case FL_STATUS:
for (;;) {
+#ifdef CONFIG_TANGOX
+ if (chip_ready(map, adr, chip->start, z_val))
+ break;
+#else
if (chip_ready(map, adr))
break;
+#endif
if (time_after(jiffies, timeo)) {
printk(KERN_ERR "Waiting for chip to be ready timed out.\n");
@@ -691,6 +727,12 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr
(mode == FL_WRITING && (cfip->EraseSuspend & 0x2))))
goto sleep;
+ /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ * Sentivision FIX: map_write here whole flash operation freeze on VIP1216 STB.
+ * So we just will sleep waitting for state change: */
+ goto sleep;
+ /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
/* We could check to see if we're trying to access the sector
* that is currently being erased. However, no user will try
* anything like that so we just wait for the timeout. */
@@ -703,8 +745,13 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr
chip->state = FL_ERASE_SUSPENDING;
chip->erase_suspended = 1;
for (;;) {
+#ifdef CONFIG_TANGOX
+ if (chip_ready(map, adr, chip->start, z_val))
+ break;
+#else
if (chip_ready(map, adr))
break;
+#endif
if (time_after(jiffies, timeo)) {
/* Should have suspended the erase by now.
@@ -1143,6 +1190,9 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip,
int ret = 0;
map_word oldd;
int retry_cnt = 0;
+#ifdef CONFIG_TANGOX
+ map_word z_val;
+#endif
adr += chip->start;
@@ -1162,6 +1212,9 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip,
* data at other locations when 0xff is written to a location that
* already contains 0xff.
*/
+#ifdef CONFIG_TANGOX
+ z_val = ((adr == chip->start) ? datum : map_read(map, chip->start));
+#endif
oldd = map_read(map, adr);
if (map_word_equal(map, oldd, datum)) {
pr_debug("MTD %s(): NOP\n",
@@ -1200,15 +1253,25 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip,
continue;
}
- if (time_after(jiffies, timeo) && !chip_ready(map, adr)){
+#ifdef CONFIG_TANGOX
+ if (time_after(jiffies, timeo) && !chip_ready(map, adr, chip->start, z_val))
+#else
+ if (time_after(jiffies, timeo) && !chip_ready(map, adr))
+#endif
+ {
xip_enable(map, chip, adr);
printk(KERN_WARNING "MTD %s(): software timeout\n", __func__);
xip_disable(map, chip, adr);
break;
}
+#ifdef CONFIG_TANGOX
+ if (chip_ready(map, adr, chip->start, z_val))
+ break;
+#else
if (chip_ready(map, adr))
break;
+#endif
/* Latency issues. Drop the lock, wait a while and retry */
UDELAY(map, chip, adr, 1);
@@ -1374,6 +1437,9 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip,
unsigned long cmd_adr;
int z, words;
map_word datum;
+#ifdef CONFIG_TANGOX
+ map_word z_val;
+#endif
adr += chip->start;
cmd_adr = adr;
@@ -1394,6 +1460,9 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip,
ENABLE_VPP(map);
xip_disable(map, chip, cmd_adr);
+#ifdef CONFIG_TANGOX
+ z_val = ((adr == chip->start) ? datum : map_read(map, chip->start));
+#endif
cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL);
@@ -1443,10 +1512,20 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip,
continue;
}
+#ifdef CONFIG_TANGOX
+ if (time_after(jiffies, timeo) && !chip_ready(map, adr, chip->start, z_val))
+ break;
+#else
if (time_after(jiffies, timeo) && !chip_ready(map, adr))
break;
+#endif
- if (chip_ready(map, adr)) {
+#ifdef CONFIG_TANGOX
+ if (chip_ready(map, adr, chip->start, z_val))
+#else
+ if (chip_ready(map, adr))
+#endif
+ {
xip_enable(map, chip, adr);
goto op_done;
}
@@ -1563,12 +1642,19 @@ static int cfi_amdstd_panic_wait(struct map_info *map, struct flchip *chip,
struct cfi_private *cfi = map->fldrv_priv;
int retries = 10;
int i;
+#ifdef CONFIG_TANGOX
+ map_word z_val = map_read(map, chip->start);
+#endif
/*
* If the driver thinks the chip is idle, and no toggle bits
* are changing, then the chip is actually idle for sure.
*/
+#ifdef CONFIG_TANGOX
+ if (chip->state == FL_READY && chip_ready(map, adr, chip->start, z_val))
+#else
if (chip->state == FL_READY && chip_ready(map, adr))
+#endif
return 0;
/*
@@ -1585,7 +1671,11 @@ static int cfi_amdstd_panic_wait(struct map_info *map, struct flchip *chip,
/* wait for the chip to become ready */
for (i = 0; i < jiffies_to_usecs(timeo); i++) {
+#ifdef CONFIG_TANGOX
+ if (chip_ready(map, adr, chip->start, z_val))
+#else
if (chip_ready(map, adr))
+#endif
return 0;
udelay(1);
@@ -1616,6 +1706,9 @@ static int do_panic_write_oneword(struct map_info *map, struct flchip *chip,
map_word oldd;
int ret = 0;
int i;
+#ifdef CONFIG_TANGOX
+ map_word z_val = map_read(map, chip->start);
+#endif
adr += chip->start;
@@ -1647,7 +1740,11 @@ retry:
map_write(map, datum, adr);
for (i = 0; i < jiffies_to_usecs(uWriteTimeout); i++) {
+#ifdef CONFIG_TANGOX
+ if (chip_ready(map, adr, chip->start, z_val))
+#else
if (chip_ready(map, adr))
+#endif
break;
udelay(1);
@@ -1793,6 +1890,10 @@ static int __xipram do_erase_chip(struct map_info *map, struct flchip *chip)
unsigned long int adr;
DECLARE_WAITQUEUE(wait, current);
int ret = 0;
+#ifdef CONFIG_TANGOX
+ map_word z_val;
+ z_val.x[0] = ((map->bankwidth == 1) ? 0xff : 0xffff);
+#endif
adr = cfi->addr_unlock1;
@@ -1845,8 +1946,13 @@ static int __xipram do_erase_chip(struct map_info *map, struct flchip *chip)
chip->erase_suspended = 0;
}
+#ifdef CONFIG_TANGOX
+ if (chip_ready(map, adr, chip->start, z_val))
+ break;
+#else
if (chip_ready(map, adr))
break;
+#endif
if (time_after(jiffies, timeo)) {
printk(KERN_WARNING "MTD %s(): software timeout\n",
@@ -1882,6 +1988,9 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip,
unsigned long timeo = jiffies + HZ;
DECLARE_WAITQUEUE(wait, current);
int ret = 0;
+#ifdef CONFIG_TANGOX
+ map_word z_val;
+#endif
adr += chip->start;
@@ -1895,6 +2004,13 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip,
pr_debug("MTD %s(): ERASE 0x%.8lx\n",
__func__, adr );
+#ifdef CONFIG_TANGOX
+ if (adr == chip->start)
+ z_val.x[0] = ((map->bankwidth == 1) ? 0xff : 0xffff);
+ else
+ z_val = map_read(map, chip->start);
+#endif
+
XIP_INVAL_CACHED_RANGE(map, adr, len);
ENABLE_VPP(map);
xip_disable(map, chip, adr);
@@ -1928,13 +2044,18 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip,
continue;
}
if (chip->erase_suspended) {
- /* This erase was suspended and resumed.
+ /* This erase was suspended and resumed.
Adjust the timeout */
timeo = jiffies + (HZ*20); /* FIXME */
chip->erase_suspended = 0;
}
- if (chip_ready(map, adr)) {
+#ifdef CONFIG_TANGOX
+ if (chip_ready(map, adr, chip->start, z_val))
+#else
+ if (chip_ready(map, adr))
+#endif
+ {
xip_enable(map, chip, adr);
break;
}
diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
index 1924d247c1cb..077105f0996d 100644
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -56,6 +56,9 @@
/* Used for Macronix flashes only. */
#define OPCODE_EN4B 0xb7 /* Enter 4-byte mode */
#define OPCODE_EX4B 0xe9 /* Exit 4-byte mode */
+#if defined(CONFIG_SPI_TANGOX) || defined (CONFIG_SPI_TANGOX_MODULE)
+#define OPCODE_RDP 0xab /* Release from deep power down */
+#endif
/* Used for Spansion flashes only. */
#define OPCODE_BRWR 0x17 /* Bank register write */
@@ -388,6 +391,80 @@ static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len,
return 0;
}
+ /*
+ * Read an address range from the flash chip page by page.
+ * Some controller has transaction length limitation such as the
+ * Freescale's eSPI controller can only trasmit 0xFFFF bytes one
+ * time, so we have to read page by page if the len is more than
+ * the limitation.
+ */
+static int m25p80_page_read(struct mtd_info *mtd, loff_t from, size_t len,
+ size_t *retlen, u_char *buf)
+{
+ struct m25p *flash = mtd_to_m25p(mtd);
+ struct spi_transfer t[2];
+ struct spi_message m;
+ u32 i, page_size = 0;
+
+ pr_debug("%s: %s from 0x%08x, len %zd\n", dev_name(&flash->spi->dev),
+ __func__, (u32)from, len);
+
+ /* sanity checks */
+ if (!len)
+ return 0;
+
+ if (from + len > flash->mtd.size)
+ return -EINVAL;
+
+ spi_message_init(&m);
+ memset(t, 0, (sizeof t));
+
+ /* NOTE:
+ * OPCODE_FAST_READ (if available) is faster.
+ * Should add 1 byte DUMMY_BYTE.
+ */
+ t[0].tx_buf = flash->command;
+ t[0].len = m25p_cmdsz(flash) + FAST_READ_DUMMY_BYTE;
+ spi_message_add_tail(&t[0], &m);
+
+ t[1].rx_buf = buf;
+ spi_message_add_tail(&t[1], &m);
+
+ /* Byte count starts at zero. */
+ if (retlen)
+ *retlen = 0;
+
+ mutex_lock(&flash->lock);
+
+ /* Wait till previous write/erase is done. */
+ if (wait_till_ready(flash)) {
+ /* REVISIT status return?? */
+ mutex_unlock(&flash->lock);
+ return 1;
+ }
+
+ /* Set up the write data buffer. */
+ flash->command[0] = OPCODE_READ;
+
+ for (i = page_size; i < len; i += page_size) {
+ page_size = len - i;
+ if (page_size > flash->page_size)
+ page_size = flash->page_size;
+ m25p_addr2cmd(flash, from + i, flash->command);
+ t[1].len = page_size;
+ t[1].rx_buf = buf + i;
+
+ spi_sync(flash->spi, &m);
+
+ *retlen += m.actual_length - m25p_cmdsz(flash)
+ - FAST_READ_DUMMY_BYTE;
+ }
+
+ mutex_unlock(&flash->lock);
+
+ return 0;
+}
+
/*
* Write an address range to the flash chip. Data must be written in
* FLASH_PAGESIZE chunks. The address range may be any size provided
@@ -820,6 +897,22 @@ static int __devinit m25p_probe(struct spi_device *spi)
dev_warn(&spi->dev, "unrecognized id %s\n", data->type);
}
+#if defined(CONFIG_SPI_TANGOX) || defined (CONFIG_SPI_TANGOX_MODULE)
+ /*
+ * - we need to send wake up command before probing id. this is because
+ * the macronix device will not return correct id in sleep mode.
+ *
+ * - the wake up command is only for macronix device and we check it with
+ * the id string from platform device info.
+ */
+ if ( !strncmp(id->name, "mx", 2) ) {
+ /* wake up device for the case flash in deep power down mode */
+ u8 code = OPCODE_RDP;
+ u8 dummy;
+ spi_write_then_read(spi, &code, 1, &dummy, 1);
+ }
+#endif
+
info = (void *)id->driver_data;
if (info->jedec_id) {
@@ -880,6 +973,12 @@ static int __devinit m25p_probe(struct spi_device *spi)
flash->mtd._erase = m25p80_erase;
flash->mtd._read = m25p80_read;
+#if defined(CONFIG_SPI_TANGOX) || defined (CONFIG_SPI_TANGOX_MODULE)
+ /* overwrite read for page size read */
+ if (spi->master->quirks & SPI_QUIRK_TRANS_LEN_LIMIT)
+ flash->mtd._read = m25p80_page_read;
+#endif
+
/* sst flash chips use AAI word program */
if (JEDEC_MFR(info->jedec_id) == CFI_MFR_SST)
flash->mtd._write = sst_write;
@@ -934,7 +1033,6 @@ static int __devinit m25p_probe(struct spi_device *spi)
flash->mtd.eraseregions[i].erasesize / 1024,
flash->mtd.eraseregions[i].numblocks);
-
/* partitions should match sector boundaries; and it may be good to
* use readonly partitions for writeprotected sectors (BP2..BP0).
*/
diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig
index 8af67cfd671a..7354f465b430 100644
--- a/drivers/mtd/maps/Kconfig
+++ b/drivers/mtd/maps/Kconfig
@@ -4,6 +4,7 @@ menu "Mapping drivers for chip access"
config MTD_COMPLEX_MAPPINGS
bool "Support non-linear mappings of flash chips"
+ depends on MTD && !TANGOX_XENV_READ
help
This causes the chip drivers to allow for complicated
paged mappings of flash chips.
@@ -24,7 +25,7 @@ config MTD_PHYSMAP
config MTD_PHYSMAP_COMPAT
bool "Physmap compat support"
- depends on MTD_PHYSMAP
+ depends on MTD_PHYSMAP && !TANGOX_XENV_READ
default n
help
Setup a simple mapping via the Kconfig options. Normally the
@@ -35,7 +36,7 @@ config MTD_PHYSMAP_COMPAT
config MTD_PHYSMAP_START
hex "Physical start address of flash mapping"
- depends on MTD_PHYSMAP_COMPAT
+ depends on MTD_PHYSMAP_COMPAT && !TANGOX_XENV_READ
default "0x8000000"
help
This is the physical memory location at which the flash chips
@@ -45,8 +46,8 @@ config MTD_PHYSMAP_START
config MTD_PHYSMAP_LEN
hex "Physical length of flash mapping"
- depends on MTD_PHYSMAP_COMPAT
- default "0"
+ depends on MTD_PHYSMAP_COMPAT && !TANGOX_XENV_READ
+ default "0x4000000"
help
This is the total length of the mapping of the flash chips on
your particular board. If there is space, or aliases, in the
@@ -57,7 +58,7 @@ config MTD_PHYSMAP_LEN
config MTD_PHYSMAP_BANKWIDTH
int "Bank width in octets"
- depends on MTD_PHYSMAP_COMPAT
+ depends on MTD_PHYSMAP_COMPAT && !TANGOX_XENV_READ
default "2"
help
This is the total width of the data bus of the flash devices
diff --git a/drivers/mtd/maps/physmap.c b/drivers/mtd/maps/physmap.c
index 21b0b713cacb..3b682502988d 100644
--- a/drivers/mtd/maps/physmap.c
+++ b/drivers/mtd/maps/physmap.c
@@ -21,6 +21,53 @@
#include <linux/mtd/concat.h>
#include <linux/io.h>
+#if defined(CONFIG_TANGOX) && defined(CONFIG_TANGOX_XENV_READ)
+
+#ifdef CONFIG_TANGO2
+#include <asm/tango2/emhwlib_registers_tango2.h>
+#include <asm/tango2/tango2_gbus.h>
+#elif defined(CONFIG_TANGO3)
+#include <asm/tango3/emhwlib_registers_tango3.h>
+#include <asm/tango3/tango3_gbus.h>
+#endif
+
+#define XENV_MAX_FLASH 4
+#define XENV_MAX_FLASH_PARTITIONS 16
+static struct mtd_info *mymtds[XENV_MAX_FLASH] = { NULL, NULL, NULL, NULL };
+static struct mtd_partition *mtd_parts[XENV_MAX_FLASH] = { NULL, NULL, NULL, NULL };
+static unsigned int p_cnts[XENV_MAX_FLASH] = { 0, 0, 0, 0 };
+static u64 f_sizes[XENV_MAX_FLASH] = { 0, 0, 0, 0 };
+
+struct map_info physmap_maps[XENV_MAX_FLASH] = {
+ {
+ .name = "CS0: Physically mapped flash",
+ .phys = 0x40000000,
+ .size = 0, /* To be filled by XENV */
+ .bankwidth = 2, /* To be checked by PBI registers */
+ },
+ {
+ .name = "CS1: Physically mapped flash",
+ .phys = 0x44000000,
+ .size = 0, /* To be filled by XENV */
+ .bankwidth = 2, /* To be checked by PBI registers */
+ },
+ {
+ .name = "CS2: Physically mapped flash",
+ .phys = 0x48000000,
+ .size = 0, /* To be filled by XENV */
+ .bankwidth = 2, /* To be checked by PBI registers */
+ },
+ {
+ .name = "CS3: Physically mapped flash",
+ .phys = 0x4c000000,
+ .size = 0, /* To be filled by XENV */
+ .bankwidth = 2, /* To be checked by PBI registers */
+ },
+};
+int tangox_flash_get_info(int cs, u64 *size, unsigned int *part_count);
+int tangox_flash_get_parts(int cs, u64 offset[], u64 size[]);
+#endif
+
#define MAX_RESOURCES 4
struct physmap_flash_info {
@@ -33,6 +80,29 @@ struct physmap_flash_info {
static int physmap_flash_remove(struct platform_device *dev)
{
+#if defined(CONFIG_TANGOX) && defined(CONFIG_TANGOX_XENV_READ)
+ int cs, p;
+ struct mtd_partition *part_ptr;
+
+ for (cs = 0; cs < XENV_MAX_FLASH; cs++) {
+ if (f_sizes[cs] != 0) {
+ if (p_cnts[cs] != 0) {
+ for (part_ptr = mtd_parts[cs], p = 0; p < p_cnts[cs]; p++, part_ptr++) {
+ if (part_ptr->name) {
+ kfree(part_ptr->name);
+ part_ptr->name = NULL;
+ }
+ }
+ }
+ mtd_device_unregister(mymtds[cs]);
+ map_destroy(mymtds[cs]);
+ kfree(mtd_parts[cs]);
+ mtd_parts[cs] = NULL;
+ iounmap(physmap_maps[cs].virt);
+ physmap_maps[cs].virt = NULL;
+ }
+ }
+#else
struct physmap_flash_info *info;
struct physmap_flash_data *physmap_data;
int i;
@@ -57,7 +127,7 @@ static int physmap_flash_remove(struct platform_device *dev)
if (physmap_data->exit)
physmap_data->exit(dev);
-
+#endif
return 0;
}
@@ -93,14 +163,128 @@ static const char *rom_probe_types[] = {
"qinfo_probe",
"map_rom",
NULL };
+
+#ifndef CONFIG_TANGOX
static const char *part_probe_types[] = { "cmdlinepart", "RedBoot", "afs",
NULL };
+#endif
static int physmap_flash_probe(struct platform_device *dev)
{
+ const char **probe_type;
+
+#if defined(CONFIG_TANGOX) && defined(CONFIG_TANGOX_XENV_READ)
+ int cs;
+ int part_num = 0;
+ unsigned long csconfig = gbus_read_reg32(REG_BASE_host_interface + PB_CS_config) & 0xf;
+
+ for (cs = 0; cs < XENV_MAX_FLASH; cs++) {
+
+ /* Check XENV for availability */
+ f_sizes[cs] = p_cnts[cs] = 0;
+
+ tangox_flash_get_info(cs, &f_sizes[cs], &p_cnts[cs]);
+ if (f_sizes[cs] == 0)
+ continue;
+ else {
+ physmap_maps[cs].size = f_sizes[cs];
+ physmap_maps[cs].bankwidth = ((csconfig >> cs) & 0x1) ? 1 : 2;
+ }
+
+ printk(KERN_NOTICE "physmap flash device CS%d: 0x%x at 0x%x\n",
+ cs, (u32)physmap_maps[cs].size, (u32)physmap_maps[cs].phys);
+ physmap_maps[cs].virt = ioremap(physmap_maps[cs].phys, physmap_maps[cs].size);
+
+ if (!physmap_maps[cs].virt) {
+ printk("Failed to ioremap\n");
+ continue;
+ }
+
+ simple_map_init(&physmap_maps[cs]);
+
+ mymtds[cs] = NULL;
+ probe_type = rom_probe_types;
+ for(; !mymtds[cs] && *probe_type; probe_type++) {
+ mymtds[cs] = do_map_probe(*probe_type, &physmap_maps[cs]);
+ }
+
+ if (mymtds[cs] && (mymtds[cs]->size != f_sizes[cs])) {
+ /* Redo ioremap if size specified is not the same as detected */
+ iounmap((void *)physmap_maps[cs].virt);
+ physmap_maps[cs].size = mymtds[cs]->size;
+ physmap_maps[cs].virt = ioremap(physmap_maps[cs].phys, physmap_maps[cs].size);
+ physmap_maps[cs].set_vpp = physmap_set_vpp;
+
+ if (!physmap_maps[cs].virt) {
+ printk(KERN_NOTICE "Failed to ioremap at 0x%08x, size 0x%08x\n",
+ (u32)physmap_maps[cs].phys, (u32)physmap_maps[cs].size);
+ continue;
+ }
+ printk(KERN_NOTICE "CS%d: flash size mismatched, re-do probing/initialization.\n", cs);
+ printk(KERN_NOTICE "physmap flash device CS%d: 0x%x at 0x%x (remapped 0x%x)\n",
+ cs, (u32)physmap_maps[cs].size, (u32)physmap_maps[cs].phys, (u32)physmap_maps[cs].virt);
+
+ /* Re-do initialization */
+ simple_map_init(&physmap_maps[cs]);
+ mymtds[cs] = NULL;
+ probe_type = rom_probe_types;
+ for(; !mymtds[cs] && *probe_type; probe_type++) {
+ mymtds[cs] = do_map_probe(*probe_type, &physmap_maps[cs]);
+ }
+ }
+
+ if (mymtds[cs]) {
+ mymtds[cs]->owner = THIS_MODULE;
+ mtd_device_register(mymtds[cs], NULL, 0);
+ part_num++;
+
+ if (p_cnts[cs] > 0) {
+ int p, pcnt;
+ struct mtd_partition *part_ptr;
+ u64 offsets[XENV_MAX_FLASH_PARTITIONS];
+ u64 szs[XENV_MAX_FLASH_PARTITIONS];
+
+ if ((mtd_parts[cs] = (struct mtd_partition *)kmalloc(
+ sizeof(struct mtd_partition) * p_cnts[cs], GFP_KERNEL)) == NULL) {
+ printk(KERN_NOTICE "Out of memory.\n");
+ return -ENOMEM;
+ }
+ memset(mtd_parts[cs], 0, sizeof(struct mtd_partition) * p_cnts[cs]);
+ tangox_flash_get_parts(cs, offsets, szs);
+
+ printk(KERN_NOTICE "Using physmap partition definition\n");
+
+ /* Initialize each partition */
+ for (pcnt = 0, part_ptr = mtd_parts[cs], p = 0; p < p_cnts[cs]; p++) {
+ if (((szs[p] & 0x7fffffff) + offsets[p]) > physmap_maps[cs].size) {
+ printk(KERN_NOTICE "CS%d-Part%d (offset:0x%llx, size:0x%llx) outside physical map, removed.\n",
+ cs, p + 1, offsets[p], szs[p] & 0x7fffffffffffffffULL);
+ continue;
+ }
+ part_ptr->size = szs[p] & 0x7fffffffffffffffULL;
+ part_ptr->offset = offsets[p];
+ if (part_ptr->size & 0x8000000000000000ULL)
+ part_ptr->mask_flags = MTD_WRITEABLE;
+ part_ptr->name = (char *)kmalloc(16, GFP_KERNEL);
+ if (part_ptr->name != NULL)
+ sprintf(part_ptr->name, "CS%d-Part%d", cs, p + 1);
+ pcnt++;
+ part_ptr++;
+ }
+ p_cnts[cs] = pcnt;
+
+ if (p_cnts[cs] > 0) {
+ printk(KERN_NOTICE "Adding partition #%d-#%d\n", part_num, part_num + p_cnts[cs] - 1);
+ mtd_device_register(mymtds[cs], mtd_parts[cs], p_cnts[cs]);
+ part_num += p_cnts[cs];
+ }
+ }
+ }
+ }
+ return 0;
+#else
struct physmap_flash_data *physmap_data;
struct physmap_flash_info *info;
- const char **probe_type;
const char **part_types;
int err = 0;
int i;
@@ -199,6 +383,7 @@ static int physmap_flash_probe(struct platform_device *dev)
err_out:
physmap_flash_remove(dev);
return err;
+#endif /* CONFIG_TANGOX && CONFIG_TANGOX_XENV_READ */
}
#ifdef CONFIG_PM
@@ -218,7 +403,9 @@ static void physmap_flash_shutdown(struct platform_device *dev)
static struct platform_driver physmap_flash_driver = {
.probe = physmap_flash_probe,
.remove = physmap_flash_remove,
- .shutdown = physmap_flash_shutdown,
+#ifdef CONFIG_PM
+ .shutdown = physmap_flash_shutdown,
+#endif
.driver = {
.name = "physmap-flash",
.owner = THIS_MODULE,
@@ -261,11 +448,20 @@ static int __init physmap_init(void)
}
#endif
+#ifdef CONFIG_TANGOX
+ /* a hack to force probing here */
+ err = physmap_flash_probe(NULL);
+#endif
+
return err;
}
static void __exit physmap_exit(void)
{
+#ifdef CONFIG_TANGOX
+ physmap_flash_remove(NULL);
+#endif
+
#ifdef CONFIG_MTD_PHYSMAP_COMPAT
platform_device_unregister(&physmap_flash);
#endif
diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c
index f2f482bec573..8219c1ce0f6b 100644
--- a/drivers/mtd/mtdchar.c
+++ b/drivers/mtd/mtdchar.c
@@ -620,6 +620,8 @@ static int mtdchar_write_ioctl(struct mtd_info *mtd,
return ret;
}
+#define MEMERASEFORCE _IOW('M', 20, struct erase_info_user)
+
static int mtdchar_ioctl(struct file *file, u_int cmd, u_long arg)
{
struct mtd_file_info *mfi = file->private_data;
@@ -751,6 +753,58 @@ static int mtdchar_ioctl(struct file *file, u_int cmd, u_long arg)
break;
}
+ case MEMERASEFORCE:
+ {
+ struct erase_info *erase;
+
+ if(!(file->f_mode & 2))
+ return -EPERM;
+
+ erase=kzalloc(sizeof(struct erase_info),GFP_KERNEL);
+ if (!erase)
+ ret = -ENOMEM;
+ else {
+ wait_queue_head_t waitq;
+ DECLARE_WAITQUEUE(wait, current);
+
+ init_waitqueue_head(&waitq);
+
+ if (copy_from_user(&erase->addr, argp,
+ sizeof(struct erase_info_user))) {
+ kfree(erase);
+ return -EFAULT;
+ }
+ erase->mtd = mtd;
+ erase->callback = mtdchar_erase_callback;
+ erase->priv = (unsigned long)&waitq;
+ erase->retries = 0x73092215;
+
+ /*
+ FIXME: Allow INTERRUPTIBLE. Which means
+ not having the wait_queue head on the stack.
+
+ If the wq_head is on the stack, and we
+ leave because we got interrupted, then the
+ wq_head is no longer there when the
+ callback routine tries to wake us up.
+ */
+ ret = mtd_erase(mtd, erase);
+ if (!ret) {
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ add_wait_queue(&waitq, &wait);
+ if (erase->state != MTD_ERASE_DONE &&
+ erase->state != MTD_ERASE_FAILED)
+ schedule();
+ remove_wait_queue(&waitq, &wait);
+ set_current_state(TASK_RUNNING);
+
+ ret = (erase->state == MTD_ERASE_FAILED)?-EIO:0;
+ }
+ kfree(erase);
+ }
+ break;
+ }
+
case MEMWRITEOOB:
{
struct mtd_oob_buf buf;
diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
index c837507dfb1c..3a3d5062456e 100644
--- a/drivers/mtd/mtdcore.c
+++ b/drivers/mtd/mtdcore.c
@@ -3,7 +3,7 @@
* drivers and users.
*
* Copyright © 1999-2010 David Woodhouse <dwmw2 at infradead.org>
- * Copyright © 2006 Red Hat UK Limited
+ * Copyright © 2006 Red Hat UK Limited
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -80,6 +80,10 @@ static struct class mtd_class = {
.resume = mtd_cls_resume,
};
+#if defined(CONFIG_ARCH_VENDOR_SX6) && defined(CONFIG_MTD_UBI) && !defined(CONFIG_BLK_DEV_INITRD)
+extern char saved_root_name[64];
+#endif
+
static DEFINE_IDR(mtd_idr);
/* These are exported solely for the purpose of mtd_blkdevs.c. You
@@ -250,6 +254,49 @@ static ssize_t mtd_name_show(struct device *dev,
}
static DEVICE_ATTR(name, S_IRUGO, mtd_name_show, NULL);
+static ssize_t mtd_nand_type_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct mtd_info *mtd = dev_get_drvdata(dev);
+
+ return snprintf(buf, PAGE_SIZE, "%s\n", mtd->nand_type);
+}
+static DEVICE_ATTR(nand_type, S_IRUGO, mtd_nand_type_show, NULL);
+
+static ssize_t mtd_nand_manufacturer_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct mtd_info *mtd = dev_get_drvdata(dev);
+
+ return snprintf(buf, PAGE_SIZE, "%s\n", mtd->nand_manufacturer);
+}
+static DEVICE_ATTR(nand_manufacturer, S_IRUGO, mtd_nand_manufacturer_show, NULL);
+
+static ssize_t mtd_nand_onfi_version_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct mtd_info *mtd = dev_get_drvdata(dev);
+
+ return snprintf(buf, PAGE_SIZE, "%s\n", mtd->onfi_version);
+}
+static DEVICE_ATTR(onfi_version, S_IRUGO, mtd_nand_onfi_version_show, NULL);
+
+static ssize_t mtd_nand_id_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct mtd_info *mtd = dev_get_drvdata(dev);
+
+ return snprintf(buf, PAGE_SIZE, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", mtd->id_data[0]
+ , mtd->id_data[1]
+ , mtd->id_data[2]
+ , mtd->id_data[3]
+ , mtd->id_data[4]
+ , mtd->id_data[5]
+ , mtd->id_data[6]
+ , mtd->id_data[7]);
+}
+static DEVICE_ATTR(nand_id, S_IRUGO, mtd_nand_id_show, NULL);
+
static struct attribute *mtd_attrs[] = {
&dev_attr_type.attr,
&dev_attr_flags.attr,
@@ -260,6 +307,10 @@ static struct attribute *mtd_attrs[] = {
&dev_attr_oobsize.attr,
&dev_attr_numeraseregions.attr,
&dev_attr_name.attr,
+ &dev_attr_nand_type.attr,
+ &dev_attr_nand_manufacturer.attr,
+ &dev_attr_nand_id.attr,
+ &dev_attr_onfi_version.attr,
NULL,
};
@@ -321,7 +372,15 @@ int add_mtd_device(struct mtd_info *mtd)
mtd->index = i;
mtd->usecount = 0;
-
+#if defined(CONFIG_ARCH_VENDOR_SX6) && defined(CONFIG_MTD_UBI) && !defined(CONFIG_BLK_DEV_INITRD)
+ if(0 == strncmp(mtd->name,"Rootfs",6))
+ {
+ char rootname[16];
+ sprintf(rootname,"/dev/mtdblock%d",i);
+ strlcpy(saved_root_name, rootname, sizeof(rootname));
+ printk("UBI root=%s\n",saved_root_name);
+ }
+#endif
if (is_power_of_2(mtd->erasesize))
mtd->erasesize_shift = ffs(mtd->erasesize) - 1;
else
diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c
index bf24aa77175d..148cfefa045d 100644
--- a/drivers/mtd/mtdpart.c
+++ b/drivers/mtd/mtdpart.c
@@ -345,6 +345,7 @@ static struct mtd_part *allocate_partition(struct mtd_info *master,
{
struct mtd_part *slave;
char *name;
+ int i;
/* allocate the partition structure */
slave = kzalloc(sizeof(*slave), GFP_KERNEL);
@@ -366,6 +367,11 @@ static struct mtd_part *allocate_partition(struct mtd_info *master,
slave->mtd.oobsize = master->oobsize;
slave->mtd.oobavail = master->oobavail;
slave->mtd.subpage_sft = master->subpage_sft;
+ slave->mtd.nand_type = master->nand_type;
+ slave->mtd.nand_manufacturer = master->nand_manufacturer;
+ slave->mtd.onfi_version = master->onfi_version;
+ for (i = 0; i < 8; i++)
+ slave->mtd.id_data[i] = master->id_data[i];
slave->mtd.name = name;
slave->mtd.owner = master->owner;
@@ -646,6 +652,9 @@ int add_mtd_partitions(struct mtd_info *master,
return 0;
}
+#ifdef CONFIG_VENDOR_DTV
+EXPORT_SYMBOL(add_mtd_partitions);
+#endif
static DEFINE_SPINLOCK(part_parser_lock);
static LIST_HEAD(part_parsers);
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index 7d17cecad69d..241410eee873 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -1,3 +1,10 @@
+config MTD_NAND_IDS
+ tristate "Include chip ids for known NAND devices."
+ depends on MTD
+ help
+ Useful for NAND drivers that do not use the NAND subsystem but
+ still like to take advantage of the known chip information.
+
config MTD_NAND_ECC
tristate
@@ -83,6 +90,14 @@ config MTD_NAND_DENALI_SCRATCH_REG_ADDR
scratch register here to enable this feature. On Intel Moorestown
boards, the scratch register is at 0xFF108018.
+config MTD_NAND_TANGOX
+ tristate "TANGOX NAND Device Support"
+ depends on TANGO3 || TANGO4
+ select MTD_PARTITIONS
+ default m
+ help
+ Support TANGOX NAND Flash in the NAND flash reserved zone.
+
config MTD_NAND_H1900
tristate "iPAQ H1900 flash"
depends on ARCH_PXA && BROKEN
@@ -115,9 +130,6 @@ config MTD_NAND_OMAP2
Support for NAND flash on Texas Instruments OMAP2, OMAP3 and OMAP4
platforms.
-config MTD_NAND_IDS
- tristate
-
config MTD_NAND_RICOH
tristate "Ricoh xD card reader"
default n
@@ -566,5 +578,33 @@ config MTD_NAND_FSMC
help
Enables support for NAND Flash chips on the ST Microelectronics
Flexible Static Memory Controller (FSMC)
+choice
+ prompt "NAND ECC mode"
+ depends on MTD_NAND && ARCH_VENDOR_SX6
+ default MTD_NAND_MLC_BCH if (VENDOR_DTV_ROM_SLC || VENDOR_DTV_ROM_MLC)
+config MTD_NAND_ECC_HW
+ bool "Hardware ECC"
+config MTD_NAND_ECC_SW
+ bool "Soft ECC"
+config MTD_NAND_MLC_BCH
+ bool "MLC BCH "
+config MTD_NAND_ECC_NONE
+ bool "None ECC"
+endchoice
+
+choice
+ prompt "NAND ECC calc size"
+ depends on MTD_NAND && ARCH_VENDOR_SX6
+ default MTD_NAND_ECC_512 if VENDOR_DTV_ROM_SLC
+ default MTD_NAND_ECC_1024 if VENDOR_DTV_ROM_MLC
+config MTD_NAND_ECC_512
+ bool "512 bytes"
+config MTD_NAND_ECC_1024
+ bool "1024 bytes"
+endchoice
+config MTD_NAND_DMA
+ bool "DMA enable"
+ depends on MTD_NAND_PHYSMAP
+default y
endif # MTD_NAND
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index d4b4d8739bd8..696b8ddfd8f4 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -7,12 +7,15 @@ obj-$(CONFIG_MTD_NAND_ECC) += nand_ecc.o
obj-$(CONFIG_MTD_NAND_BCH) += nand_bch.o
obj-$(CONFIG_MTD_NAND_IDS) += nand_ids.o
obj-$(CONFIG_MTD_SM_COMMON) += sm_common.o
-
+ifdef CONFIG_MTD_NAND
+obj-$(CONFIG_ARCH_VENDOR_SX6) += monza_nand.o
+endif
obj-$(CONFIG_MTD_NAND_CAFE) += cafe_nand.o
obj-$(CONFIG_MTD_NAND_SPIA) += spia.o
obj-$(CONFIG_MTD_NAND_AMS_DELTA) += ams-delta.o
obj-$(CONFIG_MTD_NAND_AUTCPU12) += autcpu12.o
obj-$(CONFIG_MTD_NAND_DENALI) += denali.o
+obj-$(CONFIG_MTD_NAND_TANGOX) += smp8xxx_nand.o
obj-$(CONFIG_MTD_NAND_AU1550) += au1550nd.o
obj-$(CONFIG_MTD_NAND_BF5XX) += bf5xx_nand.o
obj-$(CONFIG_MTD_NAND_PPCHAMELEONEVB) += ppchameleonevb.o
@@ -53,3 +56,9 @@ obj-$(CONFIG_MTD_NAND_JZ4740) += jz4740_nand.o
obj-$(CONFIG_MTD_NAND_GPMI_NAND) += gpmi-nand/
nand-objs := nand_base.o nand_bbt.o
+
+ifeq ($(CONFIG_VENDOR_DTV),y)
+ifdef CONFIG_MTD_NAND_MLC_BCH
+nand-objs += nand_bch_ecc.o
+endif
+endif
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index eb9f5fb02eef..4f05253bdc26 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -47,7 +47,22 @@
#include <linux/bitops.h>
#include <linux/leds.h>
#include <linux/io.h>
+#ifdef CONFIG_VENDOR_DTV
+#include <linux/semaphore.h>
+
+#include <asm/byteorder.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+#include <asm/unaligned.h>
+#endif
+
+#ifdef CONFIG_MTD_PARTITIONS
#include <linux/mtd/partitions.h>
+#endif
+#ifdef CONFIG_MTD_NAND_MLC_BCH
+#define CONFIG_NAND_MODE 1
+#endif
/* Define default oob placement schemes for large and small page devices */
static struct nand_ecclayout nand_oob_8 = {
@@ -64,8 +79,11 @@ static struct nand_ecclayout nand_oob_16 = {
.eccbytes = 6,
.eccpos = {0, 1, 2, 3, 6, 7},
.oobfree = {
- {.offset = 8,
- . length = 8} }
+#ifdef CONFIG_MTD_NAND_BBM
+ {.offset = 9, . length = 7}} //nand bbm config
+#else
+ {.offset = 8, . length = 8}}
+#endif
};
static struct nand_ecclayout nand_oob_64 = {
@@ -75,8 +93,112 @@ static struct nand_ecclayout nand_oob_64 = {
48, 49, 50, 51, 52, 53, 54, 55,
56, 57, 58, 59, 60, 61, 62, 63},
.oobfree = {
- {.offset = 2,
- .length = 38} }
+#ifdef CONFIG_MTD_NAND_BBM
+ {.offset = 3,.length = 37}} //nand bbm config
+#else
+ {.offset = 2,.length = 38}}
+#endif
+};
+
+/*For BCH code*/
+static struct nand_ecclayout nand_oob_mlcbch_16 = {
+ .eccbytes = 7,
+ .eccpos = {0, 1, 2, 3, 6, 7, 9},
+ .oobfree = {
+ {.offset = 10,
+ .length = 6}}
+};
+
+#ifdef CONFIG_MTD_NAND_ECC_512
+//change for 8bit 512 byte ecc
+static struct nand_ecclayout nand_oob_mlcbch_64 = {
+ .eccbytes = 56,
+ .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 },
+ .oobfree = {
+ {.offset = 3,
+ .length = 5}}
+};
+#else
+//change for 8bit 1024 byte ecc
+static struct nand_ecclayout nand_oob_mlcbch_64 = {
+ .eccbytes = 28,
+ .eccpos = {
+ 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 = 3,
+ .length = 33}}
+};
+
+static struct nand_ecclayout nand_oob_mlcbch_448 = {
+ .eccbytes = 336,//24*7/4 *8,
+ .eccpos = {
+ 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, 264, 265,
+ 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276,
+ 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287,
+ 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298,
+ 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309,
+ 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320,
+ 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331,
+ 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342,
+ 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353,
+ 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364,
+ 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375,
+ 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386,
+ 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397,
+ 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408,
+ 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419,
+ 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430,
+ 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441,
+ 442, 443, 444, 445, 446, 447 },
+ .oobfree = {
+ {.offset = 3,
+ .length = 109}}
+};
+
+#endif
+
+/*2013.4.2 add for Micron MT29F16G08CBACA*/
+static struct nand_ecclayout nand_oob_mlcbch_224 = {
+ .eccbytes = 168,
+ .eccpos = {
+ 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},
+ .oobfree = {
+ {.offset = 3,
+ .length = 53}}
};
static struct nand_ecclayout nand_oob_128 = {
@@ -93,6 +215,86 @@ static struct nand_ecclayout nand_oob_128 = {
.length = 78} }
};
+#ifdef CONFIG_MIPS_TRIDENT_FUSION_ANDROID
+/*
+ read 1`b1 , access permission, 0`b1 permission denied. it should be write
+ 1 after finish access, then others can access
+ warning: the SPI_lock will change when read the register each time,so don`t
+ use unnecessary ReadRegWord operation
+*/
+
+static int DMA_flag_reset = 1;
+#define SPIN_REG_ADDR 0xf5024068
+
+#define SPINID 0x1
+static void NAND_spin_lock_hw(volatile void * reg)
+{
+ u32 value ;
+ do {
+ value = ReadRegWord(reg) ;
+ } while((value & SPINID) == 0 ); //get 0 permission denied
+
+ //now we get the SPI_lock, value should be 1`b1
+ //printk(KERN_INFO "[%s] reg = 0x%x\t value = 0x%x \n",__func__,reg,value);
+
+ return ;
+}
+
+//fail return 1, 0 success & get the SPIN lock
+u32 NAND_try_spinlock_hw(volatile void * reg)
+{
+ u32 val;
+ val = ReadRegWord(reg);
+ if((val&SPINID)==0x0) //0 is permission denied
+ {
+ //printk(KERN_INFO "NAND: try to get hw SPIN lock fail \n");
+ return 1;
+ }
+ else
+ {
+ //printk(KERN_INFO "NAND: try to get hw SPIN lock success \n");
+ return 0;
+ }
+}
+
+void NAND_spin_lock_hw_dump(volatile void * reg)
+{
+ int try_time = 0;
+ int print_once = 1;
+ while( NAND_try_spinlock_hw(reg) )
+ {
+ schedule();
+
+ //debug
+ #if 0
+ try_time++;
+ if(unlikely(try_time > 20000))
+ {
+ if(print_once)
+ {
+ print_once = 0;
+ dump_stack();
+ }
+ }
+ #endif
+ }
+}
+
+void NAND_spin_unlock_hw(volatile void * reg)
+{
+ u32 val;
+ val = ReadRegWord(reg);
+ WriteRegWord(reg,(val |SPINID));
+
+ //printk(KERN_INFO "[%s] reg = 0x%x\t value = 0x%x \n",__func__,reg,val);
+}
+
+#endif
+
+#ifdef CONFIG_TRIDENT_FLASH_MULTI
+DECLARE_MUTEX(flash_multi_sem);
+#endif
+
static int nand_get_device(struct nand_chip *chip, struct mtd_info *mtd,
int new_state);
@@ -123,6 +325,14 @@ static int check_offs_len(struct mtd_info *mtd,
ret = -EINVAL;
}
+//#ifdef CONFIG_VENDOR_DTV
+ /* Do not allow past end of device */
+ if (ofs + len > mtd->size) {
+ pr_debug( "%s: Past end of device\n",__func__);
+ ret = -EINVAL;
+ }
+//#endif
+
return ret;
}
@@ -145,6 +355,14 @@ static void nand_release_device(struct mtd_info *mtd)
chip->state = FL_READY;
wake_up(&chip->controller->wq);
spin_unlock(&chip->controller->lock);
+
+#ifdef CONFIG_TRIDENT_FLASH_MULTI
+ up(&flash_multi_sem);
+#endif
+
+#ifdef CONFIG_MIPS_TRIDENT_FUSION_ANDROID
+ NAND_spin_unlock_hw(SPIN_REG_ADDR);
+#endif
}
/**
@@ -156,7 +374,11 @@ static void nand_release_device(struct mtd_info *mtd)
static uint8_t nand_read_byte(struct mtd_info *mtd)
{
struct nand_chip *chip = mtd->priv;
+#ifdef CONFIG_VENDOR_DTV
+ return ReadRegByte(chip->IO_ADDR_R);
+#else
return readb(chip->IO_ADDR_R);
+#endif
}
/**
@@ -182,7 +404,11 @@ static uint8_t nand_read_byte16(struct mtd_info *mtd)
static u16 nand_read_word(struct mtd_info *mtd)
{
struct nand_chip *chip = mtd->priv;
+#ifdef CONFIG_VENDOR_DTV
+ return ReadRegWord(chip->IO_ADDR_R);
+#else
return readw(chip->IO_ADDR_R);
+#endif
}
/**
@@ -322,6 +548,51 @@ static int nand_verify_buf16(struct mtd_info *mtd, const uint8_t *buf, int len)
return 0;
}
+#ifdef CONFIG_VENDOR_DTV
+static void nand_write_buf32(struct mtd_info *mtd, const uint8_t *buf, int len)
+{
+// int i;
+ struct nand_chip *chip = mtd->priv;
+ register volatile void* hwaddr = chip->IO_ADDR_W;
+ register u32 *p = (u32 *) buf;
+
+ len >>= 2;
+ if (len == 0)
+ return;
+ do {
+ WriteRegWord(hwaddr,*p++);
+ } while(--len);
+
+// for (i = 0; i < len; i++)
+// WriteRegWord(chip->IO_ADDR_W,p[i]);
+}
+
+static void nand_read_buf32(struct mtd_info *mtd, uint8_t *buf, int len)
+{
+ int i;
+ struct nand_chip *chip = mtd->priv;
+ u32 *p = (u32 *) buf;
+
+ len >>= 2;
+ for (i = 0; i < len; i++)
+ p[i] = ReadRegWord(chip->IO_ADDR_R);
+}
+
+static int nand_verify_buf32(struct mtd_info *mtd, const uint8_t *buf, int len)
+{
+ int i;
+ struct nand_chip *chip = mtd->priv;
+ u32 *p = (u32 *) buf;
+
+ len >>= 2;
+ for (i = 0; i < len; i++)
+ if (p[i] != ReadRegWord(chip->IO_ADDR_R))
+ return -EFAULT;
+
+ return 0;
+}
+#endif
+
/**
* nand_block_bad - [DEFAULT] Read bad block marker from the chip
* @mtd: MTD device structure
@@ -646,7 +917,13 @@ static void nand_command(struct mtd_info *mtd, unsigned int command,
* Apply this short delay always to ensure that we do wait tWB in
* any case on any machine.
*/
+#ifdef CONFIG_TANGOX
+ udelay(1); /* needs to make it much longer than tWB */
+#elif defined(CONFIG_VENDOR_DTV)
+ //ndelay(100);
+#else
ndelay(100);
+#endif
nand_wait_ready(mtd);
}
@@ -768,7 +1045,13 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned int command,
* Apply this short delay always to ensure that we do wait tWB in
* any case on any machine.
*/
+#ifdef CONFIG_TANGOX
+ udelay(1); /* needs to make it much longer than tWB */
+#elif defined(CONFIG_VENDOR_DTV)
+ //ndelay(100);
+#else
ndelay(100);
+#endif
nand_wait_ready(mtd);
}
@@ -800,9 +1083,59 @@ static void panic_nand_get_device(struct nand_chip *chip,
static int
nand_get_device(struct nand_chip *chip, struct mtd_info *mtd, int new_state)
{
+#ifdef CONFIG_MIPS_TRIDENT_FUSION_ANDROID
+ /*for share NAND control between PLF and APP, we use HW SPIN_LOCK to
+ protect */
+ NAND_spin_lock_hw_dump(SPIN_REG_ADDR);
+#endif
+
spinlock_t *lock = &chip->controller->lock;
wait_queue_head_t *wq = &chip->controller->wq;
DECLARE_WAITQUEUE(wait, current);
+
+#ifdef CONFIG_TRIDENT_FLASH_MULTI
+ unsigned int val;
+ if(new_state != FL_PM_SUSPENDED){
+ down(&flash_multi_sem);
+ }
+
+ /*switch to nand*/
+ val = ReadRegWord((void*)0xfB002008);
+ if(val != 0x2)
+ {
+ WriteRegWord((void*)0xfb002008,0x2);
+ ReadRegWord((void*)0xfb002008);
+ }
+
+ #ifdef CONFIG_NAND_MODE
+ /* switch the nand source clock from 100Hz to 200Hz for this version of NAND mode setting
+ if the souce clock is not match the NAND mode, will cause the DMA read time out error */
+ unsigned char nand_clock = ReadRegByte((void*)0xf500e849);
+ nand_clock &= 0xcf;
+ nand_clock |= 0x20;
+ WriteRegByte((void*)0xf500e849,nand_clock);
+
+ /* switch the nand source clock 200Hz clock for write,
+ if the clock is not match the NAND init setting such like 1b002004 = 0x21, will cause WP*/
+ WriteRegWord((void*)0xfb002004, 0x00000067);
+
+ unsigned int write_clock = ReadRegWord((void*)0xfb002070);
+ write_clock |= 0x100;
+ WriteRegWord((void*)0xfb002070,write_clock);
+
+ write_clock = ReadRegWord((void*)0xfb002020);
+ write_clock &= 0xffff3f3f;
+ WriteRegWord((void*)0xfb002020,write_clock);
+
+ /*we set 205c only here,it changed in UXL*/
+ #ifdef CONFIG_MIPS_TRIDENT_UXL
+ WriteRegWord((void*)0xfb00205c, 0x40193333);
+ #else
+ WriteRegWord((void*)0xfb00205c, 0x40193333);
+ #endif
+ #endif
+#endif
+
retry:
spin_lock(lock);
@@ -874,7 +1207,11 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip)
if (state == FL_ERASING)
timeo += (HZ * 400) / 1000;
else
+#ifdef CONFIG_VENDOR_DTV
+ timeo += (HZ * 100) / 1000;
+#else
timeo += (HZ * 20) / 1000;
+#endif
led_trigger_event(nand_led_trigger, LED_FULL);
@@ -882,7 +1219,11 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip)
* Apply this short delay always to ensure that we do wait tWB in any
* case on any machine.
*/
+#ifdef CONFIG_TANGOX
+ udelay(1); /* needs to make it much longer than tWB */
+#else
ndelay(100);
+#endif
if ((state == FL_ERASING) && (chip->options & NAND_IS_AND))
chip->cmdfunc(mtd, NAND_CMD_STATUS_MULTI, -1, -1);
@@ -903,6 +1244,10 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip)
cond_resched();
}
}
+#ifdef CONFIG_VENDOR_DTV
+ if(!time_before(jiffies, timeo)&& state == FL_ERASING)
+ printk("%s eraseing? %d not ready\n",__func__,state == FL_ERASING);
+#endif
led_trigger_event(nand_led_trigger, LED_OFF);
status = (int)chip->read_byte(mtd);
@@ -939,6 +1284,11 @@ static int __nand_unlock(struct mtd_info *mtd, loff_t ofs,
/* Call wait ready function */
status = chip->waitfunc(mtd, chip);
+
+#ifdef CONFIG_VENDOR_DTV
+ udelay(1000);
+#endif
+
/* See if device thinks it succeeded */
if (status & 0x01) {
pr_debug("%s: error status = 0x%08x\n",
@@ -991,6 +1341,10 @@ int nand_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
ret = __nand_unlock(mtd, ofs, len, 0);
out:
+#ifdef CONFIG_VENDOR_DTV
+ /* de-select the NAND device */
+ chip->select_chip(mtd, -1);
+#endif
nand_release_device(mtd);
return ret;
@@ -1272,6 +1626,76 @@ static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
uint8_t *ecc_code = chip->buffers->ecccode;
uint32_t *eccpos = chip->ecc.layout->eccpos;
+#ifdef CONFIG_VENDOR_DTV
+ unsigned int reg;
+ unsigned int status;
+ //unsigned char soft_ecc_code[3];
+ int timeo = 1000;
+
+ //printk("%s\n",__func__);
+
+ chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page);//read oob first to get ECC code
+ chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
+
+// enable_nce(0); //make ce invalid for a while
+ //ndelay(100); //ce high
+ nand_wait_ready(mtd);
+
+ for (i = 0; i < chip->ecc.total; i++)
+ ecc_code[i] = chip->oob_poi[eccpos[i]];
+
+ chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page);
+
+ for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
+ //enable read ecc, size 256 bytes
+ WriteRegWord((u32 __iomem *)0xfb002044, 0);
+
+ //write ecc code to register need by caculate
+ reg = ReadRegWord((u32 __iomem *)0xfb002044);
+ reg |= (0x2000000 | ecc_code[i+2]<<16 | ecc_code[i+1] | ecc_code[i+0]<<8 );//0x12000000; only supprot 3 byte ecc code by SX
+ WriteRegWord((u32 __iomem *)0xfb002044, reg);
+
+#ifdef CONFIG_MTD_NAND_DMA
+ nand_dma_read(p, chip->IO_ADDR_R, eccsize);
+#else
+ chip->read_buf(mtd, p, eccsize);
+#endif
+ //chip->ecc.calculate(mtd, p, &ecc_calc[i]);
+
+ status = ReadRegWord((u32 __iomem *)0xfb002048);
+ while(timeo&&(status&0x8000)!=0x8000){
+ udelay(1);
+ timeo--;
+ status = ReadRegWord((u32 __iomem *)0xfb002048);
+ }
+ if(timeo<=0)
+ printk("Error: NAND ECC ready timeout\n");
+
+ //check status
+ if((status&0x2000)==0x2000){
+ mtd->ecc_stats.failed++;
+ printk("Error:Hardware ECC error at page:%d\n",page);
+ }
+ else if((status&0x1000)!=0x1000){
+ // no ecc error
+ //return 0;
+ }
+ else{
+ int byte_position;
+ int bit_position;
+ //printk("Hardware ECC correct one bit error at page:%d\n",page);
+ byte_position = status>>3 &0x1ff;
+ bit_position = status&0x7;
+
+ p[byte_position] ^= 1<<bit_position;
+
+ mtd->ecc_stats.corrected ++;
+ }
+
+ }
+ return 0;
+
+#else
for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
chip->ecc.hwctl(mtd, NAND_ECC_READ);
chip->read_buf(mtd, p, eccsize);
@@ -1295,6 +1719,7 @@ static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
mtd->ecc_stats.corrected += stat;
}
return 0;
+#endif
}
/**
@@ -1448,6 +1873,12 @@ static uint8_t *nand_transfer_oob(struct nand_chip *chip, uint8_t *oob,
return NULL;
}
+#ifdef CONFIG_VENDOR_DTV
+static int nand_read_page_onek(struct mtd_info *mtd, struct nand_chip *chip, u_char *buf,u_int page_addr);
+#ifdef CONFIG_UBI_SCAN_OPTIMIZE
+static int ubi_scan_finished = 0;
+#endif
+#endif
/**
* nand_do_read_ops - [INTERN] Read data with ECC
* @mtd: MTD device structure
@@ -1485,6 +1916,18 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
buf = ops->datbuf;
oob = ops->oobbuf;
+#if defined(CONFIG_UBI_SCAN_OPTIMIZE) && defined(CONFIG_VENDOR_DTV)
+ //optimize ubi attach speed
+ if(!ubi_scan_finished && col == 0 && readlen <= 1024 && !oob )
+ {
+ //printk("%s %08x\n",__func__,readlen);
+ ret = nand_read_page_onek(mtd, chip, buf, page);
+
+ readlen = 0;
+ }
+ else
+ {
+#endif
while (1) {
bytes = min(mtd->writesize - col, readlen);
aligned = (bytes == mtd->writesize);
@@ -1493,15 +1936,21 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
if (realpage != chip->pagebuf || oob) {
bufpoi = aligned ? buf : chip->buffers->databuf;
+#if defined(CONFIG_TANGOX) || (!defined(CONFIG_MTD_NAND_MLC_BCH) && !defined(CONFIG_MTD_NAND_ECC_HW) && defined(CONFIG_VENDOR_DTV))
if (likely(sndcmd)) {
chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page);
sndcmd = 0;
}
+#endif
/* Now read the page into the buffer */
- if (unlikely(ops->mode == MTD_OPS_RAW))
+ if (unlikely(ops->mode == MTD_OPS_RAW)){
+#ifdef CONFIG_VENDOR_DTV
+ chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page);
+#endif
ret = chip->ecc.read_page_raw(mtd, chip,
bufpoi, page);
+ }
else if (!aligned && NAND_SUBPAGE_READ(chip) && !oob)
ret = chip->ecc.read_subpage(mtd, chip,
col, bytes, bufpoi);
@@ -1583,6 +2032,9 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
if (!NAND_CANAUTOINCR(chip) || !(page & blkcheck))
sndcmd = 1;
}
+#if defined(CONFIG_UBI_SCAN_OPTIMIZE) && defined(CONFIG_VENDOR_DTV)
+ }
+#endif
ops->retlen = ops->len - (size_t) readlen;
if (oob)
@@ -1614,6 +2066,14 @@ static int nand_read(struct mtd_info *mtd, loff_t from, size_t len,
struct mtd_oob_ops ops;
int ret;
+//#ifdef CONFIG_VENDOR_DTV
+ /* Do not allow reads past end of device */
+ if ((from + len) > mtd->size)
+ return -EINVAL;
+ if (!len)
+ return 0;
+//#endif
+
nand_get_device(chip, mtd, FL_READING);
ops.len = len;
ops.datbuf = buf;
@@ -2010,18 +2470,91 @@ static void nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
const uint8_t *p = buf;
uint32_t *eccpos = chip->ecc.layout->eccpos;
+#ifdef CONFIG_VENDOR_DTV
+ unsigned int reg;
+ unsigned int status;
+ //unsigned char soft_ecc_code[3];
+ int timeo = 1000;
+
+ for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
+ //enable read ecc, size 256 bytes
+ WriteRegWord((u32 __iomem *)0xfb002044, 0);
+
+ reg = ReadRegWord((u32 __iomem *)0xfb002044);
+ reg |= 0x1000000 ;
+ WriteRegWord((u32 __iomem *)0xfb002044, reg);
+
+ chip->write_buf(mtd, p, eccsize);
+
+ status = ReadRegWord((u32 __iomem *)0xfb002048);
+ while(timeo&&(status&0x8000)!=0x8000){
+ udelay(1);
+ timeo--;
+ status = ReadRegWord((u32 __iomem *)0xfb002048);
+ }
+ if(timeo<=0)
+ printk("Error: NAND ECC ready timeout\n");
+
+ ecc_calc[i+2] = ReadRegWord((u32 __iomem *)0xfb00204c)&0xff;
+ ecc_calc[i+1] = (ReadRegWord((u32 __iomem *)0xfb002048)&0x00ff0000)>>16;
+ ecc_calc[i+0] = (ReadRegWord((u32 __iomem *)0xfb002048)&0xff000000)>>24;
+
+ //nand_calc_ecc_word_256((unsigned int *)(p),soft_ecc_code);
+
+ //printk(" hardware ECC code:%02x,%02x,%02x\n",ecc_calc[i+0],ecc_calc[i+1],ecc_calc[i+2]);
+ //printf(" soft ECC code:%02x,%02x,%02x\n",soft_ecc_code[0],soft_ecc_code[1],soft_ecc_code[2]);
+
+ }
+#else
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]);
}
+#endif
+
+ 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);
+}
+
+#if defined(CONFIG_MTD_NAND_MLC_BCH) && defined(CONFIG_VENDOR_DTV)
+
+char ecc_tmp_write[250] __attribute__ ((aligned (4)));
+static int nand_write_page_mlcbch(struct mtd_info *mtd, struct nand_chip *chip,
+ u_char *buf,u_int page_addr)
+{
+ int i, eccsize = chip->ecc.size;
+ int eccbytes = chip->ecc.bytes;
+ int eccsteps = chip->ecc.steps;
+ u_char *p = buf;
+ u_char *ecc_calc = chip->buffers->ecccalc;
+ int *eccpos = chip->ecc.layout->eccpos;
+ unsigned int ret;
+
+ for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
+ BCH_ECC_enc_start(chip);
+ chip->write_buf(mtd, p, eccsize);
+ ret = BCH_ECC_enc_end((unsigned int*)ecc_tmp_write,chip);
+ if(ret)
+ {
+ printk("BCH: write page error %d at page addr %d \n",ret,page_addr);
+ return ret;
+ }
+
+ memcpy(&ecc_calc[i] ,ecc_tmp_write,eccbytes);
+ }
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;
}
+#endif
+
/**
* nand_write_page_syndrome - [REPLACEABLE] hardware ECC syndrome based page write
* @mtd: mtd info structure
@@ -2541,6 +3074,7 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
struct nand_chip *chip = mtd->priv;
loff_t rewrite_bbt[NAND_MAX_CHIPS] = {0};
unsigned int bbt_masked_page = 0xffffffff;
+ int force_erase = 0;
loff_t len;
pr_debug("%s: start = 0x%012llx, len = %llu\n",
@@ -2550,6 +3084,9 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
if (check_offs_len(mtd, instr->addr, instr->len))
return -EINVAL;
+ if (instr->retries == 0x73092215)
+ force_erase = 1;
+
/* Grab the lock and see if the device is available */
nand_get_device(chip, mtd, FL_ERASING);
@@ -2586,14 +3123,16 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
instr->state = MTD_ERASING;
while (len) {
+#ifndef CONFIG_MTD_NAND_BBM
/* Check if we have a bad block, we do not erase bad blocks! */
- if (nand_block_checkbad(mtd, ((loff_t) page) <<
+ if (!force_erase && 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;
}
+#endif
/*
* Invalidate the page cache, if we erase the block which
@@ -2713,6 +3252,11 @@ static void nand_sync(struct mtd_info *mtd)
*/
static int nand_block_isbad(struct mtd_info *mtd, loff_t offs)
{
+//#ifdef CONFIG_VENDOR_DTV
+ /* Check for invalid offset */
+ if (offs > mtd->size)
+ return -EINVAL;
+//#endif
return nand_block_checkbad(mtd, offs, 1, 0);
}
@@ -2788,12 +3332,23 @@ static void nand_set_defaults(struct nand_chip *chip, int busw)
chip->block_bad = nand_block_bad;
if (!chip->block_markbad)
chip->block_markbad = nand_default_block_markbad;
+#ifdef CONFIG_VENDOR_DTV
+ //speed up
+ if (!chip->write_buf)
+ chip->write_buf = nand_write_buf32;
+ if (!chip->read_buf)
+ chip->read_buf = nand_read_buf32;
+ if (!chip->verify_buf)
+ chip->verify_buf = nand_verify_buf32;
+#else
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;
+#endif
+
if (!chip->scan_bbt)
chip->scan_bbt = nand_default_bbt;
@@ -2851,6 +3406,22 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip,
chip->read_byte(mtd) != 'F' || chip->read_byte(mtd) != 'I')
return 0;
+#ifdef CONFIG_TANGOX
+ chip->cmdfunc(mtd, NAND_CMD_PARAM, 0, -1);
+ for (i = 0; i < 3; i++) {
+ int j = 0;
+
+ for ( j = 0; j < sizeof(*p); j++ ) {
+ *(((uint8_t *)p)+j) = chip->read_byte(mtd);
+ }
+
+ 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;
+ }
+ }
+#else
chip->cmdfunc(mtd, NAND_CMD_PARAM, 0, -1);
for (i = 0; i < 3; i++) {
chip->read_buf(mtd, (uint8_t *)p, sizeof(*p));
@@ -2860,6 +3431,7 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip,
break;
}
}
+#endif
if (i == 3)
return 0;
@@ -2888,16 +3460,29 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip,
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;
+
+ /*
+ * pages_per_block and blocks_per_lun may not be a power-of-2 size
+ * (don't ask me who thought of this...). MTD assumes that these
+ * dimensions will be power-of-2, so just truncate the remaining area.
+ */
+ mtd->erasesize = 1 << (fls(le32_to_cpu(p->pages_per_block)) - 1);
+ mtd->erasesize *= mtd->writesize;
+
mtd->oobsize = le16_to_cpu(p->spare_bytes_per_page);
- chip->chipsize = le32_to_cpu(p->blocks_per_lun);
+
+ /* See erasesize comment */
+ chip->chipsize = 1 << (fls(le32_to_cpu(p->blocks_per_lun)) - 1);
chip->chipsize *= (uint64_t)mtd->erasesize * p->lun_count;
*busw = 0;
if (le16_to_cpu(p->features) & 1)
*busw = NAND_BUSWIDTH_16;
- chip->options |= NAND_NO_READRDY | NAND_NO_AUTOINCR;
+ chip->options &= ~NAND_CHIPOPTIONS_MSK;
+ chip->options |= (NAND_NO_READRDY |
+ NAND_NO_AUTOINCR) & NAND_CHIPOPTIONS_MSK;
pr_info("ONFI flash detected\n");
return 1;
@@ -2915,6 +3500,7 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
int i, maf_idx;
u8 id_data[8];
int ret;
+ char onfi_version[3];
/* Select the device */
chip->select_chip(mtd, 0);
@@ -2941,7 +3527,7 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
- for (i = 0; i < 2; i++)
+ for (i = 0; i < 8; i++)
id_data[i] = chip->read_byte(mtd);
if (id_data[0] != *maf_id || id_data[1] != *dev_id) {
@@ -2954,12 +3540,12 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
if (!type)
type = nand_flash_ids;
- for (; type->name != NULL; type++)
+ for (; (type->name != NULL) && (type->id != 0); type++)
if (*dev_id == type->id)
break;
chip->onfi_version = 0;
- if (!type->name || !type->pagesize) {
+ if (!type->name || !type->id || !type->pagesize) {
/* Check is chip is ONFI compliant */
ret = nand_flash_detect_onfi(mtd, chip, &busw);
if (ret)
@@ -2973,7 +3559,7 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
for (i = 0; i < 8; i++)
id_data[i] = chip->read_byte(mtd);
- if (!type->name)
+ if ((!type->name) || (!type->id))
return ERR_PTR(-ENODEV);
if (!mtd->name)
@@ -2981,7 +3567,32 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
chip->chipsize = (uint64_t)type->chipsize << 20;
- if (!type->pagesize && chip->init_size) {
+#ifdef CONFIG_VENDOR_DTV
+ chip->ecc.bytes = type->eccbits;
+
+ /* Newer devices have all the information in additional id bytes */
+ /* add judgment for support Micron flash, or you can fix it use ONFI to get the chip info */
+
+ if(*maf_id ==0x2c )
+ {
+ busw = type->options & NAND_BUSWIDTH_16;
+
+ mtd->oobsize = 224;
+ mtd->writesize = 4096;
+
+ if(*dev_id == 0x38)
+ mtd->erasesize = 0x80000;
+ else if(*dev_id == 0xd3)
+ mtd->erasesize = 0x40000;
+ else if(*dev_id == 0x48)
+ mtd->erasesize = 0x100000;
+ else
+ printk("%s[%d] ERROR: unknown dev_id!\n", __func__, __LINE__);
+ }
+#else
+ if (0);
+#endif
+ else 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) {
@@ -2995,14 +3606,17 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
* Field definitions are in the following datasheets:
* Old style (4,5 byte ID): Samsung K9GAG08U0M (p.32)
* New style (6 byte ID): Samsung K9GBG08U0M (p.40)
+ * Micron (5 byte ID): Micron MT29F16G08MAA (p.24)
+ * Note: Micron rule is based on heuristics for
+ * newer chips
*
* Check for wraparound + Samsung ID + nonzero 6th byte
* to decide what to do.
*/
- if (id_data[0] == id_data[6] && id_data[1] == id_data[7] &&
+ if ((id_data[0] == id_data[6] && id_data[1] == id_data[7] &&
id_data[0] == NAND_MFR_SAMSUNG &&
(chip->cellinfo & NAND_CI_CELLTYPE_MSK) &&
- id_data[5] != 0x00) {
+ id_data[5] != 0x00) || (id_data[0] == NAND_MFR_MIRA)) {
/* Calc pagesize */
mtd->writesize = 2048 << (extid & 0x03);
extid >>= 2;
@@ -3026,27 +3640,71 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
mtd->erasesize = (128 * 1024) <<
(((extid >> 1) & 0x04) | (extid & 0x03));
busw = 0;
- } else {
+ } else if (id_data[0] == NAND_MFR_ESMT) {
/* Calc pagesize */
mtd->writesize = 1024 << (extid & 0x03);
extid >>= 2;
/* Calc oobsize */
- mtd->oobsize = (8 << (extid & 0x01)) *
- (mtd->writesize >> 9);
+ mtd->oobsize = (8 << (extid & 0x01)) * (mtd->writesize / 512) ;
extid >>= 2;
- /* Calc blocksize. Blocksize is multiples of 64KiB */
+ /* Calc blocksize */
mtd->erasesize = (64 * 1024) << (extid & 0x03);
+ busw = 0;
+ } else {
+ /* Calc pagesize */
+ mtd->writesize = 1024 << (extid & 0x03);
extid >>= 2;
- /* Get buswidth information */
- busw = (extid & 0x01) ? NAND_BUSWIDTH_16 : 0;
+
+ /* Check for 5 byte ID + Micron + read more 0x00 */
+ if (id_data[0] == NAND_MFR_MICRON && id_data[4] != 0x00
+ && mtd->writesize >= 4096
+ && id_data[5] == 0x00
+ && id_data[6] == 0x00) {
+ /* OOB is 218B/224B per 4KiB pagesize */
+ mtd->oobsize = ((extid & 0x03) == 0x03 ? 218 :
+ 224) << (mtd->writesize >> 13);
+ extid >>= 3;
+ /* Blocksize is multiple of 64KiB */
+ mtd->erasesize = mtd->writesize <<
+ (extid & 0x03) << 6;
+ /* All Micron have busw x8? */
+ printk("[%s] All Micron : %d\n", __func__, extid);
+ busw = 0;
+ } else {
+ /* Calc oobsize */
+ mtd->oobsize = (8 << (extid & 0x01)) *
+ (mtd->writesize >> 9);
+ extid >>= 2;
+ /* Calc blocksize (multiples of 64KiB) */
+ mtd->erasesize = (64 * 1024) << (extid & 0x03);
+ extid >>= 2;
+ /* Get buswidth information */
+ busw = (extid & 0x01) ? NAND_BUSWIDTH_16 : 0;
+ }
}
+#ifdef CONFIG_VENDOR_DTV
+ } else if (*maf_id == 0xad && dev_id == 0xd5 ){ //hynix
+ busw = type->options & NAND_BUSWIDTH_16;
+ mtd->oobsize = 448;
+ mtd->writesize = 8192;
+ mtd->erasesize = 0x200000;
+ chip->ecc.bytes = type->eccbits;
+ printk(KERN_DEBUG "chip->ecc.bytes is 0x%x\n",chip->ecc.bytes);
+#endif
} else {
/*
* Old devices have chip data hardcoded in the device id table.
*/
mtd->erasesize = type->erasesize;
mtd->writesize = type->pagesize;
+#ifdef CONFIG_VENDOR_DTV
+ if(type->oobsize)
+ mtd->oobsize = type->oobsize;
+ else
+ mtd->oobsize = mtd->writesize / 32;
+#else
mtd->oobsize = mtd->writesize / 32;
+#endif
busw = type->options & NAND_BUSWIDTH_16;
/*
@@ -3062,8 +3720,9 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
mtd->erasesize <<= ((id_data[3] & 0x03) << 1);
}
}
- /* Get chip options */
- chip->options |= type->options;
+ /* Get chip options, preserve non chip based options */
+ chip->options &= ~NAND_CHIPOPTIONS_MSK;
+ chip->options |= type->options & NAND_CHIPOPTIONS_MSK;
/*
* Check if chip is not a Samsung device. Do not clear the
@@ -3129,10 +3788,14 @@ ident_done:
*/
if ((chip->cellinfo & NAND_CI_CELLTYPE_MSK) &&
(*maf_id == NAND_MFR_SAMSUNG ||
+ *maf_id == NAND_MFR_MIRA ||
+ *maf_id == NAND_MFR_ESMT ||
*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_MIRA ||
+ *maf_id == NAND_MFR_ESMT ||
*maf_id == NAND_MFR_HYNIX ||
*maf_id == NAND_MFR_TOSHIBA ||
*maf_id == NAND_MFR_AMD ||
@@ -3141,6 +3804,7 @@ ident_done:
*maf_id == NAND_MFR_MICRON))
chip->bbt_options |= NAND_BBT_SCAN2NDPAGE;
+
/* Check for AND chips with 4 page planes */
if (chip->options & NAND_4PAGE_ARRAY)
chip->erase_cmd = multi_erase_cmd;
@@ -3156,7 +3820,42 @@ ident_done:
nand_manuf_ids[maf_idx].name,
chip->onfi_version ? chip->onfi_params.model : type->name);
+ if (chip->onfi_version)
+ snprintf(onfi_version, sizeof(onfi_version), "%d.%d",
+ chip->onfi_version / 10,
+ chip->onfi_version % 10);
+ else
+ snprintf(onfi_version, sizeof(onfi_version), "%s", "0");
+
+ /* ID Data Mapping */
+ for (i = 0; i < 8; i++)
+ {
+ mtd->id_data[i] = id_data[i];
+ }
+
+ mtd->onfi_version = kstrdup(onfi_version, GFP_KERNEL);
+ if (!mtd->onfi_version)
+ return ERR_PTR(-ENOMEM);
+
+ mtd->nand_manufacturer = kstrdup(nand_manuf_ids[maf_idx].name, GFP_KERNEL);
+ if (!mtd->nand_manufacturer) {
+ ret = -ENOMEM;
+ goto out_onfi_version;
+ }
+
+ mtd->nand_type = kstrdup(type->name, GFP_KERNEL);
+ if (!mtd->nand_type) {
+ ret = -ENOMEM;
+ goto out_nand_type;
+ }
+
return type;
+
+out_nand_type:
+ kfree(mtd->nand_type);
+out_onfi_version:
+ kfree(mtd->onfi_version);
+ return ERR_PTR(ret);
}
/**
@@ -3176,6 +3875,7 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips,
int i, busw, nand_maf_id, nand_dev_id;
struct nand_chip *chip = mtd->priv;
struct nand_flash_dev *type;
+ int err;
/* Get buswidth to select the correct functions */
busw = chip->options & NAND_BUSWIDTH_16;
@@ -3190,7 +3890,8 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips,
if (!(chip->options & NAND_SCAN_SILENT_NODEV))
pr_warn("No NAND device found\n");
chip->select_chip(mtd, -1);
- return PTR_ERR(type);
+ err = PTR_ERR(type);
+ goto out_error;
}
/* Check for a chip array */
@@ -3212,7 +3913,20 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips,
chip->numchips = i;
mtd->size = i * chip->chipsize;
+ chip->maf_id = nand_maf_id;
+ chip->dev_id = type->id;
+
return 0;
+
+out_error:
+ if (mtd->nand_type)
+ kfree(mtd->nand_type);
+ if (mtd->nand_manufacturer)
+ kfree(mtd->nand_manufacturer);
+ if (mtd->onfi_version)
+ kfree(mtd->onfi_version);
+
+ return err;
}
EXPORT_SYMBOL(nand_scan_ident);
@@ -3254,11 +3968,28 @@ int nand_scan_tail(struct mtd_info *mtd)
chip->ecc.layout = &nand_oob_16;
break;
case 64:
+#if defined(CONFIG_MTD_NAND_MLC_BCH) && defined(CONFIG_VENDOR_DTV)
+ chip->ecc.layout = &nand_oob_mlcbch_64;
+#else
chip->ecc.layout = &nand_oob_64;
+#endif
break;
case 128:
chip->ecc.layout = &nand_oob_128;
break;
+ case 224:
+ chip->ecc.layout = &nand_oob_mlcbch_224;
+ //8 bit bch ecc for Micron 1G flash, 224 oobsize use 128 for ecc
+ //for(i=224-112,k=0;i<224;k++,i++)
+ // chip->ecc.layout->eccpos[k]=i;
+ //chip->ecc.layout->oobfree[0].offset=3;
+ //chip->ecc.layout->oobfree[0].length=(224-112-3);
+ break;
+#ifndef CONFIG_MTD_NAND_ECC_512
+ case 448:
+ chip->ecc.layout = &nand_oob_mlcbch_448;
+ break;
+#endif
default:
pr_warn("No oob scheme defined for oobsize %d\n",
mtd->oobsize);
@@ -3300,6 +4031,37 @@ int nand_scan_tail(struct mtd_info *mtd)
chip->ecc.read_oob = nand_read_oob_std;
if (!chip->ecc.write_oob)
chip->ecc.write_oob = nand_write_oob_std;
+#ifdef CONFIG_VENDOR_DTV
+ chip->ecc.size = 256;
+ chip->ecc.bytes = 3;
+ break;
+
+#ifdef CONFIG_MTD_NAND_MLC_BCH
+ case NAND_MLC_BCH:
+ chip->ecc.read_page = nand_read_page_mlcbch;
+ chip->ecc.write_page = nand_write_page_mlcbch;
+ 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;
+
+ // do ECC control reset. REG_BCH_ECC_CONTROL = 0xfb002200
+ WriteRegWord((u32 __iomem *)0xfb002200, (ReadRegWord((u32 __iomem *)0xfb002200)&(~0x4)));
+ WriteRegWord((u32 __iomem *)0xfb002200, 0x1000);
+ while(ReadRegWord((u32 __iomem *)0xfb002200)&0x1000!=0)
+ ;
+ WriteRegWord((u32 __iomem *)0xfb002200, 0x02);
+
+ #ifdef CONFIG_MTD_NAND_ECC_512
+ printk(KERN_DEBUG "NAND: BCH ECC,size 512B.\n");
+ chip->ecc.size = 512;
+ #else
+ printk(KERN_DEBUG "NAND: BCH ECC,size 1024B.\n");
+ chip->ecc.size = 1024;
+ #endif
+ break;
+#endif
+#endif //ifdef CONFIG_VENDOR_DTV
case NAND_ECC_HW_SYNDROME:
if ((!chip->ecc.calculate || !chip->ecc.correct ||
@@ -3437,12 +4199,20 @@ int nand_scan_tail(struct mtd_info *mtd)
!(chip->cellinfo & NAND_CI_CELLTYPE_MSK)) {
switch (chip->ecc.steps) {
case 2:
+#if defined(CONFIG_MTD_UBI) && defined(CONFIG_VENDOR_DTV)
+ mtd->subpage_sft = 0; //fix me, to simplify ubi config
+#else
mtd->subpage_sft = 1;
+#endif
break;
case 4:
case 8:
case 16:
+#if defined(CONFIG_MTD_UBI) && defined(CONFIG_VENDOR_DTV)
+ mtd->subpage_sft = 0; //fix me, to simplify ubi config
+#else
mtd->subpage_sft = 2;
+#endif
break;
}
}
@@ -3517,6 +4287,44 @@ int nand_scan(struct mtd_info *mtd, int maxchips)
{
int ret;
+#ifdef CONFIG_VENDOR_DTV
+ struct nand_chip *chip;
+#ifdef CONFIG_MIPS_TRIDENT_FUSION_ANDROID
+ //protect NAND init
+ NAND_spin_lock_hw_dump(SPIN_REG_ADDR);
+#endif
+
+#ifdef CONFIG_NAND_MODE
+ /* switch the nand source clock from 100Hz to 200Hz for this version of NAND mode setting
+ * if the souce clock is not match the NAND mode, will cause the DMA read time out error */
+
+ unsigned char nand_clock = ReadRegByte((void*)0xf500e849);
+ nand_clock &= 0xcf;
+ nand_clock |= 0x20;
+ WriteRegByte((void*)0xf500e849,nand_clock);
+
+ /* switch the nand source clock 200Hz clock for write,
+ if the clock is not match the NAND init setting such like 1b002004 = 0x21, will cause WP*/
+ WriteRegWord((void*)0xfb002004, 0x00000067);
+
+ unsigned int write_clock = ReadRegWord((void*)0xfb002070);
+ write_clock |= 0x100;
+ WriteRegWord((void*)0xfb002070,write_clock);
+
+ write_clock = ReadRegWord((void*)0xfb002020);
+ write_clock &= 0xffff3f3f;
+ WriteRegWord((void*)0xfb002020,write_clock);
+
+ /*we set 205c only here,it changed in UXL*/
+#ifdef CONFIG_MIPS_TRIDENT_UXL
+ WriteRegWord((void*)0xfb00205c, 0x40193333);
+#else
+ WriteRegWord((void*)0xfb00205c, 0x40193333);
+#endif
+
+#endif //ifdef CONFIG_NAND_MODE
+#endif //ifdef CONFIG_VENDOR_DTV
+
/* Many callers got this wrong, so check for it for a while... */
if (!mtd->owner && caller_is_module()) {
pr_crit("%s called with NULL mtd->owner!\n", __func__);
@@ -3526,7 +4334,25 @@ int nand_scan(struct mtd_info *mtd, int maxchips)
ret = nand_scan_ident(mtd, maxchips, NULL);
if (!ret)
ret = nand_scan_tail(mtd);
+
+#ifdef CONFIG_MIPS_TRIDENT_FUSION_ANDROID
+ NAND_spin_unlock_hw(SPIN_REG_ADDR);
+#endif
+
+#ifdef CONFIG_VENDOR_DTV
+ chip = mtd->priv;
+
+ if (chip->options & NAND_SKIP_BBTSCAN)
+ return ret;
+/*scan_bbt will be processed in nand_scan_tail*/
+//#ifdef CONFIG_MTD_UBI
+// return chip->scan_bbt(mtd);
+//#else
return ret;
+//#endif
+#else
+ return ret;
+#endif
}
EXPORT_SYMBOL(nand_scan);
@@ -3541,7 +4367,9 @@ void nand_release(struct mtd_info *mtd)
if (chip->ecc.mode == NAND_ECC_SOFT_BCH)
nand_bch_free((struct nand_bch_control *)chip->ecc.priv);
+#ifndef CONFIG_VENDOR_DTV
mtd_device_unregister(mtd);
+#endif
/* Free bad block table memory */
kfree(chip->bbt);
@@ -3552,6 +4380,10 @@ void nand_release(struct mtd_info *mtd)
if (chip->badblock_pattern && chip->badblock_pattern->options
& NAND_BBT_DYNAMICSTRUCT)
kfree(chip->badblock_pattern);
+
+ kfree(mtd->nand_type);
+ kfree(mtd->nand_manufacturer);
+ kfree(mtd->onfi_version);
}
EXPORT_SYMBOL_GPL(nand_release);
diff --git a/drivers/mtd/nand/nand_ids.c b/drivers/mtd/nand/nand_ids.c
index af4fe8ca7b5e..03c687c3b8a4 100644
--- a/drivers/mtd/nand/nand_ids.c
+++ b/drivers/mtd/nand/nand_ids.c
@@ -23,6 +23,232 @@
*/
struct nand_flash_dev nand_flash_ids[] = {
+#ifdef CONFIG_VENDOR_DTV
+#ifdef CONFIG_MTD_NAND_MLC_BCH
+#ifdef CONFIG_MTD_NAND_MUSEUM_IDS
+// unsigned long eccbits;
+ {"NAND 1MiB 5V 8-bit", 0x0,0x6e, 256, 1, 0x1000, 0x0,0,14},
+ {"NAND 2MiB 5V 8-bit", 0x0,0x64, 256, 2, 0x1000, 0x0,0,14},
+ {"NAND 4MiB 5V 8-bit", 0x0,0x6b, 512, 4, 0x2000, 0x0,0,14},
+ {"NAND 1MiB 3,3V 8-bit", 0x0,0xe8, 256, 1, 0x1000, 0x0,0,14},
+ {"NAND 1MiB 3,3V 8-bit", 0x0,0xec, 256, 1, 0x1000, 0x0,0,14},
+ {"NAND 2MiB 3,3V 8-bit", 0x0,0xea, 256, 2, 0x1000, 0x0,0,14},
+ {"NAND 4MiB 3,3V 8-bit", 0xff,0xd5, 512, 4, 0x2000, 0x0,0,14},
+ {"NAND 4MiB 3,3V 8-bit", 0x0,0xe3, 512, 4, 0x2000, 0x0,0,14},
+ {"NAND 4MiB 3,3V 8-bit", 0x0,0xe5, 512, 4, 0x2000, 0x0,0,14},
+ {"NAND 8MiB 3,3V 8-bit", 0x0,0xd6, 512, 8, 0x2000, 0x0,0,14},
+
+ {"NAND 8MiB 1,8V 8-bit", 0x0,0x39, 512, 8, 0x2000, 0x0,0,14},
+ {"NAND 8MiB 3,3V 8-bit", 0x0,0xe6, 512, 8, 0x2000, 0x0,0,14},
+ {"NAND 8MiB 1,8V 16-bit", 0x0,0x49, 512, 8, 0x2000, 0x0,NAND_BUSWIDTH_16,14},
+ {"NAND 8MiB 3,3V 16-bit", 0x0,0x59, 512, 8, 0x2000, 0x0,NAND_BUSWIDTH_16,14},
+#endif
+
+ {"NAND 16MiB 1,8V 8-bit", 0x0,0x33, 512, 16, 0x4000, 0x0,0,14},
+ {"NAND 16MiB 3,3V 8-bit", 0x0,0x73, 512, 16, 0x4000, 0x0,0,14},
+ {"NAND 16MiB 1,8V 16-bit", 0x0,0x43, 512, 16, 0x4000, 0x0,NAND_BUSWIDTH_16,14},
+ {"NAND 16MiB 3,3V 16-bit", 0x0,0x53, 512, 16, 0x4000, 0x0,NAND_BUSWIDTH_16,14},
+
+ {"NAND 32MiB 1,8V 8-bit", 0x0,0x35, 512, 32, 0x4000, 0x0,0,14},
+ {"NAND 32MiB 3,3V 8-bit", 0x0,0x75, 512, 32, 0x4000, 0x0,0,14},
+ {"NAND 32MiB 1,8V 16-bit", 0x0,0x45, 512, 32, 0x4000, 0x0,NAND_BUSWIDTH_16,14},
+ {"NAND 32MiB 3,3V 16-bit", 0x0,0x55, 512, 32, 0x4000, 0x0,NAND_BUSWIDTH_16,14},
+
+ {"NAND 64MiB 1,8V 8-bit", 0x0,0x36, 512, 64, 0x4000, 0x0,0,14},
+ {"NAND 64MiB 3,3V 8-bit", 0x0,0x76, 512, 64, 0x4000, 0x0,0,14},
+ {"NAND 64MiB 1,8V 16-bit", 0x0,0x46, 512, 64, 0x4000, 0x0,NAND_BUSWIDTH_16,14},
+ {"NAND 64MiB 3,3V 16-bit", 0x0,0x56, 512, 64, 0x4000, 0x0,NAND_BUSWIDTH_16,14},
+
+ {"NAND 128MiB 1,8V 8-bit", 0x0,0x78, 512, 128, 0x4000, 0x0,0,14},
+ {"NAND 128MiB 1,8V 8-bit", 0x0,0x39, 512, 128, 0x4000, 0x0,0,14},
+ {"NAND 128MiB 3,3V 8-bit", 0x0,0x79, 512, 128, 0x4000, 0x0,0,14},
+ {"NAND 128MiB 1,8V 16-bit", 0x0,0x72, 512, 128, 0x4000, 0x0,NAND_BUSWIDTH_16,14},
+ {"NAND 128MiB 1,8V 16-bit", 0x0,0x49, 512, 128, 0x4000, 0x0,NAND_BUSWIDTH_16,14},
+ {"NAND 128MiB 3,3V 16-bit", 0x0,0x74, 512, 128, 0x4000, 0x0,NAND_BUSWIDTH_16,14},
+ {"NAND 128MiB 3,3V 16-bit", 0x0,0x59, 512, 128, 0x4000, 0x0,NAND_BUSWIDTH_16,14},
+
+ {"NAND 256MiB 3,3V 8-bit", 0x0,0x71, 512, 256, 0x4000, 0x0,0,14},
+
+ /*
+ * 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 | NAND_NO_READRDY | NAND_NO_AUTOINCR)
+#define LP_OPTIONS16 (LP_OPTIONS | NAND_BUSWIDTH_16)
+
+ /*512 Megabit */
+ {"NAND 64MiB 1,8V 8-bit", 0x0,0xA2, 0, 64, 0, 0x0,LP_OPTIONS,14},
+ {"NAND 64MiB 3,3V 8-bit", 0x0,0xF2, 0, 64, 0, 0x0,LP_OPTIONS,14},
+ {"NAND 64MiB 1,8V 16-bit", 0x0,0xB2, 0, 64, 0, 0x0,LP_OPTIONS16,14},
+ {"NAND 64MiB 3,3V 16-bit", 0x0,0xC2, 0, 64, 0, 0x0,LP_OPTIONS16,14},
+
+ /* 1 Gigabit */
+ {"NAND 128MiB 1,8V 8-bit", 0x0,0xA1, 0, 128, 0, 0x0,LP_OPTIONS,14},
+ {"NAND 128MiB 3,3V 8-bit", 0x0,0xF1, 2048, 128, 0x20000,0x0, LP_OPTIONS,14},
+ {"NAND 128MiB 1,8V 16-bit", 0x0,0xB1, 0, 128, 0, 0x0,LP_OPTIONS16,14},
+ {"NAND 128MiB 3,3V 16-bit", 0x0,0xC1, 0, 128, 0, 0x0,LP_OPTIONS16,14},
+
+ /* 2 Gigabit */
+ {"NAND 256MiB 1,8V 8-bit", 0x0,0xAA, 0, 256, 0, 0x0,LP_OPTIONS,14},
+ {"NAND 256MiB 3,3V 8-bit", 0x0,0xDA, 0, 256, 0, 0x0,LP_OPTIONS,14},
+ {"NAND 256MiB 1,8V 16-bit", 0x0,0xBA, 0, 256, 0, 0x0,LP_OPTIONS16,14},
+ {"NAND 256MiB 3,3V 16-bit", 0x0,0xCA, 0, 256, 0, 0x0,LP_OPTIONS16,14},
+
+ /* 4 Gigabit */
+ {"NAND 512MiB 1,8V 8-bit", 0x0,0xAC, 0, 512, 0, 0x0,LP_OPTIONS,14},
+ {"NAND 512MiB 3,3V 8-bit", 0xff,0xDC, 0, 512, 0, 0x0,LP_OPTIONS,14},
+ {"NAND 512MiB 1,8V 16-bit", 0x0,0xBC, 0, 512, 0, 0x0,LP_OPTIONS16,14},
+ {"NAND 512MiB 3,3V 16-bit", 0x0,0xCC, 0, 512, 0, 0x0,LP_OPTIONS16,14},
+
+ /* 8 Gigabit */
+ {"NAND 1GiB 1,8V 8-bit", 0x0,0xA3, 0, 1024, 0, 0x0,LP_OPTIONS,14},
+ {"NAND 1GiB 3,3V 8-bit", 0x2c,0xD3, 4096, 1024, 0x80000, 224,LP_OPTIONS,14},
+ {"NAND 1GiB 3,3V 8-bit", 0x2c,0x38,4096, 1024, 0x80000,224,LP_OPTIONS,14},
+ {"NAND 1GiB 3,3V 8-bit", 0x0,0x38,4096, 1024, 0x80000,0x0,LP_OPTIONS,14},
+
+ {"NAND 1GiB 1,8V 16-bit", 0x0,0xB3, 0, 1024, 0, 0x0,LP_OPTIONS16,14},
+ {"NAND 1GiB 3,3V 16-bit", 0x0,0xC3, 0, 1024, 0, 0x0,LP_OPTIONS16,14},
+
+ //samsung chip, same dev id , different chip size
+ {"NAND 1GiB/2GiB 3,3V 8-bit", 0xec,0xD3, 0, 0, 0, 0,LP_OPTIONS,14},
+
+ /* 16 Gigabit */
+ {"NAND 2GiB 1,8V 8-bit", 0x0,0xA5, 0, 2048, 0, 0x0,LP_OPTIONS,42},
+ {"NAND 2GiB 3,3V 8-bit", 0xec,0xD5, 8192, 2048, 0x100000, 512,LP_OPTIONS,42},
+ {"NAND 2GiB 3,3V 8-bit", 0xad,0xD5, 8192, 2048, 0x200000, 448,LP_OPTIONS|NAND_MLC,42},
+ {"NAND 2GiB 1,8V 16-bit", 0x0,0xB5, 0, 2048, 0, 0x0,LP_OPTIONS16,42},
+ {"NAND 2GiB 3,3V 16-bit", 0x0,0xC5, 0, 2048, 0, 0x0,LP_OPTIONS16,42},
+
+ /*2013.4.2 add for Micron MT29F16G*/
+ {"NAND 2GiB 3,3V 8-bit", 0x2c, 0x48, 4096, 2048, 0x100000,224, LP_OPTIONS|NAND_MLC,42},
+ /*
+ * 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", 0x0,0x01, 2048, 128, 0x4000,0x0,
+ NAND_IS_AND | NAND_NO_AUTOINCR |NAND_NO_READRDY | NAND_4PAGE_ARRAY |
+ BBT_AUTO_REFRESH,14},
+
+#else /*not define CONFIG_MTD_NAND_MLC_BCH*/
+#ifdef CONFIG_MTD_NAND_MUSEUM_IDS
+ {"NAND 1MiB 5V 8-bit", 0x0,0x6e, 256, 1, 0x1000, 0x0,0},
+ {"NAND 2MiB 5V 8-bit", 0x0,0x64, 256, 2, 0x1000, 0x0,0},
+ {"NAND 4MiB 5V 8-bit", 0x0,0x6b, 512, 4, 0x2000, 0x0,0},
+ {"NAND 1MiB 3,3V 8-bit", 0x0,0xe8, 256, 1, 0x1000, 0x0,0},
+ {"NAND 1MiB 3,3V 8-bit", 0x0,0xec, 256, 1, 0x1000, 0x0,0},
+ {"NAND 2MiB 3,3V 8-bit", 0x0,0xea, 256, 2, 0x1000, 0x0,0},
+ {"NAND 4MiB 3,3V 8-bit", 0xff,0xd5, 512, 4, 0x2000, 0x0,0},
+ {"NAND 4MiB 3,3V 8-bit", 0x0,0xe3, 512, 4, 0x2000, 0x0,0},
+ {"NAND 4MiB 3,3V 8-bit", 0x0,0xe5, 512, 4, 0x2000, 0x0,0},
+ {"NAND 8MiB 3,3V 8-bit", 0x0,0xd6, 512, 8, 0x2000, 0x0,0},
+
+ {"NAND 8MiB 1,8V 8-bit", 0x0,0x39, 512, 8, 0x2000, 0x0,0},
+ {"NAND 8MiB 3,3V 8-bit", 0x0,0xe6, 512, 8, 0x2000, 0x0,0},
+ {"NAND 8MiB 1,8V 16-bit", 0x0,0x49, 512, 8, 0x2000, 0x0,NAND_BUSWIDTH_16},
+ {"NAND 8MiB 3,3V 16-bit", 0x0,0x59, 512, 8, 0x2000, 0x0,NAND_BUSWIDTH_16},
+#endif
+
+ {"NAND 16MiB 1,8V 8-bit", 0x0,0x33, 512, 16, 0x4000, 0x0,0},
+ {"NAND 16MiB 3,3V 8-bit", 0x0,0x73, 512, 16, 0x4000, 0x0,0},
+ {"NAND 16MiB 1,8V 16-bit", 0x0,0x43, 512, 16, 0x4000, 0x0,NAND_BUSWIDTH_16},
+ {"NAND 16MiB 3,3V 16-bit", 0x0,0x53, 512, 16, 0x4000, 0x0,NAND_BUSWIDTH_16},
+
+ {"NAND 32MiB 1,8V 8-bit", 0x0,0x35, 512, 32, 0x4000, 0x0,0},
+ {"NAND 32MiB 3,3V 8-bit", 0x0,0x75, 512, 32, 0x4000, 0x0,0},
+ {"NAND 32MiB 1,8V 16-bit", 0x0,0x45, 512, 32, 0x4000, 0x0,NAND_BUSWIDTH_16},
+ {"NAND 32MiB 3,3V 16-bit", 0x0,0x55, 512, 32, 0x4000, 0x0,NAND_BUSWIDTH_16},
+
+ {"NAND 64MiB 1,8V 8-bit", 0x0,0x36, 512, 64, 0x4000, 0x0,0},
+ {"NAND 64MiB 3,3V 8-bit", 0x0,0x76, 512, 64, 0x4000, 0x0,0},
+ {"NAND 64MiB 1,8V 16-bit", 0x0,0x46, 512, 64, 0x4000, 0x0,NAND_BUSWIDTH_16},
+ {"NAND 64MiB 3,3V 16-bit", 0x0,0x56, 512, 64, 0x4000, 0x0,NAND_BUSWIDTH_16},
+
+ {"NAND 128MiB 1,8V 8-bit", 0x0,0x78, 512, 128, 0x4000, 0x0,0},
+ {"NAND 128MiB 1,8V 8-bit", 0x0,0x39, 512, 128, 0x4000, 0x0,0},
+ {"NAND 128MiB 3,3V 8-bit", 0x0,0x79, 512, 128, 0x4000, 0x0,0},
+ {"NAND 128MiB 1,8V 16-bit", 0x0,0x72, 512, 128, 0x4000, 0x0,NAND_BUSWIDTH_16},
+ {"NAND 128MiB 1,8V 16-bit", 0x0,0x49, 512, 128, 0x4000, 0x0,NAND_BUSWIDTH_16},
+ {"NAND 128MiB 3,3V 16-bit", 0x0,0x74, 512, 128, 0x4000, 0x0,NAND_BUSWIDTH_16},
+ {"NAND 128MiB 3,3V 16-bit", 0x0,0x59, 512, 128, 0x4000, 0x0,NAND_BUSWIDTH_16},
+
+ {"NAND 256MiB 3,3V 8-bit", 0x0,0x71, 512, 256, 0x4000, 0x0,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 | NAND_NO_READRDY | NAND_NO_AUTOINCR)
+#define LP_OPTIONS16 (LP_OPTIONS | NAND_BUSWIDTH_16)
+
+ /*512 Megabit */
+ {"NAND 64MiB 1,8V 8-bit", 0x0,0xA2, 0, 64, 0, 0x0,LP_OPTIONS},
+ {"NAND 64MiB 3,3V 8-bit", 0x0,0xF2, 0, 64, 0, 0x0,LP_OPTIONS},
+ {"NAND 64MiB 1,8V 16-bit", 0x0,0xB2, 0, 64, 0, 0x0,LP_OPTIONS16},
+ {"NAND 64MiB 3,3V 16-bit", 0x0,0xC2, 0, 64, 0, 0x0,LP_OPTIONS16},
+
+ /* 1 Gigabit */
+ {"NAND 128MiB 1,8V 8-bit", 0x0,0xA1, 0, 128, 0, 0x0,LP_OPTIONS},
+ {"NAND 128MiB 3,3V 8-bit", 0x0,0xF1, 2048, 128, 0x20000,0x0, LP_OPTIONS},
+ {"NAND 128MiB 1,8V 16-bit", 0x0,0xB1, 0, 128, 0, 0x0,LP_OPTIONS16},
+ {"NAND 128MiB 3,3V 16-bit", 0x0,0xC1, 0, 128, 0, 0x0,LP_OPTIONS16},
+
+ /* 2 Gigabit */
+ {"NAND 256MiB 1,8V 8-bit", 0x0,0xAA, 0, 256, 0, 0x0,LP_OPTIONS},
+ {"NAND 256MiB 3,3V 8-bit", 0x0,0xDA, 0, 256, 0, 0x0,LP_OPTIONS},
+ {"NAND 256MiB 1,8V 16-bit", 0x0,0xBA, 0, 256, 0, 0x0,LP_OPTIONS16},
+ {"NAND 256MiB 3,3V 16-bit", 0x0,0xCA, 0, 256, 0, 0x0,LP_OPTIONS16},
+
+ /* 4 Gigabit */
+ {"NAND 512MiB 1,8V 8-bit", 0x0,0xAC, 0, 512, 0, 0x0,LP_OPTIONS},
+ {"NAND 512MiB 3,3V 8-bit", 0xff,0xDC, 0, 512, 0, 0x0,LP_OPTIONS},
+ {"NAND 512MiB 1,8V 16-bit", 0x0,0xBC, 0, 512, 0, 0x0,LP_OPTIONS16},
+ {"NAND 512MiB 3,3V 16-bit", 0x0,0xCC, 0, 512, 0, 0x0,LP_OPTIONS16},
+
+ /* 8 Gigabit */
+ {"NAND 1GiB 1,8V 8-bit", 0x0,0xA3, 0, 1024, 0, 0x0,LP_OPTIONS},
+ {"NAND 1GiB 3,3V 8-bit", 0x2c,0xD3, 4096, 1024, 0x80000, 224,LP_OPTIONS},
+ {"NAND 1GiB 3,3V 8-bit", 0x2c,0x38,4096, 1024, 0x80000,224,LP_OPTIONS},
+ {"NAND 1GiB 3,3V 8-bit", 0x0,0x38,4096, 1024, 0x80000,0x0,LP_OPTIONS},
+
+ {"NAND 1GiB 1,8V 16-bit", 0x0,0xB3, 0, 1024, 0, 0x0,LP_OPTIONS16},
+ {"NAND 1GiB 3,3V 16-bit", 0x0,0xC3, 0, 1024, 0, 0x0,LP_OPTIONS16},
+
+ //samsung chip, same dev id , different chip size
+ {"NAND 1GiB/2GiB 3,3V 8-bit", 0xec,0xD3, 0, 0, 0, 0,LP_OPTIONS},
+
+ /* 16 Gigabit */
+ {"NAND 2GiB 1,8V 8-bit", 0x0,0xA5, 0, 2048, 0, 0x0,LP_OPTIONS},
+ {"NAND 2GiB 3,3V 8-bit", 0xec,0xD5, 8192, 2048, 0x100000, 512,LP_OPTIONS},
+ {"NAND 2GiB 3,3V 8-bit", 0xad,0xD5, 8192, 2048, 0x200000, 448,LP_OPTIONS},
+ {"NAND 2GiB 1,8V 16-bit", 0x0,0xB5, 0, 2048, 0, 0x0,LP_OPTIONS16},
+ {"NAND 2GiB 3,3V 16-bit", 0x0,0xC5, 0, 2048, 0, 0x0,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", 0x0,0x01, 2048, 128, 0x4000,0x0,
+ NAND_IS_AND | NAND_NO_AUTOINCR |NAND_NO_READRDY | NAND_4PAGE_ARRAY |
+ BBT_AUTO_REFRESH
+ },
+
+#endif /* not define CONFIG_MTD_NAND_MLC_BCH */
+
+#else /* not define CONFIG_VENDOR_DTV */
#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},
@@ -90,7 +316,7 @@ struct nand_flash_dev nand_flash_ids[] = {
{"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},
+ {"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},
@@ -107,22 +333,26 @@ struct nand_flash_dev nand_flash_ids[] = {
/* 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 3,3V 8-bit", 0x38, 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 3,3V 8-bit", 0x48, 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 3,3V 8-bit", 0x68, 0, 4096, 0, LP_OPTIONS},
{"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 3,3V 8-bit", 0x88, 0, 8192, 0, LP_OPTIONS},
{"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},
@@ -135,6 +365,7 @@ struct nand_flash_dev nand_flash_ids[] = {
{"NAND 16GiB 3,3V 16-bit", 0x4A, 0, 16384, 0, LP_OPTIONS16},
/* 256 Gigabit */
+ {"NAND 32GiB 3,3V 8-bit", 0xA8, 0, 32768, 0, LP_OPTIONS},
{"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},
@@ -161,7 +392,23 @@ struct nand_flash_dev nand_flash_ids[] = {
BBT_AUTO_REFRESH
},
- {NULL,}
+ /*
+ * Fill-in gaps, may be refilled at the runtime
+ */
+ {" ", 0, },
+ {" ", 0, },
+ {" ", 0, },
+ {" ", 0, },
+ {" ", 0, },
+ {" ", 0, },
+ {" ", 0, },
+ {" ", 0, },
+#endif /* not define CONFIG_VENDOR_DTV */
+
+ /*
+ * Terminates the table
+ */
+ {NULL, },
};
/*
@@ -178,6 +425,8 @@ struct nand_manufacturers nand_manuf_ids[] = {
{NAND_MFR_MICRON, "Micron"},
{NAND_MFR_AMD, "AMD"},
{NAND_MFR_MACRONIX, "Macronix"},
+ {NAND_MFR_ESMT, "ESMT"},
+ {NAND_MFR_MIRA, "MIRA"},
{0x0, "Unknown"}
};
diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c
index b9cbd65f49b5..a3b0336dc374 100644
--- a/drivers/mtd/nand/nandsim.c
+++ b/drivers/mtd/nand/nandsim.c
@@ -654,7 +654,7 @@ static int init_nandsim(struct mtd_info *mtd)
}
/* Detect how many ID bytes the NAND chip outputs */
- for (i = 0; nand_flash_ids[i].name != NULL; i++) {
+ for (i = 0; (nand_flash_ids[i].name != NULL) && (nand_flash_ids[i].id != 0); i++) {
if (second_id_byte != nand_flash_ids[i].id)
continue;
if (!(nand_flash_ids[i].options & NAND_NO_AUTOINCR))
diff --git a/drivers/mtd/ubi/misc.c b/drivers/mtd/ubi/misc.c
old mode 100644
new mode 100755
index f6a7d7ac4b98..475fd0063b12
--- a/drivers/mtd/ubi/misc.c
+++ b/drivers/mtd/ubi/misc.c
@@ -63,6 +63,13 @@ int ubi_check_volume(struct ubi_device *ubi, int vol_id)
void *buf;
int err = 0, i;
struct ubi_volume *vol = ubi->volumes[vol_id];
+#ifdef CONFIG_VENDOR_DTV
+ /*
+ Do not check the volume when the volume is static,in order to reduce the
+ time of attach mtd device when the device include big static volume
+ */
+ return 0;
+#endif
if (vol->vol_type != UBI_STATIC_VOLUME)
return 0;
More information about the linux-mtd
mailing list