xref: /rk3399_rockchip-uboot/include/linux/mtd/mtd.h (revision 504668197e7197da1a2a34a2d43ae93e5b496ded)
1932394acSWolfgang Denk /*
2ff94bc40SHeiko Schocher  * Copyright © 1999-2010 David Woodhouse <dwmw2@infradead.org> et al.
3932394acSWolfgang Denk  *
478e9e71cSTom Rini  * SPDX-License-Identifier:	GPL-2.0+
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>
231221ce45SMasahiro Yamada #include <linux/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
1042580a2a7SSiva Durga Prasad Paladugu #define MTD_MAX_ECCPOS_ENTRIES_LARGE	680
10568ec9c85SPrabhakar Kushwaha #endif
106c44c4cceSBoris Brezillon /**
107c44c4cceSBoris Brezillon  * struct mtd_oob_region - oob region definition
108c44c4cceSBoris Brezillon  * @offset: region offset
109c44c4cceSBoris Brezillon  * @length: region length
110c44c4cceSBoris Brezillon  *
111c44c4cceSBoris Brezillon  * This structure describes a region of the OOB area, and is used
112c44c4cceSBoris Brezillon  * to retrieve ECC or free bytes sections.
113c44c4cceSBoris Brezillon  * Each section is defined by an offset within the OOB area and a
114c44c4cceSBoris Brezillon  * length.
115c44c4cceSBoris Brezillon  */
116c44c4cceSBoris Brezillon struct mtd_oob_region {
117c44c4cceSBoris Brezillon 	u32 offset;
118c44c4cceSBoris Brezillon 	u32 length;
119c44c4cceSBoris Brezillon };
120c44c4cceSBoris Brezillon 
121c44c4cceSBoris Brezillon /*
122c44c4cceSBoris Brezillon  * struct mtd_ooblayout_ops - NAND OOB layout operations
123c44c4cceSBoris Brezillon  * @ecc: function returning an ECC region in the OOB area.
124c44c4cceSBoris Brezillon  *	 Should return -ERANGE if %section exceeds the total number of
125c44c4cceSBoris Brezillon  *	 ECC sections.
126c44c4cceSBoris Brezillon  * @free: function returning a free region in the OOB area.
127c44c4cceSBoris Brezillon  *	  Should return -ERANGE if %section exceeds the total number of
128c44c4cceSBoris Brezillon  *	  free sections.
129c44c4cceSBoris Brezillon  */
130c44c4cceSBoris Brezillon struct mtd_ooblayout_ops {
131c44c4cceSBoris Brezillon 	int (*ecc)(struct mtd_info *mtd, int section,
132c44c4cceSBoris Brezillon 		   struct mtd_oob_region *oobecc);
133c44c4cceSBoris Brezillon 	int (*free)(struct mtd_info *mtd, int section,
134c44c4cceSBoris Brezillon 		    struct mtd_oob_region *oobfree);
135c44c4cceSBoris Brezillon };
13668ec9c85SPrabhakar Kushwaha 
13768ec9c85SPrabhakar Kushwaha /*
138ff94bc40SHeiko Schocher  * Internal ECC layout control structure. For historical reasons, there is a
139ff94bc40SHeiko Schocher  * similar, smaller struct nand_ecclayout_user (in mtd-abi.h) that is retained
140ff94bc40SHeiko Schocher  * for export to user-space via the ECCGETLAYOUT ioctl.
141ff94bc40SHeiko Schocher  * nand_ecclayout should be expandable in the future simply by the above macros.
14268ec9c85SPrabhakar Kushwaha  */
14368ec9c85SPrabhakar Kushwaha struct nand_ecclayout {
144ff94bc40SHeiko Schocher 	__u32 eccbytes;
145ff94bc40SHeiko Schocher 	__u32 eccpos[MTD_MAX_ECCPOS_ENTRIES_LARGE];
146ff94bc40SHeiko Schocher 	__u32 oobavail;
14768ec9c85SPrabhakar Kushwaha 	struct nand_oobfree oobfree[MTD_MAX_OOBFREE_ENTRIES_LARGE];
14868ec9c85SPrabhakar Kushwaha };
14968ec9c85SPrabhakar Kushwaha 
150ff94bc40SHeiko Schocher struct module;	/* only needed for owner field in mtd_info */
151ff94bc40SHeiko Schocher 
152932394acSWolfgang Denk struct mtd_info {
153932394acSWolfgang Denk 	u_char type;
154ff94bc40SHeiko Schocher 	uint32_t flags;
155ff94bc40SHeiko Schocher 	uint64_t size;	 // Total size of the MTD
156932394acSWolfgang Denk 
157fa82f871SAlbert ARIBAUD 	/* "Major" erase size for the device. Naïve users may take this
158932394acSWolfgang Denk 	 * to be the only erase size available, or may use the more detailed
159932394acSWolfgang Denk 	 * information below if they desire
160932394acSWolfgang Denk 	 */
161ff94bc40SHeiko Schocher 	uint32_t erasesize;
162cfa460adSWilliam Juul 	/* Minimal writable flash unit size. In case of NOR flash it is 1 (even
163cfa460adSWilliam Juul 	 * though individual bits can be cleared), in case of NAND flash it is
164cfa460adSWilliam Juul 	 * one NAND page (or half, or one-fourths of it), in case of ECC-ed NOR
165cfa460adSWilliam Juul 	 * it is of ECC block size, etc. It is illegal to have writesize = 0.
166cfa460adSWilliam Juul 	 * Any driver registering a struct mtd_info must ensure a writesize of
167cfa460adSWilliam Juul 	 * 1 or larger.
168cfa460adSWilliam Juul 	 */
169ff94bc40SHeiko Schocher 	uint32_t writesize;
170932394acSWolfgang Denk 
171ff94bc40SHeiko Schocher 	/*
172ff94bc40SHeiko Schocher 	 * Size of the write buffer used by the MTD. MTD devices having a write
173ff94bc40SHeiko Schocher 	 * buffer can write multiple writesize chunks at a time. E.g. while
174ff94bc40SHeiko Schocher 	 * writing 4 * writesize bytes to a device with 2 * writesize bytes
175ff94bc40SHeiko Schocher 	 * buffer the MTD driver can (but doesn't have to) do 2 writesize
176ff94bc40SHeiko Schocher 	 * operations, but not 4. Currently, all NANDs have writebufsize
177ff94bc40SHeiko Schocher 	 * equivalent to writesize (NAND page size). Some NOR flashes do have
178ff94bc40SHeiko Schocher 	 * writebufsize greater than writesize.
179ff94bc40SHeiko Schocher 	 */
180ff94bc40SHeiko Schocher 	uint32_t writebufsize;
181ff94bc40SHeiko Schocher 
182ff94bc40SHeiko Schocher 	uint32_t oobsize;   // Amount of OOB data per block (e.g. 16)
183ff94bc40SHeiko Schocher 	uint32_t oobavail;  // Available OOB bytes per block
184ff94bc40SHeiko Schocher 
185ff94bc40SHeiko Schocher 	/*
186ff94bc40SHeiko Schocher 	 * If erasesize is a power of 2 then the shift is stored in
187ff94bc40SHeiko Schocher 	 * erasesize_shift otherwise erasesize_shift is zero. Ditto writesize.
188ff94bc40SHeiko Schocher 	 */
189ff94bc40SHeiko Schocher 	unsigned int erasesize_shift;
190ff94bc40SHeiko Schocher 	unsigned int writesize_shift;
191ff94bc40SHeiko Schocher 	/* Masks based on erasesize_shift and writesize_shift */
192ff94bc40SHeiko Schocher 	unsigned int erasesize_mask;
193ff94bc40SHeiko Schocher 	unsigned int writesize_mask;
194932394acSWolfgang Denk 
195dfe64e2cSSergey Lapin 	/*
196dfe64e2cSSergey Lapin 	 * read ops return -EUCLEAN if max number of bitflips corrected on any
197dfe64e2cSSergey Lapin 	 * one region comprising an ecc step equals or exceeds this value.
198dfe64e2cSSergey Lapin 	 * Settable by driver, else defaults to ecc_strength.  User can override
199dfe64e2cSSergey Lapin 	 * in sysfs.  N.B. The meaning of the -EUCLEAN return code has changed;
200dfe64e2cSSergey Lapin 	 * see Documentation/ABI/testing/sysfs-class-mtd for more detail.
201dfe64e2cSSergey Lapin 	 */
202dfe64e2cSSergey Lapin 	unsigned int bitflip_threshold;
203dfe64e2cSSergey Lapin 
204ff94bc40SHeiko Schocher 	// Kernel-only stuff starts here.
205ff94bc40SHeiko Schocher #ifndef __UBOOT__
206c45912d8SScott Wood 	const char *name;
207ff94bc40SHeiko Schocher #else
208ff94bc40SHeiko Schocher 	char *name;
209ff94bc40SHeiko Schocher #endif
210932394acSWolfgang Denk 	int index;
211932394acSWolfgang Denk 
212c44c4cceSBoris Brezillon 	/* OOB layout description */
213c44c4cceSBoris Brezillon 	const struct mtd_ooblayout_ops *ooblayout;
214c44c4cceSBoris Brezillon 
215dfe64e2cSSergey Lapin 	/* ECC layout structure pointer - read only! */
216cfa460adSWilliam Juul 	struct nand_ecclayout *ecclayout;
217932394acSWolfgang Denk 
218ff94bc40SHeiko Schocher 	/* the ecc step size. */
219ff94bc40SHeiko Schocher 	unsigned int ecc_step_size;
220ff94bc40SHeiko Schocher 
221dfe64e2cSSergey Lapin 	/* max number of correctible bit errors per ecc step */
222dfe64e2cSSergey Lapin 	unsigned int ecc_strength;
223dfe64e2cSSergey Lapin 
224932394acSWolfgang Denk 	/* Data for variable erase regions. If numeraseregions is zero,
225932394acSWolfgang Denk 	 * it means that the whole device has erasesize as given above.
226932394acSWolfgang Denk 	 */
227932394acSWolfgang Denk 	int numeraseregions;
228932394acSWolfgang Denk 	struct mtd_erase_region_info *eraseregions;
229932394acSWolfgang Denk 
230c45912d8SScott Wood 	/*
231dfe64e2cSSergey Lapin 	 * Do not call via these pointers, use corresponding mtd_*()
232dfe64e2cSSergey Lapin 	 * wrappers instead.
233c45912d8SScott Wood 	 */
234dfe64e2cSSergey Lapin 	int (*_erase) (struct mtd_info *mtd, struct erase_info *instr);
235ff94bc40SHeiko Schocher #ifndef __UBOOT__
236dfe64e2cSSergey Lapin 	int (*_point) (struct mtd_info *mtd, loff_t from, size_t len,
237ff94bc40SHeiko Schocher 		       size_t *retlen, void **virt, resource_size_t *phys);
238ff94bc40SHeiko Schocher 	int (*_unpoint) (struct mtd_info *mtd, loff_t from, size_t len);
239ff94bc40SHeiko Schocher #endif
240ff94bc40SHeiko Schocher 	unsigned long (*_get_unmapped_area) (struct mtd_info *mtd,
241ff94bc40SHeiko Schocher 					     unsigned long len,
242ff94bc40SHeiko Schocher 					     unsigned long offset,
243ff94bc40SHeiko Schocher 					     unsigned long flags);
244dfe64e2cSSergey Lapin 	int (*_read) (struct mtd_info *mtd, loff_t from, size_t len,
245dfe64e2cSSergey Lapin 		      size_t *retlen, u_char *buf);
246dfe64e2cSSergey Lapin 	int (*_write) (struct mtd_info *mtd, loff_t to, size_t len,
247dfe64e2cSSergey Lapin 		       size_t *retlen, const u_char *buf);
248ff94bc40SHeiko Schocher 	int (*_panic_write) (struct mtd_info *mtd, loff_t to, size_t len,
249ff94bc40SHeiko Schocher 			     size_t *retlen, const u_char *buf);
250dfe64e2cSSergey Lapin 	int (*_read_oob) (struct mtd_info *mtd, loff_t from,
251cfa460adSWilliam Juul 			  struct mtd_oob_ops *ops);
252dfe64e2cSSergey Lapin 	int (*_write_oob) (struct mtd_info *mtd, loff_t to,
253cfa460adSWilliam Juul 			   struct mtd_oob_ops *ops);
2544e67c571SHeiko Schocher 	int (*_get_fact_prot_info) (struct mtd_info *mtd, size_t len,
2554e67c571SHeiko Schocher 				    size_t *retlen, struct otp_info *buf);
256dfe64e2cSSergey Lapin 	int (*_read_fact_prot_reg) (struct mtd_info *mtd, loff_t from,
257dfe64e2cSSergey Lapin 				    size_t len, size_t *retlen, u_char *buf);
2584e67c571SHeiko Schocher 	int (*_get_user_prot_info) (struct mtd_info *mtd, size_t len,
2594e67c571SHeiko Schocher 				    size_t *retlen, struct otp_info *buf);
260dfe64e2cSSergey Lapin 	int (*_read_user_prot_reg) (struct mtd_info *mtd, loff_t from,
261dfe64e2cSSergey Lapin 				    size_t len, size_t *retlen, u_char *buf);
262ff94bc40SHeiko Schocher 	int (*_write_user_prot_reg) (struct mtd_info *mtd, loff_t to,
263ff94bc40SHeiko Schocher 				     size_t len, size_t *retlen, u_char *buf);
264dfe64e2cSSergey Lapin 	int (*_lock_user_prot_reg) (struct mtd_info *mtd, loff_t from,
265dfe64e2cSSergey Lapin 				    size_t len);
266ff94bc40SHeiko Schocher #ifndef __UBOOT__
267ff94bc40SHeiko Schocher 	int (*_writev) (struct mtd_info *mtd, const struct kvec *vecs,
268ff94bc40SHeiko Schocher 			unsigned long count, loff_t to, size_t *retlen);
269ff94bc40SHeiko Schocher #endif
270dfe64e2cSSergey Lapin 	void (*_sync) (struct mtd_info *mtd);
271dfe64e2cSSergey Lapin 	int (*_lock) (struct mtd_info *mtd, loff_t ofs, uint64_t len);
272dfe64e2cSSergey Lapin 	int (*_unlock) (struct mtd_info *mtd, loff_t ofs, uint64_t len);
273ff94bc40SHeiko Schocher 	int (*_is_locked) (struct mtd_info *mtd, loff_t ofs, uint64_t len);
27486a720aaSEzequiel Garcia 	int (*_block_isreserved) (struct mtd_info *mtd, loff_t ofs);
275dfe64e2cSSergey Lapin 	int (*_block_isbad) (struct mtd_info *mtd, loff_t ofs);
276dfe64e2cSSergey Lapin 	int (*_block_markbad) (struct mtd_info *mtd, loff_t ofs);
277ff94bc40SHeiko Schocher #ifndef __UBOOT__
278ff94bc40SHeiko Schocher 	int (*_suspend) (struct mtd_info *mtd);
279ff94bc40SHeiko Schocher 	void (*_resume) (struct mtd_info *mtd);
2800195a7bbSHeiko Schocher 	void (*_reboot) (struct mtd_info *mtd);
281ff94bc40SHeiko Schocher #endif
282932394acSWolfgang Denk 	/*
283dfe64e2cSSergey Lapin 	 * If the driver is something smart, like UBI, it may need to maintain
284dfe64e2cSSergey Lapin 	 * its own reference counting. The below functions are only for driver.
285932394acSWolfgang Denk 	 */
286dfe64e2cSSergey Lapin 	int (*_get_device) (struct mtd_info *mtd);
287dfe64e2cSSergey Lapin 	void (*_put_device) (struct mtd_info *mtd);
288cfa460adSWilliam Juul 
289ff94bc40SHeiko Schocher #ifndef __UBOOT__
290ff94bc40SHeiko Schocher 	/* Backing device capabilities for this device
291ff94bc40SHeiko Schocher 	 * - provides mmap capabilities
292932394acSWolfgang Denk 	 */
293ff94bc40SHeiko Schocher 	struct backing_dev_info *backing_dev_info;
294ff94bc40SHeiko Schocher 
295cfa460adSWilliam Juul 	struct notifier_block reboot_notifier;  /* default mode before reboot */
296cfa460adSWilliam Juul #endif
297cfa460adSWilliam Juul 
298cfa460adSWilliam Juul 	/* ECC status information */
299cfa460adSWilliam Juul 	struct mtd_ecc_stats ecc_stats;
300cfa460adSWilliam Juul 	/* Subpage shift (NAND) */
301cfa460adSWilliam Juul 	int subpage_sft;
302cfa460adSWilliam Juul 
303932394acSWolfgang Denk 	void *priv;
304932394acSWolfgang Denk 
305932394acSWolfgang Denk 	struct module *owner;
306ff94bc40SHeiko Schocher #ifndef __UBOOT__
307ff94bc40SHeiko Schocher 	struct device dev;
308d8587993SThomas Chou #else
309d8587993SThomas Chou 	struct udevice *dev;
310ff94bc40SHeiko Schocher #endif
311932394acSWolfgang Denk 	int usecount;
312932394acSWolfgang Denk };
313932394acSWolfgang Denk 
314c44c4cceSBoris Brezillon int mtd_ooblayout_ecc(struct mtd_info *mtd, int section,
315c44c4cceSBoris Brezillon 		      struct mtd_oob_region *oobecc);
316c44c4cceSBoris Brezillon int mtd_ooblayout_find_eccregion(struct mtd_info *mtd, int eccbyte,
317c44c4cceSBoris Brezillon 				 int *section,
318c44c4cceSBoris Brezillon 				 struct mtd_oob_region *oobregion);
319c44c4cceSBoris Brezillon int mtd_ooblayout_get_eccbytes(struct mtd_info *mtd, u8 *eccbuf,
320c44c4cceSBoris Brezillon 			       const u8 *oobbuf, int start, int nbytes);
321c44c4cceSBoris Brezillon int mtd_ooblayout_set_eccbytes(struct mtd_info *mtd, const u8 *eccbuf,
322c44c4cceSBoris Brezillon 			       u8 *oobbuf, int start, int nbytes);
323c44c4cceSBoris Brezillon int mtd_ooblayout_free(struct mtd_info *mtd, int section,
324c44c4cceSBoris Brezillon 		       struct mtd_oob_region *oobfree);
325c44c4cceSBoris Brezillon int mtd_ooblayout_get_databytes(struct mtd_info *mtd, u8 *databuf,
326c44c4cceSBoris Brezillon 				const u8 *oobbuf, int start, int nbytes);
327c44c4cceSBoris Brezillon int mtd_ooblayout_set_databytes(struct mtd_info *mtd, const u8 *databuf,
328c44c4cceSBoris Brezillon 				u8 *oobbuf, int start, int nbytes);
329c44c4cceSBoris Brezillon int mtd_ooblayout_count_freebytes(struct mtd_info *mtd);
330c44c4cceSBoris Brezillon int mtd_ooblayout_count_eccbytes(struct mtd_info *mtd);
331c44c4cceSBoris Brezillon 
332c44c4cceSBoris Brezillon static inline void mtd_set_ooblayout(struct mtd_info *mtd,
333c44c4cceSBoris Brezillon 				     const struct mtd_ooblayout_ops *ooblayout)
334c44c4cceSBoris Brezillon {
335c44c4cceSBoris Brezillon 	mtd->ooblayout = ooblayout;
336c44c4cceSBoris Brezillon }
337c44c4cceSBoris Brezillon 
338ceee07b6SScott Wood static inline int mtd_oobavail(struct mtd_info *mtd, struct mtd_oob_ops *ops)
339ceee07b6SScott Wood {
340ceee07b6SScott Wood 	return ops->mode == MTD_OPS_AUTO_OOB ? mtd->oobavail : mtd->oobsize;
341ceee07b6SScott Wood }
342ceee07b6SScott Wood 
343dfe64e2cSSergey Lapin int mtd_erase(struct mtd_info *mtd, struct erase_info *instr);
344ff94bc40SHeiko Schocher #ifndef __UBOOT__
345ff94bc40SHeiko Schocher int mtd_point(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen,
346ff94bc40SHeiko Schocher 	      void **virt, resource_size_t *phys);
347ff94bc40SHeiko Schocher int mtd_unpoint(struct mtd_info *mtd, loff_t from, size_t len);
348ff94bc40SHeiko Schocher #endif
349ff94bc40SHeiko Schocher unsigned long mtd_get_unmapped_area(struct mtd_info *mtd, unsigned long len,
350ff94bc40SHeiko Schocher 				    unsigned long offset, unsigned long flags);
351dfe64e2cSSergey Lapin int mtd_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen,
352dfe64e2cSSergey Lapin 	     u_char *buf);
353dfe64e2cSSergey Lapin int mtd_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen,
354dfe64e2cSSergey Lapin 	      const u_char *buf);
355dfe64e2cSSergey Lapin int mtd_panic_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen,
356dfe64e2cSSergey Lapin 		    const u_char *buf);
357dfe64e2cSSergey Lapin 
358dfe64e2cSSergey Lapin int mtd_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops);
35986db6a45SEzequiel Garcia int mtd_write_oob(struct mtd_info *mtd, loff_t to, struct mtd_oob_ops *ops);
360dfe64e2cSSergey Lapin 
3614e67c571SHeiko Schocher int mtd_get_fact_prot_info(struct mtd_info *mtd, size_t len, size_t *retlen,
3624e67c571SHeiko Schocher 			   struct otp_info *buf);
363dfe64e2cSSergey Lapin int mtd_read_fact_prot_reg(struct mtd_info *mtd, loff_t from, size_t len,
364dfe64e2cSSergey Lapin 			   size_t *retlen, u_char *buf);
3654e67c571SHeiko Schocher int mtd_get_user_prot_info(struct mtd_info *mtd, size_t len, size_t *retlen,
3664e67c571SHeiko Schocher 			   struct otp_info *buf);
367dfe64e2cSSergey Lapin int mtd_read_user_prot_reg(struct mtd_info *mtd, loff_t from, size_t len,
368dfe64e2cSSergey Lapin 			   size_t *retlen, u_char *buf);
369dfe64e2cSSergey Lapin int mtd_write_user_prot_reg(struct mtd_info *mtd, loff_t to, size_t len,
370dfe64e2cSSergey Lapin 			    size_t *retlen, u_char *buf);
371dfe64e2cSSergey Lapin int mtd_lock_user_prot_reg(struct mtd_info *mtd, loff_t from, size_t len);
372dfe64e2cSSergey Lapin 
373ff94bc40SHeiko Schocher #ifndef __UBOOT__
374dfe64e2cSSergey Lapin int mtd_writev(struct mtd_info *mtd, const struct kvec *vecs,
375dfe64e2cSSergey Lapin 	       unsigned long count, loff_t to, size_t *retlen);
376dfe64e2cSSergey Lapin #endif
377dfe64e2cSSergey Lapin 
378dfe64e2cSSergey Lapin static inline void mtd_sync(struct mtd_info *mtd)
379dfe64e2cSSergey Lapin {
380dfe64e2cSSergey Lapin 	if (mtd->_sync)
381dfe64e2cSSergey Lapin 		mtd->_sync(mtd);
382dfe64e2cSSergey Lapin }
383dfe64e2cSSergey Lapin 
384dfe64e2cSSergey Lapin int mtd_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len);
385dfe64e2cSSergey Lapin int mtd_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len);
386dfe64e2cSSergey Lapin int mtd_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len);
38786a720aaSEzequiel Garcia int mtd_block_isreserved(struct mtd_info *mtd, loff_t ofs);
388dfe64e2cSSergey Lapin int mtd_block_isbad(struct mtd_info *mtd, loff_t ofs);
389dfe64e2cSSergey Lapin int mtd_block_markbad(struct mtd_info *mtd, loff_t ofs);
390dfe64e2cSSergey Lapin 
391ff94bc40SHeiko Schocher #ifndef __UBOOT__
392ff94bc40SHeiko Schocher static inline int mtd_suspend(struct mtd_info *mtd)
393ff94bc40SHeiko Schocher {
394ff94bc40SHeiko Schocher 	return mtd->_suspend ? mtd->_suspend(mtd) : 0;
395ff94bc40SHeiko Schocher }
396ff94bc40SHeiko Schocher 
397ff94bc40SHeiko Schocher static inline void mtd_resume(struct mtd_info *mtd)
398ff94bc40SHeiko Schocher {
399ff94bc40SHeiko Schocher 	if (mtd->_resume)
400ff94bc40SHeiko Schocher 		mtd->_resume(mtd);
401ff94bc40SHeiko Schocher }
402ff94bc40SHeiko Schocher #endif
403ff94bc40SHeiko Schocher 
4048d2effeaSStefan Roese static inline uint32_t mtd_div_by_eb(uint64_t sz, struct mtd_info *mtd)
4058d2effeaSStefan Roese {
406ff94bc40SHeiko Schocher 	if (mtd->erasesize_shift)
407ff94bc40SHeiko Schocher 		return sz >> mtd->erasesize_shift;
4088d2effeaSStefan Roese 	do_div(sz, mtd->erasesize);
4098d2effeaSStefan Roese 	return sz;
4108d2effeaSStefan Roese }
4118d2effeaSStefan Roese 
4128d2effeaSStefan Roese static inline uint32_t mtd_mod_by_eb(uint64_t sz, struct mtd_info *mtd)
4138d2effeaSStefan Roese {
414ff94bc40SHeiko Schocher 	if (mtd->erasesize_shift)
415ff94bc40SHeiko Schocher 		return sz & mtd->erasesize_mask;
4168d2effeaSStefan Roese 	return do_div(sz, mtd->erasesize);
4178d2effeaSStefan Roese }
418932394acSWolfgang Denk 
419ff94bc40SHeiko Schocher static inline uint32_t mtd_div_by_ws(uint64_t sz, struct mtd_info *mtd)
420ff94bc40SHeiko Schocher {
421ff94bc40SHeiko Schocher 	if (mtd->writesize_shift)
422ff94bc40SHeiko Schocher 		return sz >> mtd->writesize_shift;
423ff94bc40SHeiko Schocher 	do_div(sz, mtd->writesize);
424ff94bc40SHeiko Schocher 	return sz;
425ff94bc40SHeiko Schocher }
426ff94bc40SHeiko Schocher 
427ff94bc40SHeiko Schocher static inline uint32_t mtd_mod_by_ws(uint64_t sz, struct mtd_info *mtd)
428ff94bc40SHeiko Schocher {
429ff94bc40SHeiko Schocher 	if (mtd->writesize_shift)
430ff94bc40SHeiko Schocher 		return sz & mtd->writesize_mask;
431ff94bc40SHeiko Schocher 	return do_div(sz, mtd->writesize);
432ff94bc40SHeiko Schocher }
433ff94bc40SHeiko Schocher 
434dfe64e2cSSergey Lapin static inline int mtd_has_oob(const struct mtd_info *mtd)
435dfe64e2cSSergey Lapin {
436dfe64e2cSSergey Lapin 	return mtd->_read_oob && mtd->_write_oob;
437dfe64e2cSSergey Lapin }
438dfe64e2cSSergey Lapin 
439ff94bc40SHeiko Schocher static inline int mtd_type_is_nand(const struct mtd_info *mtd)
440ff94bc40SHeiko Schocher {
441ff94bc40SHeiko Schocher 	return mtd->type == MTD_NANDFLASH || mtd->type == MTD_MLCNANDFLASH;
442ff94bc40SHeiko Schocher }
443ff94bc40SHeiko Schocher 
444dfe64e2cSSergey Lapin static inline int mtd_can_have_bb(const struct mtd_info *mtd)
445dfe64e2cSSergey Lapin {
446dfe64e2cSSergey Lapin 	return !!mtd->_block_isbad;
447dfe64e2cSSergey Lapin }
448dfe64e2cSSergey Lapin 
449932394acSWolfgang Denk 	/* Kernel-side ioctl definitions */
450932394acSWolfgang Denk 
451ff94bc40SHeiko Schocher struct mtd_partition;
452ff94bc40SHeiko Schocher struct mtd_part_parser_data;
453932394acSWolfgang Denk 
454ff94bc40SHeiko Schocher extern int mtd_device_parse_register(struct mtd_info *mtd,
455ff94bc40SHeiko Schocher 				     const char * const *part_probe_types,
456ff94bc40SHeiko Schocher 				     struct mtd_part_parser_data *parser_data,
457ff94bc40SHeiko Schocher 				     const struct mtd_partition *defparts,
458ff94bc40SHeiko Schocher 				     int defnr_parts);
459ff94bc40SHeiko Schocher #define mtd_device_register(master, parts, nr_parts)	\
460ff94bc40SHeiko Schocher 	mtd_device_parse_register(master, NULL, NULL, parts, nr_parts)
461ff94bc40SHeiko Schocher extern int mtd_device_unregister(struct mtd_info *master);
462932394acSWolfgang Denk extern struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num);
463ff94bc40SHeiko Schocher extern int __get_mtd_device(struct mtd_info *mtd);
464ff94bc40SHeiko Schocher extern void __put_mtd_device(struct mtd_info *mtd);
465cfa460adSWilliam Juul extern struct mtd_info *get_mtd_device_nm(const char *name);
466932394acSWolfgang Denk extern void put_mtd_device(struct mtd_info *mtd);
467ff94bc40SHeiko Schocher 
468ff94bc40SHeiko Schocher 
469ff94bc40SHeiko Schocher #ifndef __UBOOT__
470932394acSWolfgang Denk struct mtd_notifier {
471932394acSWolfgang Denk 	void (*add)(struct mtd_info *mtd);
472932394acSWolfgang Denk 	void (*remove)(struct mtd_info *mtd);
473932394acSWolfgang Denk 	struct list_head list;
474932394acSWolfgang Denk };
475932394acSWolfgang Denk 
476ff94bc40SHeiko Schocher 
477932394acSWolfgang Denk extern void register_mtd_user (struct mtd_notifier *new);
478932394acSWolfgang Denk extern int unregister_mtd_user (struct mtd_notifier *old);
479932394acSWolfgang Denk #endif
480ff94bc40SHeiko Schocher void *mtd_kmalloc_up_to(const struct mtd_info *mtd, size_t *size);
481932394acSWolfgang Denk 
482932394acSWolfgang Denk #ifdef CONFIG_MTD_PARTITIONS
483932394acSWolfgang Denk void mtd_erase_callback(struct erase_info *instr);
484932394acSWolfgang Denk #else
485932394acSWolfgang Denk static inline void mtd_erase_callback(struct erase_info *instr)
486932394acSWolfgang Denk {
487932394acSWolfgang Denk 	if (instr->callback)
488932394acSWolfgang Denk 		instr->callback(instr);
489932394acSWolfgang Denk }
490932394acSWolfgang Denk #endif
491932394acSWolfgang Denk 
492ff94bc40SHeiko Schocher #ifdef __UBOOT__
493932394acSWolfgang Denk /*
494932394acSWolfgang Denk  * Debugging macro and defines
495932394acSWolfgang Denk  */
496932394acSWolfgang Denk #define MTD_DEBUG_LEVEL0	(0)	/* Quiet   */
497932394acSWolfgang Denk #define MTD_DEBUG_LEVEL1	(1)	/* Audible */
498932394acSWolfgang Denk #define MTD_DEBUG_LEVEL2	(2)	/* Loud    */
499932394acSWolfgang Denk #define MTD_DEBUG_LEVEL3	(3)	/* Noisy   */
500932394acSWolfgang Denk 
501932394acSWolfgang Denk #ifdef CONFIG_MTD_DEBUG
5023167c538SScott Wood #define MTDDEBUG(n, args...)				\
503932394acSWolfgang Denk 	do {						\
504932394acSWolfgang Denk 		if (n <= CONFIG_MTD_DEBUG_VERBOSE)	\
505932394acSWolfgang Denk 			printk(KERN_INFO args);		\
506932394acSWolfgang Denk 	} while(0)
507932394acSWolfgang Denk #else /* CONFIG_MTD_DEBUG */
508c45912d8SScott Wood #define MTDDEBUG(n, args...)				\
509c45912d8SScott Wood 	do {						\
510c45912d8SScott Wood 		if (0)					\
511c45912d8SScott Wood 			printk(KERN_INFO args);		\
512c45912d8SScott Wood 	} while(0)
513932394acSWolfgang Denk #endif /* CONFIG_MTD_DEBUG */
514ff94bc40SHeiko Schocher #endif
515dfe64e2cSSergey Lapin 
516dfe64e2cSSergey Lapin static inline int mtd_is_bitflip(int err) {
517dfe64e2cSSergey Lapin 	return err == -EUCLEAN;
518dfe64e2cSSergey Lapin }
519dfe64e2cSSergey Lapin 
520dfe64e2cSSergey Lapin static inline int mtd_is_eccerr(int err) {
521dfe64e2cSSergey Lapin 	return err == -EBADMSG;
522dfe64e2cSSergey Lapin }
523dfe64e2cSSergey Lapin 
524dfe64e2cSSergey Lapin static inline int mtd_is_bitflip_or_eccerr(int err) {
525dfe64e2cSSergey Lapin 	return mtd_is_bitflip(err) || mtd_is_eccerr(err);
526dfe64e2cSSergey Lapin }
527932394acSWolfgang Denk 
5280195a7bbSHeiko Schocher unsigned mtd_mmap_capabilities(struct mtd_info *mtd);
5290195a7bbSHeiko Schocher 
530ff94bc40SHeiko Schocher #ifdef __UBOOT__
531ff94bc40SHeiko Schocher /* drivers/mtd/mtdcore.h */
532ff94bc40SHeiko Schocher int add_mtd_device(struct mtd_info *mtd);
533ddf7bcfaSHeiko Schocher int del_mtd_device(struct mtd_info *mtd);
534ff94bc40SHeiko Schocher int add_mtd_partitions(struct mtd_info *, const struct mtd_partition *, int);
535ff94bc40SHeiko Schocher int del_mtd_partitions(struct mtd_info *);
53609c32807SHeiko Schocher 
537ac199d13SMiquel Raynal struct mtd_info *__mtd_next_device(int i);
538ac199d13SMiquel Raynal #define mtd_for_each_device(mtd)			\
539ac199d13SMiquel Raynal 	for ((mtd) = __mtd_next_device(0);		\
540ac199d13SMiquel Raynal 	     (mtd) != NULL;				\
541ac199d13SMiquel Raynal 	     (mtd) = __mtd_next_device(mtd->index + 1))
542ac199d13SMiquel Raynal 
54309c32807SHeiko Schocher int mtd_arg_off(const char *arg, int *idx, loff_t *off, loff_t *size,
544f18d1116SMasahiro Yamada 		loff_t *maxsize, int devtype, uint64_t chipsize);
54509c32807SHeiko Schocher int mtd_arg_off_size(int argc, char *const argv[], int *idx, loff_t *off,
546f18d1116SMasahiro Yamada 		     loff_t *size, loff_t *maxsize, int devtype,
547f18d1116SMasahiro Yamada 		     uint64_t chipsize);
54859441ac3SSteve Rae 
54959441ac3SSteve Rae /* drivers/mtd/mtdcore.c */
55059441ac3SSteve Rae void mtd_get_len_incl_bad(struct mtd_info *mtd, uint64_t offset,
55159441ac3SSteve Rae 			  const uint64_t length, uint64_t *len_incl_bad,
55259441ac3SSteve Rae 			  int *truncated);
553*50466819SMiquel Raynal 
554*50466819SMiquel Raynal /* drivers/mtd/mtd_uboot.c */
555*50466819SMiquel Raynal int mtd_search_alternate_name(const char *mtdname, char *altname,
556*50466819SMiquel Raynal 			      unsigned int max_len);
557*50466819SMiquel Raynal 
558ff94bc40SHeiko Schocher #endif
559932394acSWolfgang Denk #endif /* __MTD_MTD_H__ */
560