@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2016 Jagan Teki <jagan@openedev.com>
* Copyright (C) 2015 Thomas Chou <thomas@wytron.com.tw>
*
* SPDX-License-Identifier: GPL-2.0+
@@ -8,6 +9,66 @@
#include <dm.h>
#include <errno.h>
#include <mtd.h>
+#include <linux/log2.h>
+
+int mtd_dread(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen,
+ u_char *buf)
+{
+ struct udevice *dev = mtd->dev;
+ const struct mtd_ops *ops = mtd_get_ops(dev);
+
+ if (!ops->read)
+ return -ENOSYS;
+
+ *retlen = 0;
+ if (from < 0 || from > mtd->size || len > mtd->size - from)
+ return -EINVAL;
+ if (!len)
+ return 0;
+
+ return ops->read(dev, from, len, retlen, buf);
+}
+
+int mtd_derase(struct mtd_info *mtd, struct erase_info *instr)
+{
+ struct udevice *dev = mtd->dev;
+ const struct mtd_ops *ops = mtd_get_ops(dev);
+
+ if (!ops->erase)
+ return -ENOSYS;
+
+ if (instr->addr > mtd->size || instr->len > mtd->size - instr->addr)
+ return -EINVAL;
+ if (!(mtd->flags & MTD_WRITEABLE))
+ return -EROFS;
+ instr->fail_addr = MTD_FAIL_ADDR_UNKNOWN;
+ if (!instr->len) {
+ instr->state = MTD_ERASE_DONE;
+ return 0;
+ }
+
+ return ops->erase(dev, instr);
+}
+
+int mtd_dwrite(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen,
+ const u_char *buf)
+{
+ struct udevice *dev = mtd->dev;
+ const struct mtd_ops *ops = mtd_get_ops(dev);
+
+ if (!ops->write)
+ return -ENOSYS;
+
+ *retlen = 0;
+ if (to < 0 || to > mtd->size || len > mtd->size - to)
+ return -EINVAL;
+ if (!ops->write || !(mtd->flags & MTD_WRITEABLE))
+ return -EROFS;
+ if (!len)
+ return 0;
+
+ return ops->write(dev, to, len, retlen, buf);
+}
/*
* Implement a MTD uclass which should include most flash drivers.
@@ -20,4 +20,50 @@ static inline struct mtd_info *mtd_get_info(struct udevice *dev)
return dev_get_uclass_priv(dev);
}
+struct mtd_ops {
+ int (*erase)(struct udevice *dev, struct erase_info *instr);
+ int (*read)(struct udevice *dev, loff_t from, size_t len,
+ size_t *retlen, u_char *buf);
+ int (*write)(struct udevice *dev, loff_t to, size_t len,
+ size_t *retlen, const u_char *buf);
+};
+
+/* Access the serial operations for a device */
+#define mtd_get_ops(dev) ((struct mtd_ops *)(dev)->driver->ops)
+
+/**
+ * mtd_dread() - read data from MTD device
+ *
+ * @mtd: MTD device
+ * @from: offset into device in bytes to read from
+ * @len: length of bytes to read
+ * @retlen: length of return bytes read to
+ * @buf: buffer to put the data that is read
+ * @return 0 if OK, -ve on error
+ */
+int mtd_dread(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen,
+ u_char *buf);
+
+/**
+ * mtd_dwrite() - write data to MTD device
+ *
+ * @mtd: MTD device
+ * @to: offset into device in bytes to write to
+ * @len: length of bytes to write
+ * @retlen: length of return bytes to write to
+ * @buf: buffer containing bytes to write
+ * @return 0 if OK, -ve on error
+ */
+int mtd_dwrite(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen,
+ const u_char *buf);
+
+/**
+ * mtd_derase() - erase blocks of the MTD device
+ *
+ * @mtd: MTD device
+ * @instr: erase info details of MTD device
+ * @return 0 if OK, -ve on error
+ */
+int mtd_derase(struct mtd_info *mtd, struct erase_info *instr);
+
#endif /* _MTD_H_ */