Commit 3e04767a authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge git://git.infradead.org/mtd-2.6

* git://git.infradead.org/mtd-2.6:
  [MTD] Cleanup of 'ioremap balanced with iounmap for drivers/mtd subsystem'
  [MTD] fix nftl_write warning
  [MTD] fix printk warning
  [MTD ONENAND] Check OneNAND lock scheme & all block unlock command support
  [MTD ONENAND] Remove unused MTD_ONENAND_SYNC_READ configuration
  [MTD ONENAND] Fix OneNAND probe
  [MTD NAND] Provide prototype for newly-exported nand_wait_ready()
  [MTD] Remove #ifndef __KERNEL__ hack in <mtd/mtd-abi.h>
  [MTD NAND] Allow override of page read and write functions.
  [MTD NAND] Allocate chip->buffers separately to allow it to be overridden
  [MTD NAND] Split nand_scan() into two parts; allow board driver to intervene
  [MTD NAND] Export nand_wait_ready() for use by board drivers
parents a12f66fc 76a5027c
......@@ -96,7 +96,7 @@ static struct mtd_partition arctic_partitions[PARTITIONS] = {
static int __init
init_arctic_mtd(void)
{
int err = 0;
int err;
printk("%s: 0x%08x at 0x%08x\n", NAME, SIZE, PADDR);
......@@ -112,7 +112,7 @@ init_arctic_mtd(void)
arctic_mtd = do_map_probe("cfi_probe", &arctic_mtd_map);
if (!arctic_mtd) {
iounmap((void *) arctic_mtd_map.virt);
iounmap(arctic_mtd_map.virt);
return -ENXIO;
}
......@@ -121,7 +121,7 @@ init_arctic_mtd(void)
err = add_mtd_partitions(arctic_mtd, arctic_partitions, PARTITIONS);
if (err) {
printk("%s: add_mtd_partitions failed\n", NAME);
iounmap((void *) arctic_mtd_map.virt);
iounmap(arctic_mtd_map.virt);
}
return err;
......
......@@ -72,7 +72,7 @@ static struct mtd_partition beech_partitions[2] = {
static int __init
init_beech_mtd(void)
{
int err = 0;
int err;
printk("%s: 0x%08x at 0x%08x\n", NAME, SIZE, PADDR);
......@@ -89,7 +89,7 @@ init_beech_mtd(void)
beech_mtd = do_map_probe("cfi_probe", &beech_mtd_map);
if (!beech_mtd) {
iounmap((void *) beech_mtd_map.virt);
iounmap(beech_mtd_map.virt);
return -ENXIO;
}
......@@ -98,7 +98,7 @@ init_beech_mtd(void)
err = add_mtd_partitions(beech_mtd, beech_partitions, 2);
if (err) {
printk("%s: add_mtd_partitions failed\n", NAME);
iounmap((void *) beech_mtd_map.virt);
iounmap(beech_mtd_map.virt);
}
return err;
......
......@@ -175,8 +175,8 @@ int __init init_cstm_mips_ixx(void)
printk(KERN_WARNING "Failed to ioremap\n");
for (j = 0; j < i; j++) {
if (cstm_mips_ixx_map[j].virt) {
iounmap((void *)cstm_mips_ixx_map[j].virt);
cstm_mips_ixx_map[j].virt = 0;
iounmap(cstm_mips_ixx_map[j].virt);
cstm_mips_ixx_map[j].virt = NULL;
}
}
return -EIO;
......@@ -214,8 +214,8 @@ int __init init_cstm_mips_ixx(void)
else {
for (i = 0; i < PHYSMAP_NUMBER; i++) {
if (cstm_mips_ixx_map[i].virt) {
iounmap((void *)cstm_mips_ixx_map[i].virt);
cstm_mips_ixx_map[i].virt = 0;
iounmap(cstm_mips_ixx_map[i].virt);
cstm_mips_ixx_map[i].virt = NULL;
}
}
return -ENXIO;
......
......@@ -463,7 +463,7 @@ int __init nettel_init(void)
#ifdef CONFIG_MTD_CFI_INTELEXT
out_unmap1:
iounmap((void *) nettel_intel_map.virt);
iounmap(nettel_intel_map.virt);
#endif
out_unmap2:
......
......@@ -126,7 +126,7 @@ static struct mtd_info *redwood_mtd;
int __init init_redwood_flash(void)
{
int err = 0;
int err;
printk(KERN_NOTICE "redwood: flash mapping: %x at %x\n",
WINDOW_SIZE, WINDOW_ADDR);
......
......@@ -69,7 +69,7 @@ static int do_blktrans_request(struct mtd_blktrans_ops *tr,
return 1;
default:
printk(KERN_NOTICE "Unknown request %ld\n", rq_data_dir(req));
printk(KERN_NOTICE "Unknown request %u\n", rq_data_dir(req));
return 0;
}
}
......
......@@ -199,7 +199,7 @@ static void __exit ep7312_cleanup(void)
nand_release(ap7312_mtd);
/* Release io resource */
iounmap((void *)this->IO_ADDR_R);
iounmap(this->IO_ADDR_R);
/* Free the MTD device structure */
kfree(ep7312_mtd);
......
......@@ -415,7 +415,7 @@ static int nand_block_checkbad(struct mtd_info *mtd, loff_t ofs, int getchip,
* Wait for the ready pin, after a command
* The timeout is catched later.
*/
static void nand_wait_ready(struct mtd_info *mtd)
void nand_wait_ready(struct mtd_info *mtd)
{
struct nand_chip *chip = mtd->priv;
unsigned long timeo = jiffies + 2;
......@@ -429,6 +429,7 @@ static void nand_wait_ready(struct mtd_info *mtd)
} while (time_before(jiffies, timeo));
led_trigger_event(nand_led_trigger, LED_OFF);
}
EXPORT_SYMBOL_GPL(nand_wait_ready);
/**
* nand_command - [DEFAULT] Send command to NAND device
......@@ -766,8 +767,8 @@ static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
int eccbytes = chip->ecc.bytes;
int eccsteps = chip->ecc.steps;
uint8_t *p = buf;
uint8_t *ecc_calc = chip->buffers.ecccalc;
uint8_t *ecc_code = chip->buffers.ecccode;
uint8_t *ecc_calc = chip->buffers->ecccalc;
uint8_t *ecc_code = chip->buffers->ecccode;
int *eccpos = chip->ecc.layout->eccpos;
nand_read_page_raw(mtd, chip, buf);
......@@ -808,8 +809,8 @@ static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
int eccbytes = chip->ecc.bytes;
int eccsteps = chip->ecc.steps;
uint8_t *p = buf;
uint8_t *ecc_calc = chip->buffers.ecccalc;
uint8_t *ecc_code = chip->buffers.ecccode;
uint8_t *ecc_calc = chip->buffers->ecccalc;
uint8_t *ecc_code = chip->buffers->ecccode;
int *eccpos = chip->ecc.layout->eccpos;
for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
......@@ -970,7 +971,7 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
page = realpage & chip->pagemask;
col = (int)(from & (mtd->writesize - 1));
chip->oob_poi = chip->buffers.oobrbuf;
chip->oob_poi = chip->buffers->oobrbuf;
buf = ops->datbuf;
oob = ops->oobbuf;
......@@ -981,7 +982,7 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
/* Is the current page in the buffer ? */
if (realpage != chip->pagebuf || oob) {
bufpoi = aligned ? buf : chip->buffers.databuf;
bufpoi = aligned ? buf : chip->buffers->databuf;
if (likely(sndcmd)) {
chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page);
......@@ -989,14 +990,17 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
}
/* Now read the page into the buffer */
ret = chip->ecc.read_page(mtd, chip, bufpoi);
if (unlikely(ops->mode == MTD_OOB_RAW))
ret = chip->ecc.read_page_raw(mtd, chip, bufpoi);
else
ret = chip->ecc.read_page(mtd, chip, bufpoi);
if (ret < 0)
break;
/* Transfer not aligned data */
if (!aligned) {
chip->pagebuf = realpage;
memcpy(buf, chip->buffers.databuf + col, bytes);
memcpy(buf, chip->buffers->databuf + col, bytes);
}
buf += bytes;
......@@ -1023,7 +1027,7 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
nand_wait_ready(mtd);
}
} else {
memcpy(buf, chip->buffers.databuf + col, bytes);
memcpy(buf, chip->buffers->databuf + col, bytes);
buf += bytes;
}
......@@ -1266,7 +1270,7 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from,
realpage = (int)(from >> chip->page_shift);
page = realpage & chip->pagemask;
chip->oob_poi = chip->buffers.oobrbuf;
chip->oob_poi = chip->buffers->oobrbuf;
while(1) {
sndcmd = chip->ecc.read_oob(mtd, chip, page, sndcmd);
......@@ -1322,8 +1326,6 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from,
static int nand_read_oob(struct mtd_info *mtd, loff_t from,
struct mtd_oob_ops *ops)
{
int (*read_page)(struct mtd_info *mtd, struct nand_chip *chip,
uint8_t *buf) = NULL;
struct nand_chip *chip = mtd->priv;
int ret = -ENOTSUPP;
......@@ -1341,12 +1343,7 @@ static int nand_read_oob(struct mtd_info *mtd, loff_t from,
switch(ops->mode) {
case MTD_OOB_PLACE:
case MTD_OOB_AUTO:
break;
case MTD_OOB_RAW:
/* Replace the read_page algorithm temporary */
read_page = chip->ecc.read_page;
chip->ecc.read_page = nand_read_page_raw;
break;
default:
......@@ -1358,8 +1355,6 @@ static int nand_read_oob(struct mtd_info *mtd, loff_t from,
else
ret = nand_do_read_ops(mtd, from, ops);
if (unlikely(ops->mode == MTD_OOB_RAW))
chip->ecc.read_page = read_page;
out:
nand_release_device(mtd);
return ret;
......@@ -1391,7 +1386,7 @@ static void nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
int i, eccsize = chip->ecc.size;
int eccbytes = chip->ecc.bytes;
int eccsteps = chip->ecc.steps;
uint8_t *ecc_calc = chip->buffers.ecccalc;
uint8_t *ecc_calc = chip->buffers->ecccalc;
const uint8_t *p = buf;
int *eccpos = chip->ecc.layout->eccpos;
......@@ -1417,7 +1412,7 @@ static void nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
int i, eccsize = chip->ecc.size;
int eccbytes = chip->ecc.bytes;
int eccsteps = chip->ecc.steps;
uint8_t *ecc_calc = chip->buffers.ecccalc;
uint8_t *ecc_calc = chip->buffers->ecccalc;
const uint8_t *p = buf;
int *eccpos = chip->ecc.layout->eccpos;
......@@ -1478,7 +1473,7 @@ static void nand_write_page_syndrome(struct mtd_info *mtd,
}
/**
* nand_write_page - [INTERNAL] write one page
* nand_write_page - [REPLACEABLE] write one page
* @mtd: MTD device structure
* @chip: NAND chip descriptor
* @buf: the data to write
......@@ -1486,13 +1481,16 @@ static void nand_write_page_syndrome(struct mtd_info *mtd,
* @cached: cached programming
*/
static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip,
const uint8_t *buf, int page, int cached)
const uint8_t *buf, int page, int cached, int raw)
{
int status;
chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page);
chip->ecc.write_page(mtd, chip, buf);
if (unlikely(raw))
chip->ecc.write_page_raw(mtd, chip, buf);
else
chip->ecc.write_page(mtd, chip, buf);
/*
* Cached progamming disabled for now, Not sure if its worth the
......@@ -1627,7 +1625,7 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
(chip->pagebuf << chip->page_shift) < (to + ops->len))
chip->pagebuf = -1;
chip->oob_poi = chip->buffers.oobwbuf;
chip->oob_poi = chip->buffers->oobwbuf;
while(1) {
int cached = writelen > bytes && page != blockmask;
......@@ -1635,7 +1633,8 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
if (unlikely(oob))
oob = nand_fill_oob(chip, oob, ops);
ret = nand_write_page(mtd, chip, buf, page, cached);
ret = chip->write_page(mtd, chip, buf, page, cached,
(ops->mode == MTD_OOB_RAW));
if (ret)
break;
......@@ -1745,7 +1744,7 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to,
if (page == chip->pagebuf)
chip->pagebuf = -1;
chip->oob_poi = chip->buffers.oobwbuf;
chip->oob_poi = chip->buffers->oobwbuf;
memset(chip->oob_poi, 0xff, mtd->oobsize);
nand_fill_oob(chip, ops->oobbuf, ops);
status = chip->ecc.write_oob(mtd, chip, page & chip->pagemask);
......@@ -1768,8 +1767,6 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to,
static int nand_write_oob(struct mtd_info *mtd, loff_t to,
struct mtd_oob_ops *ops)
{
void (*write_page)(struct mtd_info *mtd, struct nand_chip *chip,
const uint8_t *buf) = NULL;
struct nand_chip *chip = mtd->priv;
int ret = -ENOTSUPP;
......@@ -1787,12 +1784,7 @@ static int nand_write_oob(struct mtd_info *mtd, loff_t to,
switch(ops->mode) {
case MTD_OOB_PLACE:
case MTD_OOB_AUTO:
break;
case MTD_OOB_RAW:
/* Replace the write_page algorithm temporary */
write_page = chip->ecc.write_page;
chip->ecc.write_page = nand_write_page_raw;
break;
default:
......@@ -1804,8 +1796,6 @@ static int nand_write_oob(struct mtd_info *mtd, loff_t to,
else
ret = nand_do_write_ops(mtd, to, ops);
if (unlikely(ops->mode == MTD_OOB_RAW))
chip->ecc.write_page = write_page;
out:
nand_release_device(mtd);
return ret;
......@@ -2288,40 +2278,22 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
return type;
}
/* module_text_address() isn't exported, and it's mostly a pointless
test if this is a module _anyway_ -- they'd have to try _really_ hard
to call us from in-kernel code if the core NAND support is modular. */
#ifdef MODULE
#define caller_is_module() (1)
#else
#define caller_is_module() \
module_text_address((unsigned long)__builtin_return_address(0))
#endif
/**
* nand_scan - [NAND Interface] Scan for the NAND device
* @mtd: MTD device structure
* @maxchips: Number of chips to scan for
* nand_scan_ident - [NAND Interface] Scan for the NAND device
* @mtd: MTD device structure
* @maxchips: Number of chips to scan for
*
* This fills out all the uninitialized function pointers
* with the defaults.
* The flash ID is read and the mtd/chip structures are
* filled with the appropriate values.
* The mtd->owner field must be set to the module of the caller
* This is the first phase of the normal nand_scan() function. It
* reads the flash ID and sets up MTD fields accordingly.
*
* The mtd->owner field must be set to the module of the caller.
*/
int nand_scan(struct mtd_info *mtd, int maxchips)
int nand_scan_ident(struct mtd_info *mtd, int maxchips)
{
int i, busw, nand_maf_id;
struct nand_chip *chip = mtd->priv;
struct nand_flash_dev *type;
/* Many callers got this wrong, so check for it for a while... */
if (!mtd->owner && caller_is_module()) {
printk(KERN_CRIT "nand_scan() called with NULL mtd->owner!\n");
BUG();
}
/* Get buswidth to select the correct functions */
busw = chip->options & NAND_BUSWIDTH_16;
/* Set the default functions */
......@@ -2353,8 +2325,31 @@ int nand_scan(struct mtd_info *mtd, int maxchips)
chip->numchips = i;
mtd->size = i * chip->chipsize;
return 0;
}
/**
* nand_scan_tail - [NAND Interface] Scan for the NAND device
* @mtd: MTD device structure
* @maxchips: Number of chips to scan for
*
* This is the second phase of the normal nand_scan() function. It
* fills out all the uninitialized function pointers with the defaults
* and scans for a bad block table if appropriate.
*/
int nand_scan_tail(struct mtd_info *mtd)
{
int i;
struct nand_chip *chip = mtd->priv;
if (!(chip->options & NAND_OWN_BUFFERS))
chip->buffers = kmalloc(sizeof(*chip->buffers), GFP_KERNEL);
if (!chip->buffers)
return -ENOMEM;
/* Preset the internal oob write buffer */
memset(chip->buffers.oobwbuf, 0xff, mtd->oobsize);
memset(chip->buffers->oobwbuf, 0xff, mtd->oobsize);
/*
* If no default placement scheme is given, select an appropriate one
......@@ -2377,10 +2372,18 @@ int nand_scan(struct mtd_info *mtd, int maxchips)
}
}
if (!chip->write_page)
chip->write_page = nand_write_page;
/*
* check ECC mode, default to software if 3byte/512byte hardware ECC is
* selected and we have 256 byte pagesize fallback to software ECC
*/
if (!chip->ecc.read_page_raw)
chip->ecc.read_page_raw = nand_read_page_raw;
if (!chip->ecc.write_page_raw)
chip->ecc.write_page_raw = nand_write_page_raw;
switch (chip->ecc.mode) {
case NAND_ECC_HW:
/* Use standard hwecc read page function ? */
......@@ -2438,6 +2441,7 @@ int nand_scan(struct mtd_info *mtd, int maxchips)
chip->ecc.size = mtd->writesize;
chip->ecc.bytes = 0;
break;
default:
printk(KERN_WARNING "Invalid NAND_ECC_MODE %d\n",
chip->ecc.mode);
......@@ -2503,6 +2507,44 @@ int nand_scan(struct mtd_info *mtd, int maxchips)
return chip->scan_bbt(mtd);
}
/* module_text_address() isn't exported, and it's mostly a pointless
test if this is a module _anyway_ -- they'd have to try _really_ hard
to call us from in-kernel code if the core NAND support is modular. */
#ifdef MODULE
#define caller_is_module() (1)
#else
#define caller_is_module() \
module_text_address((unsigned long)__builtin_return_address(0))
#endif
/**
* nand_scan - [NAND Interface] Scan for the NAND device
* @mtd: MTD device structure
* @maxchips: Number of chips to scan for
*
* This fills out all the uninitialized function pointers
* with the defaults.
* The flash ID is read and the mtd/chip structures are
* filled with the appropriate values.
* The mtd->owner field must be set to the module of the caller
*
*/
int nand_scan(struct mtd_info *mtd, int maxchips)
{
int ret;
/* Many callers got this wrong, so check for it for a while... */
if (!mtd->owner && caller_is_module()) {
printk(KERN_CRIT "nand_scan() called with NULL mtd->owner!\n");
BUG();
}
ret = nand_scan_ident(mtd, maxchips);
if (!ret)
ret = nand_scan_tail(mtd);
return ret;
}
/**
* nand_release - [NAND Interface] Free resources held by the NAND device
* @mtd: MTD device structure
......@@ -2520,9 +2562,13 @@ void nand_release(struct mtd_info *mtd)
/* Free bad block table memory */
kfree(chip->bbt);
if (!(chip->options & NAND_OWN_BUFFERS))
kfree(chip->buffers);
}
EXPORT_SYMBOL_GPL(nand_scan);
EXPORT_SYMBOL_GPL(nand_scan_ident);
EXPORT_SYMBOL_GPL(nand_scan_tail);
EXPORT_SYMBOL_GPL(nand_release);
static int __init nand_base_init(void)
......
......@@ -759,7 +759,7 @@ static inline int nand_memory_bbt(struct mtd_info *mtd, struct nand_bbt_descr *b
struct nand_chip *this = mtd->priv;
bd->options &= ~NAND_BBT_SCANEMPTY;
return create_bbt(mtd, this->buffers.databuf, bd, -1);
return create_bbt(mtd, this->buffers->databuf, bd, -1);
}
/**
......
......@@ -175,6 +175,8 @@ int nftl_write_oob(struct mtd_info *mtd, loff_t offs, size_t len,
return res;
}
#ifdef CONFIG_NFTL_RW
/*
* Write data and oob to flash
*/
......@@ -196,8 +198,6 @@ static int nftl_write(struct mtd_info *mtd, loff_t offs, size_t len,
return res;
}
#ifdef CONFIG_NFTL_RW
/* Actual NFTL access routines */
/* NFTL_findfreeblock: Find a free Erase Unit on the NFTL partition. This function is used
* when the give Virtual Unit Chain
......
......@@ -43,10 +43,4 @@ config MTD_ONENAND_OTP
OTP block is fully-guaranteed to be a valid block.
config MTD_ONENAND_SYNC_READ
bool "OneNAND Sync. Burst Read Support"
depends on ARCH_OMAP
help
This enables support for Sync. Burst Read.
endmenu
/*
* linux/drivers/mtd/onenand/onenand_base.c
*
* Copyright (C) 2005 Samsung Electronics
* Copyright (C) 2005-2006 Samsung Electronics
* Kyungmin Park <kyungmin.park@samsung.com>
*
* This program is free software; you can redistribute it and/or modify
......@@ -199,6 +199,7 @@ static int onenand_command(struct mtd_info *mtd, int cmd, loff_t addr, size_t le
case ONENAND_CMD_UNLOCK:
case ONENAND_CMD_LOCK:
case ONENAND_CMD_LOCK_TIGHT:
case ONENAND_CMD_UNLOCK_ALL:
block = -1;
page = -1;
break;
......@@ -1211,11 +1212,11 @@ static int onenand_unlock(struct mtd_info *mtd, loff_t ofs, size_t len)
end = len >> this->erase_shift;
/* Continuous lock scheme */
if (this->options & ONENAND_CONT_LOCK) {
if (this->options & ONENAND_HAS_CONT_LOCK) {
/* Set start block address */
this->write_word(start, this->base + ONENAND_REG_START_BLOCK_ADDRESS);
/* Set end block address */
this->write_word(end - 1, this->base + ONENAND_REG_END_BLOCK_ADDRESS);
this->write_word(start + end - 1, this->base + ONENAND_REG_END_BLOCK_ADDRESS);
/* Write unlock command */
this->command(mtd, ONENAND_CMD_UNLOCK, 0, 0);
......@@ -1236,7 +1237,7 @@ static int onenand_unlock(struct mtd_info *mtd, loff_t ofs, size_t len)
}
/* Block lock scheme */
for (block = start; block < end; block++) {
for (block = start; block < start + end; block++) {
/* Set block address */
value = onenand_block_address(this, block);
this->write_word(value, this->base + ONENAND_REG_START_ADDRESS1);
......@@ -1265,6 +1266,79 @@ static int onenand_unlock(struct mtd_info *mtd, loff_t ofs, size_t len)
return 0;
}
/**
* onenand_check_lock_status - [OneNAND Interface] Check lock status
* @param this onenand chip data structure
*
* Check lock status
*/
static void onenand_check_lock_status(struct onenand_chip *this)
{
unsigned int value, block, status;
unsigned int end;
end = this->chipsize >> this->erase_shift;
for (block = 0; block < end; block++) {
/* Set block address */
value = onenand_block_address(this, block);
this->write_word(value, this->base + ONENAND_REG_START_ADDRESS1);
/* Select DataRAM for DDP */
value = onenand_bufferram_address(this, block);
this->write_word(value, this->base + ONENAND_REG_START_ADDRESS2);
/* Set start block address */
this->write_word(block, this->base + ONENAND_REG_START_BLOCK_ADDRESS);
/* Check lock status */
status = this->read_word(this->base + ONENAND_REG_WP_STATUS);
if (!(status & ONENAND_WP_US))
printk(KERN_ERR "block = %d, wp status = 0x%x\n", block, status);
}
}
/**
* onenand_unlock_