diff options
author | Sascha Hauer <s.hauer@pengutronix.de> | 2009-10-20 15:28:16 +0200 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2009-12-03 10:46:47 +0100 |
commit | c6f639fafbb1874a5df1ffd9e9308762b17b544a (patch) | |
tree | 278dd79741976e2857d17ffe41cf7b628aa5fd45 | |
parent | 13d2d38aa20c1e53537077615e5135b145dec957 (diff) | |
download | barebox-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.c | 41 | ||||
-rw-r--r-- | include/linux/mtd/mtd.h | 1 |
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; |