#include <asm/errno.h>
#include <malloc.h>
+extern void *memcpy32(void *dst, const void *src, int len);
+
/* It should access 16-bit instead of 8-bit */
- static inline void *memcpy_16(void *dst, const void *src, unsigned int len)
+ static void *memcpy_16(void *dst, const void *src, unsigned int len)
{
void *ret = dst;
short *d = dst;
int dataram;
switch (cmd) {
+ case FLEXONENAND_CMD_RECOVER_LSB:
case ONENAND_CMD_READ:
case ONENAND_CMD_READOOB:
- if (ONENAND_IS_MLC(this))
+ if (ONENAND_IS_4KB_PAGE(this))
+ /* It is always BufferRAM0 */
dataram = ONENAND_SET_BUFFERRAM0(this);
else
dataram = ONENAND_SET_NEXT_BUFFERRAM(this);
*/
static int onenand_read_ecc(struct onenand_chip *this)
{
- /* TODO Handle 4bit ecc */
- return this->read_word(this->base + ONENAND_REG_ECC_STATUS);
+ int ecc, i;
+
- if (!FLEXONENAND(this))
++ if (!ONENAND_IS_4KB_PAGE(this))
+ return this->read_word(this->base + ONENAND_REG_ECC_STATUS);
+
+ for (i = 0; i < 4; i++) {
+ ecc = this->read_word(this->base
+ + ((ONENAND_REG_ECC_STATUS + i) << 1));
+ if (likely(!ecc))
+ continue;
+ if (ecc & FLEXONENAND_UNCORRECTABLE_ERROR)
+ return ONENAND_ECC_2BIT_ALL;
+ }
+
+ return 0;
}
/**
/* Do first load to bufferRAM */
if (read < len) {
if (!onenand_check_bufferram(mtd, from)) {
- this->main_buf = buf;
this->command(mtd, ONENAND_CMD_READ, from, writesize);
ret = this->wait(mtd, FL_READING);
+ if (unlikely(ret))
+ ret = onenand_recover_lsb(mtd, from, ret);
onenand_update_bufferram(mtd, from, !ret);
if (ret == -EBADMSG)
ret = 0;
thislen = min_t(int, writesize, len - read);
column = 0;
- /* Now wait for load */
- ret = this->wait(mtd, FL_READING);
- onenand_update_bufferram(mtd, from, !ret);
- if (ret == -EBADMSG)
- ret = 0;
- if (!ONENAND_IS_MLC(this)) {
++ if (ONENAND_IS_4KB_PAGE(this)) {
+ /* Now wait for load */
+ ret = this->wait(mtd, FL_READING);
+ onenand_update_bufferram(mtd, from, !ret);
+ if (ret == -EBADMSG)
+ ret = 0;
+ }
}
/*
thislen = oobsize - column;
thislen = min_t(int, thislen, len);
- this->command(mtd, ONENAND_CMD_READOOB, from, mtd->oobsize);
- this->spare_buf = buf;
+ this->command(mtd, readcmd, from, mtd->oobsize);
onenand_update_bufferram(mtd, from, 0);
thislen = mtd->oobsize - column;
thislen = min_t(int, thislen, len);
- this->command(mtd, ONENAND_CMD_READOOB, from, mtd->oobsize);
- this->spare_buf = buf;
+ this->command(mtd, readcmd, from, mtd->oobsize);
onenand_update_bufferram(mtd, from, 0);
else
MTDDEBUG (MTD_DEBUG_LEVEL0, "onenand_erase: "
"Failed erase, block %d\n",
- (unsigned)(addr >> this->erase_shift));
- if (ret == -EPERM)
- printk("onenand_erase: "
- "Device is write protected!!!\n");
- else
- printk("onenand_erase: "
- "Failed erase, block %d\n",
- (unsigned)(addr >> this->erase_shift));
+ onenand_block(this, addr));
instr->state = MTD_ERASE_FAILED;
instr->fail_addr = addr;
-
- goto erase_exit;
}
len -= block_size;
break;
}
- if (ONENAND_IS_MLC(this))
++ if (ONENAND_IS_4KB_PAGE(this))
+ this->options &= ~ONENAND_HAS_2PLANE;
+
+ if (FLEXONENAND(this)) {
+ this->options &= ~ONENAND_HAS_CONT_LOCK;
+ this->options |= ONENAND_HAS_UNLOCK_ALL;
+ }
+
if (this->options & ONENAND_HAS_CONT_LOCK)
printk(KERN_DEBUG "Lock scheme is Continuous Lock\n");
if (this->options & ONENAND_HAS_UNLOCK_ALL)
this->device_id = dev_id;
this->version_id = ver_id;
+ /* Check OneNAND features */
+ onenand_check_features(mtd);
+
density = onenand_get_density(dev_id);
+ if (FLEXONENAND(this)) {
+ this->dies = ONENAND_IS_DDP(this) ? 2 : 1;
+ /* Maximum possible erase regions */
+ mtd->numeraseregions = this->dies << 1;
+ mtd->eraseregions = malloc(sizeof(struct mtd_erase_region_info)
+ * (this->dies << 1));
+ if (!mtd->eraseregions)
+ return -ENOMEM;
+ }
+
+ /*
+ * For Flex-OneNAND, chipsize represents maximum possible device size.
+ * mtd->size represents the actual device size.
+ */
this->chipsize = (16 << density) << 20;
- /* Set density mask. it is used for DDP */
- if (ONENAND_IS_DDP(this))
- this->density_mask = (1 << (density + 6));
- else
- this->density_mask = 0;
/* OneNAND page size & block size */
/* The data buffer size is equal to page size */
mtd->writesize =
this->read_word(this->base + ONENAND_REG_DATA_BUFFER_SIZE);
- if (ONENAND_IS_MLC(this))
+ /* We use the full BufferRAM */
+ if (ONENAND_IS_4KB_PAGE(this))
mtd->writesize <<= 1;
+
mtd->oobsize = mtd->writesize >> 5;
/* Pagers per block is always 64 in OneNAND */
mtd->erasesize = mtd->writesize << 6;
/* REVIST: Multichip handling */
- mtd->size = this->chipsize;
+ if (FLEXONENAND(this))
+ flexonenand_get_size(mtd);
+ else
+ mtd->size = this->chipsize;
- /* Check OneNAND features */
- onenand_check_features(mtd);
-
mtd->flags = MTD_CAP_NANDFLASH;
mtd->erase = onenand_erase;
mtd->read = onenand_read;
ulong ticks2usec (unsigned long ticks);
int init_timebase (void);
+ /* lib_generic/gunzip.c */
+ int gunzip(void *, int, unsigned char *, unsigned long *);
+ int zunzip(void *dst, int dstlen, unsigned char *src, unsigned long *lenp,
+ int stoponerr, int offset);
++/* lib_generic/net_utils.c */
++#include <net.h>
++static inline IPaddr_t getenv_IPaddr (char *var)
++{
++ return (string_to_ip(getenv(var)));
++}
+
+ /* lib_generic/time.c */
+ void udelay (unsigned long);
+
/* lib_generic/vsprintf.c */
ulong simple_strtoul(const char *cp,char **endp,unsigned int base);
- #ifdef CONFIG_SYS_64BIT_VSPRINTF
unsigned long long simple_strtoull(const char *cp,char **endp,unsigned int base);
- #endif
long simple_strtol(const char *cp,char **endp,unsigned int base);
void panic(const char *fmt, ...)
__attribute__ ((format (__printf__, 1, 2)));