summaryrefslogtreecommitdiff
path: root/drivers/mtd
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd')
-rw-r--r--drivers/mtd/nand/au1550nd.c29
-rw-r--r--drivers/mtd/nand/omap2.c16
-rw-r--r--drivers/mtd/onenand/Kconfig4
-rw-r--r--drivers/mtd/onenand/samsung.c25
-rw-r--r--drivers/mtd/ubi/block.c18
-rw-r--r--drivers/mtd/ubi/vtbl.c2
-rw-r--r--drivers/mtd/ubi/wl.c4
7 files changed, 43 insertions, 55 deletions
diff --git a/drivers/mtd/nand/au1550nd.c b/drivers/mtd/nand/au1550nd.c
index bc5c518828d2..77d6c17b38c2 100644
--- a/drivers/mtd/nand/au1550nd.c
+++ b/drivers/mtd/nand/au1550nd.c
@@ -41,7 +41,7 @@ static u_char au_read_byte(struct mtd_info *mtd)
{
struct nand_chip *this = mtd->priv;
u_char ret = readb(this->IO_ADDR_R);
- au_sync();
+ wmb(); /* drain writebuffer */
return ret;
}
@@ -56,7 +56,7 @@ static void au_write_byte(struct mtd_info *mtd, u_char byte)
{
struct nand_chip *this = mtd->priv;
writeb(byte, this->IO_ADDR_W);
- au_sync();
+ wmb(); /* drain writebuffer */
}
/**
@@ -69,7 +69,7 @@ static u_char au_read_byte16(struct mtd_info *mtd)
{
struct nand_chip *this = mtd->priv;
u_char ret = (u_char) cpu_to_le16(readw(this->IO_ADDR_R));
- au_sync();
+ wmb(); /* drain writebuffer */
return ret;
}
@@ -84,7 +84,7 @@ static void au_write_byte16(struct mtd_info *mtd, u_char byte)
{
struct nand_chip *this = mtd->priv;
writew(le16_to_cpu((u16) byte), this->IO_ADDR_W);
- au_sync();
+ wmb(); /* drain writebuffer */
}
/**
@@ -97,7 +97,7 @@ static u16 au_read_word(struct mtd_info *mtd)
{
struct nand_chip *this = mtd->priv;
u16 ret = readw(this->IO_ADDR_R);
- au_sync();
+ wmb(); /* drain writebuffer */
return ret;
}
@@ -116,7 +116,7 @@ static void au_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
for (i = 0; i < len; i++) {
writeb(buf[i], this->IO_ADDR_W);
- au_sync();
+ wmb(); /* drain writebuffer */
}
}
@@ -135,7 +135,7 @@ static void au_read_buf(struct mtd_info *mtd, u_char *buf, int len)
for (i = 0; i < len; i++) {
buf[i] = readb(this->IO_ADDR_R);
- au_sync();
+ wmb(); /* drain writebuffer */
}
}
@@ -156,7 +156,7 @@ static void au_write_buf16(struct mtd_info *mtd, const u_char *buf, int len)
for (i = 0; i < len; i++) {
writew(p[i], this->IO_ADDR_W);
- au_sync();
+ wmb(); /* drain writebuffer */
}
}
@@ -178,7 +178,7 @@ static void au_read_buf16(struct mtd_info *mtd, u_char *buf, int len)
for (i = 0; i < len; i++) {
p[i] = readw(this->IO_ADDR_R);
- au_sync();
+ wmb(); /* drain writebuffer */
}
}
@@ -223,26 +223,23 @@ static void au1550_hwcontrol(struct mtd_info *mtd, int cmd)
case NAND_CTL_SETNCE:
/* assert (force assert) chip enable */
- au_writel((1 << (4 + ctx->cs)), MEM_STNDCTL);
+ alchemy_wrsmem((1 << (4 + ctx->cs)), AU1000_MEM_STNDCTL);
break;
case NAND_CTL_CLRNCE:
/* deassert chip enable */
- au_writel(0, MEM_STNDCTL);
+ alchemy_wrsmem(0, AU1000_MEM_STNDCTL);
break;
}
this->IO_ADDR_R = this->IO_ADDR_W;
- /* Drain the writebuffer */
- au_sync();
+ wmb(); /* Drain the writebuffer */
}
int au1550_device_ready(struct mtd_info *mtd)
{
- int ret = (au_readl(MEM_STSTAT) & 0x1) ? 1 : 0;
- au_sync();
- return ret;
+ return (alchemy_rdsmem(AU1000_MEM_STSTAT) & 0x1) ? 1 : 0;
}
/**
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
index f0ed92e210a1..5967b385141b 100644
--- a/drivers/mtd/nand/omap2.c
+++ b/drivers/mtd/nand/omap2.c
@@ -931,7 +931,7 @@ static int omap_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
u32 val;
val = readl(info->reg.gpmc_ecc_config);
- if (((val >> ECC_CONFIG_CS_SHIFT) & ~CS_MASK) != info->gpmc_cs)
+ if (((val >> ECC_CONFIG_CS_SHIFT) & CS_MASK) != info->gpmc_cs)
return -EINVAL;
/* read ecc result */
@@ -1794,9 +1794,12 @@ static int omap_nand_probe(struct platform_device *pdev)
}
/* populate MTD interface based on ECC scheme */
- nand_chip->ecc.layout = &omap_oobinfo;
ecclayout = &omap_oobinfo;
switch (info->ecc_opt) {
+ case OMAP_ECC_HAM1_CODE_SW:
+ nand_chip->ecc.mode = NAND_ECC_SOFT;
+ break;
+
case OMAP_ECC_HAM1_CODE_HW:
pr_info("nand: using OMAP_ECC_HAM1_CODE_HW\n");
nand_chip->ecc.mode = NAND_ECC_HW;
@@ -1848,7 +1851,7 @@ static int omap_nand_probe(struct platform_device *pdev)
nand_chip->ecc.priv = nand_bch_init(mtd,
nand_chip->ecc.size,
nand_chip->ecc.bytes,
- &nand_chip->ecc.layout);
+ &ecclayout);
if (!nand_chip->ecc.priv) {
pr_err("nand: error: unable to use s/w BCH library\n");
err = -EINVAL;
@@ -1923,7 +1926,7 @@ static int omap_nand_probe(struct platform_device *pdev)
nand_chip->ecc.priv = nand_bch_init(mtd,
nand_chip->ecc.size,
nand_chip->ecc.bytes,
- &nand_chip->ecc.layout);
+ &ecclayout);
if (!nand_chip->ecc.priv) {
pr_err("nand: error: unable to use s/w BCH library\n");
err = -EINVAL;
@@ -2012,6 +2015,9 @@ static int omap_nand_probe(struct platform_device *pdev)
goto return_error;
}
+ if (info->ecc_opt == OMAP_ECC_HAM1_CODE_SW)
+ goto scan_tail;
+
/* all OOB bytes from oobfree->offset till end off OOB are free */
ecclayout->oobfree->length = mtd->oobsize - ecclayout->oobfree->offset;
/* check if NAND device's OOB is enough to store ECC signatures */
@@ -2021,7 +2027,9 @@ static int omap_nand_probe(struct platform_device *pdev)
err = -EINVAL;
goto return_error;
}
+ nand_chip->ecc.layout = ecclayout;
+scan_tail:
/* second phase scan */
if (nand_scan_tail(mtd)) {
err = -ENXIO;
diff --git a/drivers/mtd/onenand/Kconfig b/drivers/mtd/onenand/Kconfig
index ab2607273e80..dcae2f6a2b11 100644
--- a/drivers/mtd/onenand/Kconfig
+++ b/drivers/mtd/onenand/Kconfig
@@ -32,10 +32,10 @@ config MTD_ONENAND_OMAP2
config MTD_ONENAND_SAMSUNG
tristate "OneNAND on Samsung SOC controller support"
- depends on ARCH_S3C64XX || ARCH_S5PC100 || ARCH_S5PV210 || ARCH_EXYNOS4
+ depends on ARCH_S3C64XX || ARCH_S5PV210 || ARCH_EXYNOS4
help
Support for a OneNAND flash device connected to an Samsung SOC.
- S3C64XX/S5PC100 use command mapping method.
+ S3C64XX uses command mapping method.
S5PC110/S5PC210 use generic OneNAND method.
config MTD_ONENAND_OTP
diff --git a/drivers/mtd/onenand/samsung.c b/drivers/mtd/onenand/samsung.c
index efb819c3df2f..19cfb97adbc0 100644
--- a/drivers/mtd/onenand/samsung.c
+++ b/drivers/mtd/onenand/samsung.c
@@ -10,7 +10,7 @@
* published by the Free Software Foundation.
*
* Implementation:
- * S3C64XX and S5PC100: emulate the pseudo BufferRAM
+ * S3C64XX: emulate the pseudo BufferRAM
* S5PC110: use DMA
*/
@@ -32,7 +32,6 @@
enum soc_type {
TYPE_S3C6400,
TYPE_S3C6410,
- TYPE_S5PC100,
TYPE_S5PC110,
};
@@ -59,7 +58,6 @@ enum soc_type {
#define MAP_11 (0x3)
#define S3C64XX_CMD_MAP_SHIFT 24
-#define S5PC100_CMD_MAP_SHIFT 26
#define S3C6400_FBA_SHIFT 10
#define S3C6400_FPA_SHIFT 4
@@ -69,10 +67,6 @@ enum soc_type {
#define S3C6410_FPA_SHIFT 6
#define S3C6410_FSA_SHIFT 4
-#define S5PC100_FBA_SHIFT 13
-#define S5PC100_FPA_SHIFT 7
-#define S5PC100_FSA_SHIFT 5
-
/* S5PC110 specific definitions */
#define S5PC110_DMA_SRC_ADDR 0x400
#define S5PC110_DMA_SRC_CFG 0x404
@@ -195,11 +189,6 @@ static unsigned int s3c64xx_cmd_map(unsigned type, unsigned val)
return (type << S3C64XX_CMD_MAP_SHIFT) | val;
}
-static unsigned int s5pc1xx_cmd_map(unsigned type, unsigned val)
-{
- return (type << S5PC100_CMD_MAP_SHIFT) | val;
-}
-
static unsigned int s3c6400_mem_addr(int fba, int fpa, int fsa)
{
return (fba << S3C6400_FBA_SHIFT) | (fpa << S3C6400_FPA_SHIFT) |
@@ -212,12 +201,6 @@ static unsigned int s3c6410_mem_addr(int fba, int fpa, int fsa)
(fsa << S3C6410_FSA_SHIFT);
}
-static unsigned int s5pc100_mem_addr(int fba, int fpa, int fsa)
-{
- return (fba << S5PC100_FBA_SHIFT) | (fpa << S5PC100_FPA_SHIFT) |
- (fsa << S5PC100_FSA_SHIFT);
-}
-
static void s3c_onenand_reset(void)
{
unsigned long timeout = 0x10000;
@@ -835,9 +818,6 @@ static void s3c_onenand_setup(struct mtd_info *mtd)
} else if (onenand->type == TYPE_S3C6410) {
onenand->mem_addr = s3c6410_mem_addr;
onenand->cmd_map = s3c64xx_cmd_map;
- } else if (onenand->type == TYPE_S5PC100) {
- onenand->mem_addr = s5pc100_mem_addr;
- onenand->cmd_map = s5pc1xx_cmd_map;
} else if (onenand->type == TYPE_S5PC110) {
/* Use generic onenand functions */
this->read_bufferram = s5pc110_read_bufferram;
@@ -1111,9 +1091,6 @@ static struct platform_device_id s3c_onenand_driver_ids[] = {
.name = "s3c6410-onenand",
.driver_data = TYPE_S3C6410,
}, {
- .name = "s5pc100-onenand",
- .driver_data = TYPE_S5PC100,
- }, {
.name = "s5pc110-onenand",
.driver_data = TYPE_S5PC110,
}, { },
diff --git a/drivers/mtd/ubi/block.c b/drivers/mtd/ubi/block.c
index 8457df7ec5af..33c64955d4d7 100644
--- a/drivers/mtd/ubi/block.c
+++ b/drivers/mtd/ubi/block.c
@@ -378,9 +378,11 @@ int ubiblock_create(struct ubi_volume_info *vi)
{
struct ubiblock *dev;
struct gendisk *gd;
- int disk_capacity;
+ u64 disk_capacity = ((u64)vi->size * vi->usable_leb_size) >> 9;
int ret;
+ if ((sector_t)disk_capacity != disk_capacity)
+ return -EFBIG;
/* Check that the volume isn't already handled */
mutex_lock(&devices_mutex);
if (find_dev_nolock(vi->ubi_num, vi->vol_id)) {
@@ -412,7 +414,6 @@ int ubiblock_create(struct ubi_volume_info *vi)
gd->first_minor = dev->ubi_num * UBI_MAX_VOLUMES + dev->vol_id;
gd->private_data = dev;
sprintf(gd->disk_name, "ubiblock%d_%d", dev->ubi_num, dev->vol_id);
- disk_capacity = (vi->size * vi->usable_leb_size) >> 9;
set_capacity(gd, disk_capacity);
dev->gd = gd;
@@ -498,11 +499,16 @@ int ubiblock_remove(struct ubi_volume_info *vi)
return 0;
}
-static void ubiblock_resize(struct ubi_volume_info *vi)
+static int ubiblock_resize(struct ubi_volume_info *vi)
{
struct ubiblock *dev;
- int disk_capacity;
+ u64 disk_capacity = ((u64)vi->size * vi->usable_leb_size) >> 9;
+ if ((sector_t)disk_capacity != disk_capacity) {
+ ubi_warn("%s: the volume is too big, cannot resize (%d LEBs)",
+ dev->gd->disk_name, vi->size);
+ return -EFBIG;
+ }
/*
* Need to lock the device list until we stop using the device,
* otherwise the device struct might get released in
@@ -512,15 +518,15 @@ static void ubiblock_resize(struct ubi_volume_info *vi)
dev = find_dev_nolock(vi->ubi_num, vi->vol_id);
if (!dev) {
mutex_unlock(&devices_mutex);
- return;
+ return -ENODEV;
}
mutex_lock(&dev->dev_mutex);
- disk_capacity = (vi->size * vi->usable_leb_size) >> 9;
set_capacity(dev->gd, disk_capacity);
ubi_msg("%s resized to %d LEBs", dev->gd->disk_name, vi->size);
mutex_unlock(&dev->dev_mutex);
mutex_unlock(&devices_mutex);
+ return 0;
}
static int ubiblock_notify(struct notifier_block *nb,
diff --git a/drivers/mtd/ubi/vtbl.c b/drivers/mtd/ubi/vtbl.c
index d77b1c1d7c72..07cac5f9ffb8 100644
--- a/drivers/mtd/ubi/vtbl.c
+++ b/drivers/mtd/ubi/vtbl.c
@@ -591,7 +591,7 @@ static int init_volumes(struct ubi_device *ubi,
/* Static volumes only */
av = ubi_find_av(ai, i);
- if (!av) {
+ if (!av || !av->leb_count) {
/*
* No eraseblocks belonging to this volume found. We
* don't actually know whether this static volume is
diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c
index 0f3425dac910..20f491713145 100644
--- a/drivers/mtd/ubi/wl.c
+++ b/drivers/mtd/ubi/wl.c
@@ -1718,12 +1718,12 @@ int ubi_wl_flush(struct ubi_device *ubi, int vol_id, int lnum)
vol_id, lnum, ubi->works_count);
while (found) {
- struct ubi_work *wrk;
+ struct ubi_work *wrk, *tmp;
found = 0;
down_read(&ubi->work_sem);
spin_lock(&ubi->wl_lock);
- list_for_each_entry(wrk, &ubi->works, list) {
+ list_for_each_entry_safe(wrk, tmp, &ubi->works, list) {
if ((vol_id == UBI_ALL || wrk->vol_id == vol_id) &&
(lnum == UBI_ALL || wrk->lnum == lnum)) {
list_del(&wrk->list);