*/
#include <common.h>
+#include <log.h>
+#include <watchdog.h>
+#include <dm/devres.h>
+#include <linux/bitops.h>
#include <linux/compat.h>
#include <linux/mtd/mtd.h>
+#include "linux/mtd/flashchip.h"
#include <linux/mtd/onenand.h>
#include <asm/io.h>
-#include <asm/errno.h>
+#include <linux/errno.h>
#include <malloc.h>
/* It should access 16-bit instead of 8-bit */
static int onenand_wait(struct mtd_info *mtd, int state)
{
struct onenand_chip *this = mtd->priv;
- unsigned int flags = ONENAND_INT_MASTER;
unsigned int interrupt = 0;
unsigned int ctrl;
- while (1) {
+ /* Wait at most 20ms ... */
+ u32 timeo = (CONFIG_SYS_HZ * 20) / 1000;
+ u32 time_start = get_timer(0);
+ do {
+ WATCHDOG_RESET();
+ if (get_timer(time_start) > timeo)
+ return -EIO;
interrupt = this->read_word(this->base + ONENAND_REG_INTERRUPT);
- if (interrupt & flags)
- break;
- }
+ } while ((interrupt & ONENAND_INT_MASTER) == 0);
ctrl = this->read_word(this->base + ONENAND_REG_CTRL_STATUS);
int ret = 0, boundary = 0;
int writesize = this->writesize;
- MTDDEBUG(MTD_DEBUG_LEVEL3, "onenand_read_ops_nolock: from = 0x%08x, len = %i\n", (unsigned int) from, (int) len);
+ pr_debug("onenand_read_ops_nolock: from = 0x%08x, len = %i\n",
+ (unsigned int) from, (int) len);
if (ops->mode == MTD_OPS_AUTO_OOB)
oobsize = this->ecclayout->oobavail;
from += ops->ooboffs;
- MTDDEBUG(MTD_DEBUG_LEVEL3, "onenand_read_oob_nolock: from = 0x%08x, len = %i\n", (unsigned int) from, (int) len);
+ pr_debug("onenand_read_oob_nolock: from = 0x%08x, len = %i\n",
+ (unsigned int) from, (int) len);
/* Initialize return length value */
ops->oobretlen = 0;
static int onenand_bbt_wait(struct mtd_info *mtd, int state)
{
struct onenand_chip *this = mtd->priv;
- unsigned int flags = ONENAND_INT_MASTER;
unsigned int interrupt;
unsigned int ctrl;
- while (1) {
+ /* Wait at most 20ms ... */
+ u32 timeo = (CONFIG_SYS_HZ * 20) / 1000;
+ u32 time_start = get_timer(0);
+ do {
+ WATCHDOG_RESET();
+ if (get_timer(time_start) > timeo)
+ return ONENAND_BBT_READ_FATAL_ERROR;
interrupt = this->read_word(this->base + ONENAND_REG_INTERRUPT);
- if (interrupt & flags)
- break;
- }
+ } while ((interrupt & ONENAND_INT_MASTER) == 0);
/* To get correct interrupt status in timeout case */
interrupt = this->read_word(this->base + ONENAND_REG_INTERRUPT);
size_t len = ops->ooblen;
u_char *buf = ops->oobbuf;
- MTDDEBUG(MTD_DEBUG_LEVEL3, "onenand_bbt_read_oob: from = 0x%08x, len = %zi\n", (unsigned int) from, len);
+ pr_debug("onenand_bbt_read_oob: from = 0x%08x, len = %zi\n",
+ (unsigned int) from, len);
readcmd = ONENAND_IS_4KB_PAGE(this) ?
ONENAND_CMD_READ : ONENAND_CMD_READOOB;
u_char *oobbuf;
int ret = 0;
- MTDDEBUG(MTD_DEBUG_LEVEL3, "onenand_write_ops_nolock: to = 0x%08x, len = %i\n", (unsigned int) to, (int) len);
+ pr_debug("onenand_write_ops_nolock: to = 0x%08x, len = %i\n",
+ (unsigned int) to, (int) len);
/* Initialize retlen, in case of early exit */
ops->retlen = 0;
to += ops->ooboffs;
- MTDDEBUG(MTD_DEBUG_LEVEL3, "onenand_write_oob_nolock: to = 0x%08x, len = %i\n", (unsigned int) to, (int) len);
+ pr_debug("onenand_write_oob_nolock: to = 0x%08x, len = %i\n",
+ (unsigned int) to, (int) len);
/* Initialize retlen, in case of early exit */
ops->oobretlen = 0;
struct mtd_erase_region_info *region = NULL;
unsigned int region_end = 0;
- MTDDEBUG(MTD_DEBUG_LEVEL3, "onenand_erase: start = 0x%08x, len = %i\n",
+ pr_debug("onenand_erase: start = 0x%08x, len = %i\n",
(unsigned int) addr, len);
if (FLEXONENAND(this)) {
* Erase region's start offset is always block start address.
*/
if (unlikely((addr - region->offset) & (block_size - 1))) {
- MTDDEBUG(MTD_DEBUG_LEVEL0, "onenand_erase:"
- " Unaligned address\n");
+ pr_debug("onenand_erase:" " Unaligned address\n");
return -EINVAL;
}
} else {
/* Start address must align on block boundary */
if (unlikely(addr & (block_size - 1))) {
- MTDDEBUG(MTD_DEBUG_LEVEL0, "onenand_erase:"
- "Unaligned address\n");
+ pr_debug("onenand_erase:" "Unaligned address\n");
return -EINVAL;
}
}
/* Length must align on block boundary */
if (unlikely(len & (block_size - 1))) {
- MTDDEBUG (MTD_DEBUG_LEVEL0,
- "onenand_erase: Length not block aligned\n");
+ pr_debug("onenand_erase: Length not block aligned\n");
return -EINVAL;
}
/* Check, if it is write protected */
if (ret) {
if (ret == -EPERM)
- MTDDEBUG (MTD_DEBUG_LEVEL0, "onenand_erase: "
- "Device is write protected!!!\n");
+ pr_debug("onenand_erase: "
+ "Device is write protected!!!\n");
else
- MTDDEBUG (MTD_DEBUG_LEVEL0, "onenand_erase: "
- "Failed erase, block %d\n",
- onenand_block(this, addr));
+ pr_debug("onenand_erase: "
+ "Failed erase, block %d\n",
+ onenand_block(this, addr));
instr->state = MTD_ERASE_FAILED;
instr->fail_addr = addr;
*/
void onenand_sync(struct mtd_info *mtd)
{
- MTDDEBUG (MTD_DEBUG_LEVEL3, "onenand_sync: called\n");
+ pr_debug("onenand_sync: called\n");
/* Grab the lock and see if the device is available */
onenand_get_device(mtd, FL_SYNCING);
*/
int onenand_block_markbad(struct mtd_info *mtd, loff_t ofs)
{
+ struct onenand_chip *this = mtd->priv;
int ret;
ret = onenand_block_isbad(mtd, ofs);
return ret;
}
- ret = mtd_block_markbad(mtd, ofs);
+ onenand_get_device(mtd, FL_WRITING);
+ ret = this->block_markbad(mtd, ofs);
+ onenand_release_device(mtd);
+
return ret;
}
this->write_word(ONENAND_CMD_RESET, this->base + ONENAND_BOOTRAM);
/* Wait reset */
- this->wait(mtd, FL_RESETING);
+ if (this->wait(mtd, FL_RESETING))
+ return -ENXIO;
/* Restore system configuration 1 */
this->write_word(syscfg, this->base + ONENAND_REG_SYS_CFG1);
else
mtd->size = this->chipsize;
+ mtd->type = ONENAND_IS_MLC(this) ? MTD_MLCNANDFLASH : MTD_NANDFLASH;
mtd->flags = MTD_CAP_NANDFLASH;
mtd->_erase = onenand_erase;
- mtd->_read = onenand_read;
- mtd->_write = onenand_write;
mtd->_read_oob = onenand_read_oob;
mtd->_write_oob = onenand_write_oob;
mtd->_sync = onenand_sync;
mtd->_block_isbad = onenand_block_isbad;
mtd->_block_markbad = onenand_block_markbad;
+ mtd->writebufsize = mtd->writesize;
return 0;
}