xref: /rk3399_rockchip-uboot/include/linux/mtd/mtd.h (revision 09c3280754f8f68a4d7fc0ee397a92b38c4f59e4)
1932394acSWolfgang Denk /*
2ff94bc40SHeiko Schocher  * Copyright © 1999-2010 David Woodhouse <dwmw2@infradead.org> et al.
3932394acSWolfgang Denk  *
4932394acSWolfgang Denk  * Released under GPL
5ff94bc40SHeiko Schocher  *
6932394acSWolfgang Denk  */
7932394acSWolfgang Denk 
8932394acSWolfgang Denk #ifndef __MTD_MTD_H__
9932394acSWolfgang Denk #define __MTD_MTD_H__
10cfa460adSWilliam Juul 
11ff94bc40SHeiko Schocher #ifndef __UBOOT__
12932394acSWolfgang Denk #include <linux/types.h>
13ff94bc40SHeiko Schocher #include <linux/uio.h>
14ff94bc40SHeiko Schocher #include <linux/notifier.h>
15ff94bc40SHeiko Schocher #include <linux/device.h>
16ff94bc40SHeiko Schocher 
17ff94bc40SHeiko Schocher #include <mtd/mtd-abi.h>
18ff94bc40SHeiko Schocher 
19ff94bc40SHeiko Schocher #include <asm/div64.h>
20ff94bc40SHeiko Schocher #else
21ff94bc40SHeiko Schocher #include <linux/compat.h>
22dfe64e2cSSergey Lapin #include <mtd/mtd-abi.h>
23dfe64e2cSSergey Lapin #include <asm/errno.h>
24ff94bc40SHeiko Schocher #include <div64.h>
25932394acSWolfgang Denk 
26cfa460adSWilliam Juul #define MAX_MTD_DEVICES 32
27ff94bc40SHeiko Schocher #endif
28932394acSWolfgang Denk 
29932394acSWolfgang Denk #define MTD_ERASE_PENDING	0x01
30932394acSWolfgang Denk #define MTD_ERASING		0x02
31932394acSWolfgang Denk #define MTD_ERASE_SUSPEND	0x04
32932394acSWolfgang Denk #define MTD_ERASE_DONE		0x08
33932394acSWolfgang Denk #define MTD_ERASE_FAILED	0x10
34932394acSWolfgang Denk 
358d2effeaSStefan Roese #define MTD_FAIL_ADDR_UNKNOWN -1LL
368d2effeaSStefan Roese 
37d438d508SKyungmin Park /*
38ff94bc40SHeiko Schocher  * If the erase fails, fail_addr might indicate exactly which block failed. If
39ff94bc40SHeiko Schocher  * fail_addr = MTD_FAIL_ADDR_UNKNOWN, the failure was not at the device level
40ff94bc40SHeiko Schocher  * or was not specific to any particular block.
41d438d508SKyungmin Park  */
42932394acSWolfgang Denk struct erase_info {
43932394acSWolfgang Denk 	struct mtd_info *mtd;
448d2effeaSStefan Roese 	uint64_t addr;
458d2effeaSStefan Roese 	uint64_t len;
468d2effeaSStefan Roese 	uint64_t fail_addr;
47932394acSWolfgang Denk 	u_long time;
48932394acSWolfgang Denk 	u_long retries;
49ff94bc40SHeiko Schocher 	unsigned dev;
50ff94bc40SHeiko Schocher 	unsigned cell;
51932394acSWolfgang Denk 	void (*callback) (struct erase_info *self);
52932394acSWolfgang Denk 	u_long priv;
53932394acSWolfgang Denk 	u_char state;
54932394acSWolfgang Denk 	struct erase_info *next;
556d41419fSMarek Vasut 	int scrub;
56932394acSWolfgang Denk };
57932394acSWolfgang Denk 
58932394acSWolfgang Denk struct mtd_erase_region_info {
598d2effeaSStefan Roese 	uint64_t offset;		/* At which this region starts, from the beginning of the MTD */
60ff94bc40SHeiko Schocher 	uint32_t erasesize;		/* For this region */
61ff94bc40SHeiko Schocher 	uint32_t numblocks;		/* Number of blocks of erasesize in this region */
62cfa460adSWilliam Juul 	unsigned long *lockmap;		/* If keeping bitmap of locks */
63cfa460adSWilliam Juul };
64cfa460adSWilliam Juul 
65cfa460adSWilliam Juul /**
66cfa460adSWilliam Juul  * struct mtd_oob_ops - oob operation operands
67cfa460adSWilliam Juul  * @mode:	operation mode
68cfa460adSWilliam Juul  *
69cfa460adSWilliam Juul  * @len:	number of data bytes to write/read
70cfa460adSWilliam Juul  *
71cfa460adSWilliam Juul  * @retlen:	number of data bytes written/read
72cfa460adSWilliam Juul  *
73cfa460adSWilliam Juul  * @ooblen:	number of oob bytes to write/read
74cfa460adSWilliam Juul  * @oobretlen:	number of oob bytes written/read
75cfa460adSWilliam Juul  * @ooboffs:	offset of oob data in the oob area (only relevant when
76dfe64e2cSSergey Lapin  *		mode = MTD_OPS_PLACE_OOB or MTD_OPS_RAW)
77cfa460adSWilliam Juul  * @datbuf:	data buffer - if NULL only oob data are read/written
78cfa460adSWilliam Juul  * @oobbuf:	oob data buffer
79cfa460adSWilliam Juul  *
80ff94bc40SHeiko Schocher  * Note, it is allowed to read more than one OOB area at one go, but not write.
81cfa460adSWilliam Juul  * The interface assumes that the OOB write requests program only one page's
82cfa460adSWilliam Juul  * OOB area.
83cfa460adSWilliam Juul  */
84cfa460adSWilliam Juul struct mtd_oob_ops {
85dfe64e2cSSergey Lapin 	unsigned int	mode;
86cfa460adSWilliam Juul 	size_t		len;
87cfa460adSWilliam Juul 	size_t		retlen;
88cfa460adSWilliam Juul 	size_t		ooblen;
89cfa460adSWilliam Juul 	size_t		oobretlen;
90cfa460adSWilliam Juul 	uint32_t	ooboffs;
91cfa460adSWilliam Juul 	uint8_t		*datbuf;
92cfa460adSWilliam Juul 	uint8_t		*oobbuf;
93932394acSWolfgang Denk };
94932394acSWolfgang Denk 
9568ec9c85SPrabhakar Kushwaha #ifdef CONFIG_SYS_NAND_MAX_OOBFREE
9668ec9c85SPrabhakar Kushwaha #define MTD_MAX_OOBFREE_ENTRIES_LARGE	CONFIG_SYS_NAND_MAX_OOBFREE
9768ec9c85SPrabhakar Kushwaha #else
9868ec9c85SPrabhakar Kushwaha #define MTD_MAX_OOBFREE_ENTRIES_LARGE	32
9968ec9c85SPrabhakar Kushwaha #endif
10068ec9c85SPrabhakar Kushwaha 
10168ec9c85SPrabhakar Kushwaha #ifdef CONFIG_SYS_NAND_MAX_ECCPOS
10268ec9c85SPrabhakar Kushwaha #define MTD_MAX_ECCPOS_ENTRIES_LARGE	CONFIG_SYS_NAND_MAX_ECCPOS
10368ec9c85SPrabhakar Kushwaha #else
10468ec9c85SPrabhakar Kushwaha #define MTD_MAX_ECCPOS_ENTRIES_LARGE	640
10568ec9c85SPrabhakar Kushwaha #endif
10668ec9c85SPrabhakar Kushwaha 
10768ec9c85SPrabhakar Kushwaha /*
108ff94bc40SHeiko Schocher  * Internal ECC layout control structure. For historical reasons, there is a
109ff94bc40SHeiko Schocher  * similar, smaller struct nand_ecclayout_user (in mtd-abi.h) that is retained
110ff94bc40SHeiko Schocher  * for export to user-space via the ECCGETLAYOUT ioctl.
111ff94bc40SHeiko Schocher  * nand_ecclayout should be expandable in the future simply by the above macros.
11268ec9c85SPrabhakar Kushwaha  */
11368ec9c85SPrabhakar Kushwaha struct nand_ecclayout {
114ff94bc40SHeiko Schocher 	__u32 eccbytes;
115ff94bc40SHeiko Schocher 	__u32 eccpos[MTD_MAX_ECCPOS_ENTRIES_LARGE];
116ff94bc40SHeiko Schocher 	__u32 oobavail;
11768ec9c85SPrabhakar Kushwaha 	struct nand_oobfree oobfree[MTD_MAX_OOBFREE_ENTRIES_LARGE];
11868ec9c85SPrabhakar Kushwaha };
11968ec9c85SPrabhakar Kushwaha 
120ff94bc40SHeiko Schocher struct module;	/* only needed for owner field in mtd_info */
121ff94bc40SHeiko Schocher 
122932394acSWolfgang Denk struct mtd_info {
123932394acSWolfgang Denk 	u_char type;
124ff94bc40SHeiko Schocher 	uint32_t flags;
125ff94bc40SHeiko Schocher 	uint64_t size;	 // Total size of the MTD
126932394acSWolfgang Denk 
127fa82f871SAlbert ARIBAUD 	/* "Major" erase size for the device. Naïve users may take this
128932394acSWolfgang Denk 	 * to be the only erase size available, or may use the more detailed
129932394acSWolfgang Denk 	 * information below if they desire
130932394acSWolfgang Denk 	 */
131ff94bc40SHeiko Schocher 	uint32_t erasesize;
132cfa460adSWilliam Juul 	/* Minimal writable flash unit size. In case of NOR flash it is 1 (even
133cfa460adSWilliam Juul 	 * though individual bits can be cleared), in case of NAND flash it is
134cfa460adSWilliam Juul 	 * one NAND page (or half, or one-fourths of it), in case of ECC-ed NOR
135cfa460adSWilliam Juul 	 * it is of ECC block size, etc. It is illegal to have writesize = 0.
136cfa460adSWilliam Juul 	 * Any driver registering a struct mtd_info must ensure a writesize of
137cfa460adSWilliam Juul 	 * 1 or larger.
138cfa460adSWilliam Juul 	 */
139ff94bc40SHeiko Schocher 	uint32_t writesize;
140932394acSWolfgang Denk 
141ff94bc40SHeiko Schocher 	/*
142ff94bc40SHeiko Schocher 	 * Size of the write buffer used by the MTD. MTD devices having a write
143ff94bc40SHeiko Schocher 	 * buffer can write multiple writesize chunks at a time. E.g. while
144ff94bc40SHeiko Schocher 	 * writing 4 * writesize bytes to a device with 2 * writesize bytes
145ff94bc40SHeiko Schocher 	 * buffer the MTD driver can (but doesn't have to) do 2 writesize
146ff94bc40SHeiko Schocher 	 * operations, but not 4. Currently, all NANDs have writebufsize
147ff94bc40SHeiko Schocher 	 * equivalent to writesize (NAND page size). Some NOR flashes do have
148ff94bc40SHeiko Schocher 	 * writebufsize greater than writesize.
149ff94bc40SHeiko Schocher 	 */
150ff94bc40SHeiko Schocher 	uint32_t writebufsize;
151ff94bc40SHeiko Schocher 
152ff94bc40SHeiko Schocher 	uint32_t oobsize;   // Amount of OOB data per block (e.g. 16)
153ff94bc40SHeiko Schocher 	uint32_t oobavail;  // Available OOB bytes per block
154ff94bc40SHeiko Schocher 
155ff94bc40SHeiko Schocher 	/*
156ff94bc40SHeiko Schocher 	 * If erasesize is a power of 2 then the shift is stored in
157ff94bc40SHeiko Schocher 	 * erasesize_shift otherwise erasesize_shift is zero. Ditto writesize.
158ff94bc40SHeiko Schocher 	 */
159ff94bc40SHeiko Schocher 	unsigned int erasesize_shift;
160ff94bc40SHeiko Schocher 	unsigned int writesize_shift;
161ff94bc40SHeiko Schocher 	/* Masks based on erasesize_shift and writesize_shift */
162ff94bc40SHeiko Schocher 	unsigned int erasesize_mask;
163ff94bc40SHeiko Schocher 	unsigned int writesize_mask;
164932394acSWolfgang Denk 
165dfe64e2cSSergey Lapin 	/*
166dfe64e2cSSergey Lapin 	 * read ops return -EUCLEAN if max number of bitflips corrected on any
167dfe64e2cSSergey Lapin 	 * one region comprising an ecc step equals or exceeds this value.
168dfe64e2cSSergey Lapin 	 * Settable by driver, else defaults to ecc_strength.  User can override
169dfe64e2cSSergey Lapin 	 * in sysfs.  N.B. The meaning of the -EUCLEAN return code has changed;
170dfe64e2cSSergey Lapin 	 * see Documentation/ABI/testing/sysfs-class-mtd for more detail.
171dfe64e2cSSergey Lapin 	 */
172dfe64e2cSSergey Lapin 	unsigned int bitflip_threshold;
173dfe64e2cSSergey Lapin 
174ff94bc40SHeiko Schocher 	// Kernel-only stuff starts here.
175ff94bc40SHeiko Schocher #ifndef __UBOOT__
176c45912d8SScott Wood 	const char *name;
177ff94bc40SHeiko Schocher #else
178ff94bc40SHeiko Schocher 	char *name;
179ff94bc40SHeiko Schocher #endif
180932394acSWolfgang Denk 	int index;
181932394acSWolfgang Denk 
182dfe64e2cSSergey Lapin 	/* ECC layout structure pointer - read only! */
183cfa460adSWilliam Juul 	struct nand_ecclayout *ecclayout;
184932394acSWolfgang Denk 
185ff94bc40SHeiko Schocher 	/* the ecc step size. */
186ff94bc40SHeiko Schocher 	unsigned int ecc_step_size;
187ff94bc40SHeiko Schocher 
188dfe64e2cSSergey Lapin 	/* max number of correctible bit errors per ecc step */
189dfe64e2cSSergey Lapin 	unsigned int ecc_strength;
190dfe64e2cSSergey Lapin 
191932394acSWolfgang Denk 	/* Data for variable erase regions. If numeraseregions is zero,
192932394acSWolfgang Denk 	 * it means that the whole device has erasesize as given above.
193932394acSWolfgang Denk 	 */
194932394acSWolfgang Denk 	int numeraseregions;
195932394acSWolfgang Denk 	struct mtd_erase_region_info *eraseregions;
196932394acSWolfgang Denk 
197c45912d8SScott Wood 	/*
198dfe64e2cSSergey Lapin 	 * Do not call via these pointers, use corresponding mtd_*()
199dfe64e2cSSergey Lapin 	 * wrappers instead.
200c45912d8SScott Wood 	 */
201dfe64e2cSSergey Lapin 	int (*_erase) (struct mtd_info *mtd, struct erase_info *instr);
202ff94bc40SHeiko Schocher #ifndef __UBOOT__
203dfe64e2cSSergey Lapin 	int (*_point) (struct mtd_info *mtd, loff_t from, size_t len,
204ff94bc40SHeiko Schocher 		       size_t *retlen, void **virt, resource_size_t *phys);
205ff94bc40SHeiko Schocher 	int (*_unpoint) (struct mtd_info *mtd, loff_t from, size_t len);
206ff94bc40SHeiko Schocher #endif
207ff94bc40SHeiko Schocher 	unsigned long (*_get_unmapped_area) (struct mtd_info *mtd,
208ff94bc40SHeiko Schocher 					     unsigned long len,
209ff94bc40SHeiko Schocher 					     unsigned long offset,
210ff94bc40SHeiko Schocher 					     unsigned long flags);
211dfe64e2cSSergey Lapin 	int (*_read) (struct mtd_info *mtd, loff_t from, size_t len,
212dfe64e2cSSergey Lapin 		      size_t *retlen, u_char *buf);
213dfe64e2cSSergey Lapin 	int (*_write) (struct mtd_info *mtd, loff_t to, size_t len,
214dfe64e2cSSergey Lapin 		       size_t *retlen, const u_char *buf);
215ff94bc40SHeiko Schocher 	int (*_panic_write) (struct mtd_info *mtd, loff_t to, size_t len,
216ff94bc40SHeiko Schocher 			     size_t *retlen, const u_char *buf);
217dfe64e2cSSergey Lapin 	int (*_read_oob) (struct mtd_info *mtd, loff_t from,
218cfa460adSWilliam Juul 			  struct mtd_oob_ops *ops);
219dfe64e2cSSergey Lapin 	int (*_write_oob) (struct mtd_info *mtd, loff_t to,
220cfa460adSWilliam Juul 			   struct mtd_oob_ops *ops);
2214e67c571SHeiko Schocher 	int (*_get_fact_prot_info) (struct mtd_info *mtd, size_t len,
2224e67c571SHeiko Schocher 				    size_t *retlen, struct otp_info *buf);
223dfe64e2cSSergey Lapin 	int (*_read_fact_prot_reg) (struct mtd_info *mtd, loff_t from,
224dfe64e2cSSergey Lapin 				    size_t len, size_t *retlen, u_char *buf);
2254e67c571SHeiko Schocher 	int (*_get_user_prot_info) (struct mtd_info *mtd, size_t len,
2264e67c571SHeiko Schocher 				    size_t *retlen, struct otp_info *buf);
227dfe64e2cSSergey Lapin 	int (*_read_user_prot_reg) (struct mtd_info *mtd, loff_t from,
228dfe64e2cSSergey Lapin 				    size_t len, size_t *retlen, u_char *buf);
229ff94bc40SHeiko Schocher 	int (*_write_user_prot_reg) (struct mtd_info *mtd, loff_t to,
230ff94bc40SHeiko Schocher 				     size_t len, size_t *retlen, u_char *buf);
231dfe64e2cSSergey Lapin 	int (*_lock_user_prot_reg) (struct mtd_info *mtd, loff_t from,
232dfe64e2cSSergey Lapin 				    size_t len);
233ff94bc40SHeiko Schocher #ifndef __UBOOT__
234ff94bc40SHeiko Schocher 	int (*_writev) (struct mtd_info *mtd, const struct kvec *vecs,
235ff94bc40SHeiko Schocher 			unsigned long count, loff_t to, size_t *retlen);
236ff94bc40SHeiko Schocher #endif
237dfe64e2cSSergey Lapin 	void (*_sync) (struct mtd_info *mtd);
238dfe64e2cSSergey Lapin 	int (*_lock) (struct mtd_info *mtd, loff_t ofs, uint64_t len);
239dfe64e2cSSergey Lapin 	int (*_unlock) (struct mtd_info *mtd, loff_t ofs, uint64_t len);
240ff94bc40SHeiko Schocher 	int (*_is_locked) (struct mtd_info *mtd, loff_t ofs, uint64_t len);
241dfe64e2cSSergey Lapin 	int (*_block_isbad) (struct mtd_info *mtd, loff_t ofs);
242dfe64e2cSSergey Lapin 	int (*_block_markbad) (struct mtd_info *mtd, loff_t ofs);
243ff94bc40SHeiko Schocher #ifndef __UBOOT__
244ff94bc40SHeiko Schocher 	int (*_suspend) (struct mtd_info *mtd);
245ff94bc40SHeiko Schocher 	void (*_resume) (struct mtd_info *mtd);
246ff94bc40SHeiko Schocher #endif
247932394acSWolfgang Denk 	/*
248dfe64e2cSSergey Lapin 	 * If the driver is something smart, like UBI, it may need to maintain
249dfe64e2cSSergey Lapin 	 * its own reference counting. The below functions are only for driver.
250932394acSWolfgang Denk 	 */
251dfe64e2cSSergey Lapin 	int (*_get_device) (struct mtd_info *mtd);
252dfe64e2cSSergey Lapin 	void (*_put_device) (struct mtd_info *mtd);
253cfa460adSWilliam Juul 
254ff94bc40SHeiko Schocher #ifndef __UBOOT__
255ff94bc40SHeiko Schocher 	/* Backing device capabilities for this device
256ff94bc40SHeiko Schocher 	 * - provides mmap capabilities
257932394acSWolfgang Denk 	 */
258ff94bc40SHeiko Schocher 	struct backing_dev_info *backing_dev_info;
259ff94bc40SHeiko Schocher 
260cfa460adSWilliam Juul 	struct notifier_block reboot_notifier;  /* default mode before reboot */
261cfa460adSWilliam Juul #endif
262cfa460adSWilliam Juul 
263cfa460adSWilliam Juul 	/* ECC status information */
264cfa460adSWilliam Juul 	struct mtd_ecc_stats ecc_stats;
265cfa460adSWilliam Juul 	/* Subpage shift (NAND) */
266cfa460adSWilliam Juul 	int subpage_sft;
267cfa460adSWilliam Juul 
268932394acSWolfgang Denk 	void *priv;
269932394acSWolfgang Denk 
270932394acSWolfgang Denk 	struct module *owner;
271ff94bc40SHeiko Schocher #ifndef __UBOOT__
272ff94bc40SHeiko Schocher 	struct device dev;
273ff94bc40SHeiko Schocher #endif
274932394acSWolfgang Denk 	int usecount;
275932394acSWolfgang Denk };
276932394acSWolfgang Denk 
277dfe64e2cSSergey Lapin int mtd_erase(struct mtd_info *mtd, struct erase_info *instr);
278ff94bc40SHeiko Schocher #ifndef __UBOOT__
279ff94bc40SHeiko Schocher int mtd_point(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen,
280ff94bc40SHeiko Schocher 	      void **virt, resource_size_t *phys);
281ff94bc40SHeiko Schocher int mtd_unpoint(struct mtd_info *mtd, loff_t from, size_t len);
282ff94bc40SHeiko Schocher #endif
283ff94bc40SHeiko Schocher unsigned long mtd_get_unmapped_area(struct mtd_info *mtd, unsigned long len,
284ff94bc40SHeiko Schocher 				    unsigned long offset, unsigned long flags);
285dfe64e2cSSergey Lapin int mtd_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen,
286dfe64e2cSSergey Lapin 	     u_char *buf);
287dfe64e2cSSergey Lapin int mtd_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen,
288dfe64e2cSSergey Lapin 	      const u_char *buf);
289dfe64e2cSSergey Lapin int mtd_panic_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen,
290dfe64e2cSSergey Lapin 		    const u_char *buf);
291dfe64e2cSSergey Lapin 
292dfe64e2cSSergey Lapin int mtd_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops);
293dfe64e2cSSergey Lapin 
294dfe64e2cSSergey Lapin static inline int mtd_write_oob(struct mtd_info *mtd, loff_t to,
295dfe64e2cSSergey Lapin 				struct mtd_oob_ops *ops)
296dfe64e2cSSergey Lapin {
297dfe64e2cSSergey Lapin 	ops->retlen = ops->oobretlen = 0;
298dfe64e2cSSergey Lapin 	if (!mtd->_write_oob)
299dfe64e2cSSergey Lapin 		return -EOPNOTSUPP;
300dfe64e2cSSergey Lapin 	if (!(mtd->flags & MTD_WRITEABLE))
301dfe64e2cSSergey Lapin 		return -EROFS;
302dfe64e2cSSergey Lapin 	return mtd->_write_oob(mtd, to, ops);
303dfe64e2cSSergey Lapin }
304dfe64e2cSSergey Lapin 
3054e67c571SHeiko Schocher int mtd_get_fact_prot_info(struct mtd_info *mtd, size_t len, size_t *retlen,
3064e67c571SHeiko Schocher 			   struct otp_info *buf);
307dfe64e2cSSergey Lapin int mtd_read_fact_prot_reg(struct mtd_info *mtd, loff_t from, size_t len,
308dfe64e2cSSergey Lapin 			   size_t *retlen, u_char *buf);
3094e67c571SHeiko Schocher int mtd_get_user_prot_info(struct mtd_info *mtd, size_t len, size_t *retlen,
3104e67c571SHeiko Schocher 			   struct otp_info *buf);
311dfe64e2cSSergey Lapin int mtd_read_user_prot_reg(struct mtd_info *mtd, loff_t from, size_t len,
312dfe64e2cSSergey Lapin 			   size_t *retlen, u_char *buf);
313dfe64e2cSSergey Lapin int mtd_write_user_prot_reg(struct mtd_info *mtd, loff_t to, size_t len,
314dfe64e2cSSergey Lapin 			    size_t *retlen, u_char *buf);
315dfe64e2cSSergey Lapin int mtd_lock_user_prot_reg(struct mtd_info *mtd, loff_t from, size_t len);
316dfe64e2cSSergey Lapin 
317ff94bc40SHeiko Schocher #ifndef __UBOOT__
318dfe64e2cSSergey Lapin int mtd_writev(struct mtd_info *mtd, const struct kvec *vecs,
319dfe64e2cSSergey Lapin 	       unsigned long count, loff_t to, size_t *retlen);
320dfe64e2cSSergey Lapin #endif
321dfe64e2cSSergey Lapin 
322dfe64e2cSSergey Lapin static inline void mtd_sync(struct mtd_info *mtd)
323dfe64e2cSSergey Lapin {
324dfe64e2cSSergey Lapin 	if (mtd->_sync)
325dfe64e2cSSergey Lapin 		mtd->_sync(mtd);
326dfe64e2cSSergey Lapin }
327dfe64e2cSSergey Lapin 
328dfe64e2cSSergey Lapin int mtd_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len);
329dfe64e2cSSergey Lapin int mtd_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len);
330dfe64e2cSSergey Lapin int mtd_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len);
331dfe64e2cSSergey Lapin int mtd_block_isbad(struct mtd_info *mtd, loff_t ofs);
332dfe64e2cSSergey Lapin int mtd_block_markbad(struct mtd_info *mtd, loff_t ofs);
333dfe64e2cSSergey Lapin 
334ff94bc40SHeiko Schocher #ifndef __UBOOT__
335ff94bc40SHeiko Schocher static inline int mtd_suspend(struct mtd_info *mtd)
336ff94bc40SHeiko Schocher {
337ff94bc40SHeiko Schocher 	return mtd->_suspend ? mtd->_suspend(mtd) : 0;
338ff94bc40SHeiko Schocher }
339ff94bc40SHeiko Schocher 
340ff94bc40SHeiko Schocher static inline void mtd_resume(struct mtd_info *mtd)
341ff94bc40SHeiko Schocher {
342ff94bc40SHeiko Schocher 	if (mtd->_resume)
343ff94bc40SHeiko Schocher 		mtd->_resume(mtd);
344ff94bc40SHeiko Schocher }
345ff94bc40SHeiko Schocher #endif
346ff94bc40SHeiko Schocher 
3478d2effeaSStefan Roese static inline uint32_t mtd_div_by_eb(uint64_t sz, struct mtd_info *mtd)
3488d2effeaSStefan Roese {
349ff94bc40SHeiko Schocher 	if (mtd->erasesize_shift)
350ff94bc40SHeiko Schocher 		return sz >> mtd->erasesize_shift;
3518d2effeaSStefan Roese 	do_div(sz, mtd->erasesize);
3528d2effeaSStefan Roese 	return sz;
3538d2effeaSStefan Roese }
3548d2effeaSStefan Roese 
3558d2effeaSStefan Roese static inline uint32_t mtd_mod_by_eb(uint64_t sz, struct mtd_info *mtd)
3568d2effeaSStefan Roese {
357ff94bc40SHeiko Schocher 	if (mtd->erasesize_shift)
358ff94bc40SHeiko Schocher 		return sz & mtd->erasesize_mask;
3598d2effeaSStefan Roese 	return do_div(sz, mtd->erasesize);
3608d2effeaSStefan Roese }
361932394acSWolfgang Denk 
362ff94bc40SHeiko Schocher static inline uint32_t mtd_div_by_ws(uint64_t sz, struct mtd_info *mtd)
363ff94bc40SHeiko Schocher {
364ff94bc40SHeiko Schocher 	if (mtd->writesize_shift)
365ff94bc40SHeiko Schocher 		return sz >> mtd->writesize_shift;
366ff94bc40SHeiko Schocher 	do_div(sz, mtd->writesize);
367ff94bc40SHeiko Schocher 	return sz;
368ff94bc40SHeiko Schocher }
369ff94bc40SHeiko Schocher 
370ff94bc40SHeiko Schocher static inline uint32_t mtd_mod_by_ws(uint64_t sz, struct mtd_info *mtd)
371ff94bc40SHeiko Schocher {
372ff94bc40SHeiko Schocher 	if (mtd->writesize_shift)
373ff94bc40SHeiko Schocher 		return sz & mtd->writesize_mask;
374ff94bc40SHeiko Schocher 	return do_div(sz, mtd->writesize);
375ff94bc40SHeiko Schocher }
376ff94bc40SHeiko Schocher 
377dfe64e2cSSergey Lapin static inline int mtd_has_oob(const struct mtd_info *mtd)
378dfe64e2cSSergey Lapin {
379dfe64e2cSSergey Lapin 	return mtd->_read_oob && mtd->_write_oob;
380dfe64e2cSSergey Lapin }
381dfe64e2cSSergey Lapin 
382ff94bc40SHeiko Schocher static inline int mtd_type_is_nand(const struct mtd_info *mtd)
383ff94bc40SHeiko Schocher {
384ff94bc40SHeiko Schocher 	return mtd->type == MTD_NANDFLASH || mtd->type == MTD_MLCNANDFLASH;
385ff94bc40SHeiko Schocher }
386ff94bc40SHeiko Schocher 
387dfe64e2cSSergey Lapin static inline int mtd_can_have_bb(const struct mtd_info *mtd)
388dfe64e2cSSergey Lapin {
389dfe64e2cSSergey Lapin 	return !!mtd->_block_isbad;
390dfe64e2cSSergey Lapin }
391dfe64e2cSSergey Lapin 
392932394acSWolfgang Denk 	/* Kernel-side ioctl definitions */
393932394acSWolfgang Denk 
394ff94bc40SHeiko Schocher struct mtd_partition;
395ff94bc40SHeiko Schocher struct mtd_part_parser_data;
396932394acSWolfgang Denk 
397ff94bc40SHeiko Schocher extern int mtd_device_parse_register(struct mtd_info *mtd,
398ff94bc40SHeiko Schocher 				     const char * const *part_probe_types,
399ff94bc40SHeiko Schocher 				     struct mtd_part_parser_data *parser_data,
400ff94bc40SHeiko Schocher 				     const struct mtd_partition *defparts,
401ff94bc40SHeiko Schocher 				     int defnr_parts);
402ff94bc40SHeiko Schocher #define mtd_device_register(master, parts, nr_parts)	\
403ff94bc40SHeiko Schocher 	mtd_device_parse_register(master, NULL, NULL, parts, nr_parts)
404ff94bc40SHeiko Schocher extern int mtd_device_unregister(struct mtd_info *master);
405932394acSWolfgang Denk extern struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num);
406ff94bc40SHeiko Schocher extern int __get_mtd_device(struct mtd_info *mtd);
407ff94bc40SHeiko Schocher extern void __put_mtd_device(struct mtd_info *mtd);
408cfa460adSWilliam Juul extern struct mtd_info *get_mtd_device_nm(const char *name);
409932394acSWolfgang Denk extern void put_mtd_device(struct mtd_info *mtd);
410ff94bc40SHeiko Schocher 
411ff94bc40SHeiko Schocher 
412ff94bc40SHeiko Schocher #ifndef __UBOOT__
413932394acSWolfgang Denk struct mtd_notifier {
414932394acSWolfgang Denk 	void (*add)(struct mtd_info *mtd);
415932394acSWolfgang Denk 	void (*remove)(struct mtd_info *mtd);
416932394acSWolfgang Denk 	struct list_head list;
417932394acSWolfgang Denk };
418932394acSWolfgang Denk 
419ff94bc40SHeiko Schocher 
420932394acSWolfgang Denk extern void register_mtd_user (struct mtd_notifier *new);
421932394acSWolfgang Denk extern int unregister_mtd_user (struct mtd_notifier *old);
422932394acSWolfgang Denk #endif
423ff94bc40SHeiko Schocher void *mtd_kmalloc_up_to(const struct mtd_info *mtd, size_t *size);
424932394acSWolfgang Denk 
425932394acSWolfgang Denk #ifdef CONFIG_MTD_PARTITIONS
426932394acSWolfgang Denk void mtd_erase_callback(struct erase_info *instr);
427932394acSWolfgang Denk #else
428932394acSWolfgang Denk static inline void mtd_erase_callback(struct erase_info *instr)
429932394acSWolfgang Denk {
430932394acSWolfgang Denk 	if (instr->callback)
431932394acSWolfgang Denk 		instr->callback(instr);
432932394acSWolfgang Denk }
433932394acSWolfgang Denk #endif
434932394acSWolfgang Denk 
435ff94bc40SHeiko Schocher #ifdef __UBOOT__
436932394acSWolfgang Denk /*
437932394acSWolfgang Denk  * Debugging macro and defines
438932394acSWolfgang Denk  */
439932394acSWolfgang Denk #define MTD_DEBUG_LEVEL0	(0)	/* Quiet   */
440932394acSWolfgang Denk #define MTD_DEBUG_LEVEL1	(1)	/* Audible */
441932394acSWolfgang Denk #define MTD_DEBUG_LEVEL2	(2)	/* Loud    */
442932394acSWolfgang Denk #define MTD_DEBUG_LEVEL3	(3)	/* Noisy   */
443932394acSWolfgang Denk 
444932394acSWolfgang Denk #ifdef CONFIG_MTD_DEBUG
445dfe64e2cSSergey Lapin #define pr_debug(args...)	MTDDEBUG(MTD_DEBUG_LEVEL0, args)
4463167c538SScott Wood #define MTDDEBUG(n, args...)				\
447932394acSWolfgang Denk 	do {						\
448932394acSWolfgang Denk 		if (n <= CONFIG_MTD_DEBUG_VERBOSE)	\
449932394acSWolfgang Denk 			printk(KERN_INFO args);		\
450932394acSWolfgang Denk 	} while(0)
451932394acSWolfgang Denk #else /* CONFIG_MTD_DEBUG */
452dfe64e2cSSergey Lapin #define pr_debug(args...)
453c45912d8SScott Wood #define MTDDEBUG(n, args...)				\
454c45912d8SScott Wood 	do {						\
455c45912d8SScott Wood 		if (0)					\
456c45912d8SScott Wood 			printk(KERN_INFO args);		\
457c45912d8SScott Wood 	} while(0)
458932394acSWolfgang Denk #endif /* CONFIG_MTD_DEBUG */
459dfe64e2cSSergey Lapin #define pr_info(args...)	MTDDEBUG(MTD_DEBUG_LEVEL0, args)
460dfe64e2cSSergey Lapin #define pr_warn(args...)	MTDDEBUG(MTD_DEBUG_LEVEL0, args)
461dfe64e2cSSergey Lapin #define pr_err(args...)		MTDDEBUG(MTD_DEBUG_LEVEL0, args)
462ff94bc40SHeiko Schocher #define pr_crit(args...)	MTDDEBUG(MTD_DEBUG_LEVEL0, args)
463ff94bc40SHeiko Schocher #define pr_cont(args...)	MTDDEBUG(MTD_DEBUG_LEVEL0, args)
464ff94bc40SHeiko Schocher #define pr_notice(args...)	MTDDEBUG(MTD_DEBUG_LEVEL0, args)
465ff94bc40SHeiko Schocher #endif
466dfe64e2cSSergey Lapin 
467dfe64e2cSSergey Lapin static inline int mtd_is_bitflip(int err) {
468dfe64e2cSSergey Lapin 	return err == -EUCLEAN;
469dfe64e2cSSergey Lapin }
470dfe64e2cSSergey Lapin 
471dfe64e2cSSergey Lapin static inline int mtd_is_eccerr(int err) {
472dfe64e2cSSergey Lapin 	return err == -EBADMSG;
473dfe64e2cSSergey Lapin }
474dfe64e2cSSergey Lapin 
475dfe64e2cSSergey Lapin static inline int mtd_is_bitflip_or_eccerr(int err) {
476dfe64e2cSSergey Lapin 	return mtd_is_bitflip(err) || mtd_is_eccerr(err);
477dfe64e2cSSergey Lapin }
478932394acSWolfgang Denk 
479ff94bc40SHeiko Schocher #ifdef __UBOOT__
480ff94bc40SHeiko Schocher /* drivers/mtd/mtdcore.h */
481ff94bc40SHeiko Schocher int add_mtd_device(struct mtd_info *mtd);
482ddf7bcfaSHeiko Schocher int del_mtd_device(struct mtd_info *mtd);
483ff94bc40SHeiko Schocher int add_mtd_partitions(struct mtd_info *, const struct mtd_partition *, int);
484ff94bc40SHeiko Schocher int del_mtd_partitions(struct mtd_info *);
485*09c32807SHeiko Schocher 
486*09c32807SHeiko Schocher int mtd_arg_off(const char *arg, int *idx, loff_t *off, loff_t *size,
487*09c32807SHeiko Schocher 		loff_t *maxsize, int devtype, int chipsize);
488*09c32807SHeiko Schocher int mtd_arg_off_size(int argc, char *const argv[], int *idx, loff_t *off,
489*09c32807SHeiko Schocher 		 loff_t *size, loff_t *maxsize, int devtype, int chipsize);
490ff94bc40SHeiko Schocher #endif
491932394acSWolfgang Denk #endif /* __MTD_MTD_H__ */
492