summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2009-10-20 15:28:16 +0200
committerSascha Hauer <s.hauer@pengutronix.de>2009-12-03 10:46:47 +0100
commitc6f639fafbb1874a5df1ffd9e9308762b17b544a (patch)
tree278dd79741976e2857d17ffe41cf7b628aa5fd45
parent13d2d38aa20c1e53537077615e5135b145dec957 (diff)
downloadbarebox-c6f639fafbb1874a5df1ffd9e9308762b17b544a.tar.gz
barebox-c6f639fafbb1874a5df1ffd9e9308762b17b544a.tar.xz
NAND: Allow to read oob data
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
-rw-r--r--drivers/nand/nand.c41
-rw-r--r--include/linux/mtd/mtd.h1
2 files changed, 42 insertions, 0 deletions
diff --git a/drivers/nand/nand.c b/drivers/nand/nand.c
index b72cbb1cb8..a058df2f63 100644
--- a/drivers/nand/nand.c
+++ b/drivers/nand/nand.c
@@ -29,6 +29,7 @@
#include <malloc.h>
#include <ioctl.h>
#include <nand.h>
+#include <errno.h>
static ssize_t nand_read(struct cdev *cdev, void* buf, size_t count, ulong offset, ulong flags)
{
@@ -158,8 +159,41 @@ static struct file_operations nand_ops = {
.erase = nand_erase,
};
+static ssize_t nand_read_oob(struct cdev *cdev, void *buf, size_t count, ulong offset, ulong flags)
+{
+ struct mtd_info *info = cdev->priv;
+ struct nand_chip *chip = info->priv;
+ struct mtd_oob_ops ops;
+ int ret;
+
+ if (count < info->oobsize)
+ return -EINVAL;
+
+ ops.mode = MTD_OOB_RAW;
+ ops.ooboffs = 0;
+ ops.ooblen = info->oobsize;
+ ops.oobbuf = buf;
+ ops.datbuf = NULL;
+ ops.len = info->oobsize;
+
+ offset /= info->oobsize;
+ ret = info->read_oob(info, offset << chip->page_shift, &ops);
+ if (ret)
+ return ret;
+
+ return info->oobsize;
+}
+
+static struct file_operations nand_ops_oob = {
+ .read = nand_read_oob,
+ .ioctl = nand_ioctl,
+ .lseek = dev_lseek_default,
+};
+
int add_mtd_device(struct mtd_info *mtd)
{
+ struct nand_chip *chip = mtd->priv;
+
strcpy(mtd->class_dev.name, "nand");
register_device(&mtd->class_dev);
@@ -176,6 +210,13 @@ int add_mtd_device(struct mtd_info *mtd)
devfs_create(&mtd->cdev);
+ mtd->cdev_oob.ops = &nand_ops_oob;
+ mtd->cdev_oob.size = (mtd->size >> chip->page_shift) * mtd->oobsize;
+ mtd->cdev_oob.name = asprintf("nand_oob%d", mtd->class_dev.id);
+ mtd->cdev_oob.priv = mtd;
+ mtd->cdev_oob.dev = &mtd->class_dev;
+ devfs_create(&mtd->cdev_oob);
+
return 0;
}
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
index b574778ad2..42bfcabda0 100644
--- a/include/linux/mtd/mtd.h
+++ b/include/linux/mtd/mtd.h
@@ -203,6 +203,7 @@ struct mtd_info {
struct device_d class_dev;
struct device_d *dev;
struct cdev cdev;
+ struct cdev cdev_oob;
struct param_d param_size;
char *size_str;