xref: /rk3399_rockchip-uboot/include/linux/mtd/nand.h (revision ed99f7731a5a40a9638c4b4e603f3caebef05913)
1*ed99f773SBoris Brezillon /* SPDX-License-Identifier: GPL-2.0 */
2*ed99f773SBoris Brezillon /*
3*ed99f773SBoris Brezillon  *  Copyright 2017 - Free Electrons
4*ed99f773SBoris Brezillon  *
5*ed99f773SBoris Brezillon  *  Authors:
6*ed99f773SBoris Brezillon  *	Boris Brezillon <boris.brezillon@free-electrons.com>
7*ed99f773SBoris Brezillon  *	Peter Pan <peterpandong@micron.com>
8*ed99f773SBoris Brezillon  */
9*ed99f773SBoris Brezillon 
10*ed99f773SBoris Brezillon #ifndef __LINUX_MTD_NAND_H
11*ed99f773SBoris Brezillon #define __LINUX_MTD_NAND_H
12*ed99f773SBoris Brezillon 
13*ed99f773SBoris Brezillon #include <linux/mtd/mtd.h>
14*ed99f773SBoris Brezillon 
15*ed99f773SBoris Brezillon /**
16*ed99f773SBoris Brezillon  * struct nand_memory_organization - Memory organization structure
17*ed99f773SBoris Brezillon  * @bits_per_cell: number of bits per NAND cell
18*ed99f773SBoris Brezillon  * @pagesize: page size
19*ed99f773SBoris Brezillon  * @oobsize: OOB area size
20*ed99f773SBoris Brezillon  * @pages_per_eraseblock: number of pages per eraseblock
21*ed99f773SBoris Brezillon  * @eraseblocks_per_lun: number of eraseblocks per LUN (Logical Unit Number)
22*ed99f773SBoris Brezillon  * @planes_per_lun: number of planes per LUN
23*ed99f773SBoris Brezillon  * @luns_per_target: number of LUN per target (target is a synonym for die)
24*ed99f773SBoris Brezillon  * @ntargets: total number of targets exposed by the NAND device
25*ed99f773SBoris Brezillon  */
26*ed99f773SBoris Brezillon struct nand_memory_organization {
27*ed99f773SBoris Brezillon 	unsigned int bits_per_cell;
28*ed99f773SBoris Brezillon 	unsigned int pagesize;
29*ed99f773SBoris Brezillon 	unsigned int oobsize;
30*ed99f773SBoris Brezillon 	unsigned int pages_per_eraseblock;
31*ed99f773SBoris Brezillon 	unsigned int eraseblocks_per_lun;
32*ed99f773SBoris Brezillon 	unsigned int planes_per_lun;
33*ed99f773SBoris Brezillon 	unsigned int luns_per_target;
34*ed99f773SBoris Brezillon 	unsigned int ntargets;
35*ed99f773SBoris Brezillon };
36*ed99f773SBoris Brezillon 
37*ed99f773SBoris Brezillon #define NAND_MEMORG(bpc, ps, os, ppe, epl, ppl, lpt, nt)	\
38*ed99f773SBoris Brezillon 	{							\
39*ed99f773SBoris Brezillon 		.bits_per_cell = (bpc),				\
40*ed99f773SBoris Brezillon 		.pagesize = (ps),				\
41*ed99f773SBoris Brezillon 		.oobsize = (os),				\
42*ed99f773SBoris Brezillon 		.pages_per_eraseblock = (ppe),			\
43*ed99f773SBoris Brezillon 		.eraseblocks_per_lun = (epl),			\
44*ed99f773SBoris Brezillon 		.planes_per_lun = (ppl),			\
45*ed99f773SBoris Brezillon 		.luns_per_target = (lpt),			\
46*ed99f773SBoris Brezillon 		.ntargets = (nt),				\
47*ed99f773SBoris Brezillon 	}
48*ed99f773SBoris Brezillon 
49*ed99f773SBoris Brezillon /**
50*ed99f773SBoris Brezillon  * struct nand_row_converter - Information needed to convert an absolute offset
51*ed99f773SBoris Brezillon  *			       into a row address
52*ed99f773SBoris Brezillon  * @lun_addr_shift: position of the LUN identifier in the row address
53*ed99f773SBoris Brezillon  * @eraseblock_addr_shift: position of the eraseblock identifier in the row
54*ed99f773SBoris Brezillon  *			   address
55*ed99f773SBoris Brezillon  */
56*ed99f773SBoris Brezillon struct nand_row_converter {
57*ed99f773SBoris Brezillon 	unsigned int lun_addr_shift;
58*ed99f773SBoris Brezillon 	unsigned int eraseblock_addr_shift;
59*ed99f773SBoris Brezillon };
60*ed99f773SBoris Brezillon 
61*ed99f773SBoris Brezillon /**
62*ed99f773SBoris Brezillon  * struct nand_pos - NAND position object
63*ed99f773SBoris Brezillon  * @target: the NAND target/die
64*ed99f773SBoris Brezillon  * @lun: the LUN identifier
65*ed99f773SBoris Brezillon  * @plane: the plane within the LUN
66*ed99f773SBoris Brezillon  * @eraseblock: the eraseblock within the LUN
67*ed99f773SBoris Brezillon  * @page: the page within the LUN
68*ed99f773SBoris Brezillon  *
69*ed99f773SBoris Brezillon  * These information are usually used by specific sub-layers to select the
70*ed99f773SBoris Brezillon  * appropriate target/die and generate a row address to pass to the device.
71*ed99f773SBoris Brezillon  */
72*ed99f773SBoris Brezillon struct nand_pos {
73*ed99f773SBoris Brezillon 	unsigned int target;
74*ed99f773SBoris Brezillon 	unsigned int lun;
75*ed99f773SBoris Brezillon 	unsigned int plane;
76*ed99f773SBoris Brezillon 	unsigned int eraseblock;
77*ed99f773SBoris Brezillon 	unsigned int page;
78*ed99f773SBoris Brezillon };
79*ed99f773SBoris Brezillon 
80*ed99f773SBoris Brezillon /**
81*ed99f773SBoris Brezillon  * struct nand_page_io_req - NAND I/O request object
82*ed99f773SBoris Brezillon  * @pos: the position this I/O request is targeting
83*ed99f773SBoris Brezillon  * @dataoffs: the offset within the page
84*ed99f773SBoris Brezillon  * @datalen: number of data bytes to read from/write to this page
85*ed99f773SBoris Brezillon  * @databuf: buffer to store data in or get data from
86*ed99f773SBoris Brezillon  * @ooboffs: the OOB offset within the page
87*ed99f773SBoris Brezillon  * @ooblen: the number of OOB bytes to read from/write to this page
88*ed99f773SBoris Brezillon  * @oobbuf: buffer to store OOB data in or get OOB data from
89*ed99f773SBoris Brezillon  *
90*ed99f773SBoris Brezillon  * This object is used to pass per-page I/O requests to NAND sub-layers. This
91*ed99f773SBoris Brezillon  * way all useful information are already formatted in a useful way and
92*ed99f773SBoris Brezillon  * specific NAND layers can focus on translating these information into
93*ed99f773SBoris Brezillon  * specific commands/operations.
94*ed99f773SBoris Brezillon  */
95*ed99f773SBoris Brezillon struct nand_page_io_req {
96*ed99f773SBoris Brezillon 	struct nand_pos pos;
97*ed99f773SBoris Brezillon 	unsigned int dataoffs;
98*ed99f773SBoris Brezillon 	unsigned int datalen;
99*ed99f773SBoris Brezillon 	union {
100*ed99f773SBoris Brezillon 		const void *out;
101*ed99f773SBoris Brezillon 		void *in;
102*ed99f773SBoris Brezillon 	} databuf;
103*ed99f773SBoris Brezillon 	unsigned int ooboffs;
104*ed99f773SBoris Brezillon 	unsigned int ooblen;
105*ed99f773SBoris Brezillon 	union {
106*ed99f773SBoris Brezillon 		const void *out;
107*ed99f773SBoris Brezillon 		void *in;
108*ed99f773SBoris Brezillon 	} oobbuf;
109*ed99f773SBoris Brezillon };
110*ed99f773SBoris Brezillon 
111*ed99f773SBoris Brezillon /**
112*ed99f773SBoris Brezillon  * struct nand_ecc_req - NAND ECC requirements
113*ed99f773SBoris Brezillon  * @strength: ECC strength
114*ed99f773SBoris Brezillon  * @step_size: ECC step/block size
115*ed99f773SBoris Brezillon  */
116*ed99f773SBoris Brezillon struct nand_ecc_req {
117*ed99f773SBoris Brezillon 	unsigned int strength;
118*ed99f773SBoris Brezillon 	unsigned int step_size;
119*ed99f773SBoris Brezillon };
120*ed99f773SBoris Brezillon 
121*ed99f773SBoris Brezillon #define NAND_ECCREQ(str, stp) { .strength = (str), .step_size = (stp) }
122*ed99f773SBoris Brezillon 
123*ed99f773SBoris Brezillon /**
124*ed99f773SBoris Brezillon  * struct nand_bbt - bad block table object
125*ed99f773SBoris Brezillon  * @cache: in memory BBT cache
126*ed99f773SBoris Brezillon  */
127*ed99f773SBoris Brezillon struct nand_bbt {
128*ed99f773SBoris Brezillon 	unsigned long *cache;
129*ed99f773SBoris Brezillon };
130*ed99f773SBoris Brezillon 
131*ed99f773SBoris Brezillon struct nand_device;
132*ed99f773SBoris Brezillon 
133*ed99f773SBoris Brezillon /**
134*ed99f773SBoris Brezillon  * struct nand_ops - NAND operations
135*ed99f773SBoris Brezillon  * @erase: erase a specific block. No need to check if the block is bad before
136*ed99f773SBoris Brezillon  *	   erasing, this has been taken care of by the generic NAND layer
137*ed99f773SBoris Brezillon  * @markbad: mark a specific block bad. No need to check if the block is
138*ed99f773SBoris Brezillon  *	     already marked bad, this has been taken care of by the generic
139*ed99f773SBoris Brezillon  *	     NAND layer. This method should just write the BBM (Bad Block
140*ed99f773SBoris Brezillon  *	     Marker) so that future call to struct_nand_ops->isbad() return
141*ed99f773SBoris Brezillon  *	     true
142*ed99f773SBoris Brezillon  * @isbad: check whether a block is bad or not. This method should just read
143*ed99f773SBoris Brezillon  *	   the BBM and return whether the block is bad or not based on what it
144*ed99f773SBoris Brezillon  *	   reads
145*ed99f773SBoris Brezillon  *
146*ed99f773SBoris Brezillon  * These are all low level operations that should be implemented by specialized
147*ed99f773SBoris Brezillon  * NAND layers (SPI NAND, raw NAND, ...).
148*ed99f773SBoris Brezillon  */
149*ed99f773SBoris Brezillon struct nand_ops {
150*ed99f773SBoris Brezillon 	int (*erase)(struct nand_device *nand, const struct nand_pos *pos);
151*ed99f773SBoris Brezillon 	int (*markbad)(struct nand_device *nand, const struct nand_pos *pos);
152*ed99f773SBoris Brezillon 	bool (*isbad)(struct nand_device *nand, const struct nand_pos *pos);
153*ed99f773SBoris Brezillon };
154*ed99f773SBoris Brezillon 
155*ed99f773SBoris Brezillon /**
156*ed99f773SBoris Brezillon  * struct nand_device - NAND device
157*ed99f773SBoris Brezillon  * @mtd: MTD instance attached to the NAND device
158*ed99f773SBoris Brezillon  * @memorg: memory layout
159*ed99f773SBoris Brezillon  * @eccreq: ECC requirements
160*ed99f773SBoris Brezillon  * @rowconv: position to row address converter
161*ed99f773SBoris Brezillon  * @bbt: bad block table info
162*ed99f773SBoris Brezillon  * @ops: NAND operations attached to the NAND device
163*ed99f773SBoris Brezillon  *
164*ed99f773SBoris Brezillon  * Generic NAND object. Specialized NAND layers (raw NAND, SPI NAND, OneNAND)
165*ed99f773SBoris Brezillon  * should declare their own NAND object embedding a nand_device struct (that's
166*ed99f773SBoris Brezillon  * how inheritance is done).
167*ed99f773SBoris Brezillon  * struct_nand_device->memorg and struct_nand_device->eccreq should be filled
168*ed99f773SBoris Brezillon  * at device detection time to reflect the NAND device
169*ed99f773SBoris Brezillon  * capabilities/requirements. Once this is done nanddev_init() can be called.
170*ed99f773SBoris Brezillon  * It will take care of converting NAND information into MTD ones, which means
171*ed99f773SBoris Brezillon  * the specialized NAND layers should never manually tweak
172*ed99f773SBoris Brezillon  * struct_nand_device->mtd except for the ->_read/write() hooks.
173*ed99f773SBoris Brezillon  */
174*ed99f773SBoris Brezillon struct nand_device {
175*ed99f773SBoris Brezillon 	struct mtd_info *mtd;
176*ed99f773SBoris Brezillon 	struct nand_memory_organization memorg;
177*ed99f773SBoris Brezillon 	struct nand_ecc_req eccreq;
178*ed99f773SBoris Brezillon 	struct nand_row_converter rowconv;
179*ed99f773SBoris Brezillon 	struct nand_bbt bbt;
180*ed99f773SBoris Brezillon 	const struct nand_ops *ops;
181*ed99f773SBoris Brezillon };
182*ed99f773SBoris Brezillon 
183*ed99f773SBoris Brezillon /**
184*ed99f773SBoris Brezillon  * struct nand_io_iter - NAND I/O iterator
185*ed99f773SBoris Brezillon  * @req: current I/O request
186*ed99f773SBoris Brezillon  * @oobbytes_per_page: maximum number of OOB bytes per page
187*ed99f773SBoris Brezillon  * @dataleft: remaining number of data bytes to read/write
188*ed99f773SBoris Brezillon  * @oobleft: remaining number of OOB bytes to read/write
189*ed99f773SBoris Brezillon  *
190*ed99f773SBoris Brezillon  * Can be used by specialized NAND layers to iterate over all pages covered
191*ed99f773SBoris Brezillon  * by an MTD I/O request, which should greatly simplifies the boiler-plate
192*ed99f773SBoris Brezillon  * code needed to read/write data from/to a NAND device.
193*ed99f773SBoris Brezillon  */
194*ed99f773SBoris Brezillon struct nand_io_iter {
195*ed99f773SBoris Brezillon 	struct nand_page_io_req req;
196*ed99f773SBoris Brezillon 	unsigned int oobbytes_per_page;
197*ed99f773SBoris Brezillon 	unsigned int dataleft;
198*ed99f773SBoris Brezillon 	unsigned int oobleft;
199*ed99f773SBoris Brezillon };
200*ed99f773SBoris Brezillon 
201*ed99f773SBoris Brezillon /**
202*ed99f773SBoris Brezillon  * mtd_to_nanddev() - Get the NAND device attached to the MTD instance
203*ed99f773SBoris Brezillon  * @mtd: MTD instance
204*ed99f773SBoris Brezillon  *
205*ed99f773SBoris Brezillon  * Return: the NAND device embedding @mtd.
206*ed99f773SBoris Brezillon  */
207*ed99f773SBoris Brezillon static inline struct nand_device *mtd_to_nanddev(struct mtd_info *mtd)
208*ed99f773SBoris Brezillon {
209*ed99f773SBoris Brezillon 	return mtd->priv;
210*ed99f773SBoris Brezillon }
211*ed99f773SBoris Brezillon 
212*ed99f773SBoris Brezillon /**
213*ed99f773SBoris Brezillon  * nanddev_to_mtd() - Get the MTD device attached to a NAND device
214*ed99f773SBoris Brezillon  * @nand: NAND device
215*ed99f773SBoris Brezillon  *
216*ed99f773SBoris Brezillon  * Return: the MTD device embedded in @nand.
217*ed99f773SBoris Brezillon  */
218*ed99f773SBoris Brezillon static inline struct mtd_info *nanddev_to_mtd(struct nand_device *nand)
219*ed99f773SBoris Brezillon {
220*ed99f773SBoris Brezillon 	return nand->mtd;
221*ed99f773SBoris Brezillon }
222*ed99f773SBoris Brezillon 
223*ed99f773SBoris Brezillon /*
224*ed99f773SBoris Brezillon  * nanddev_bits_per_cell() - Get the number of bits per cell
225*ed99f773SBoris Brezillon  * @nand: NAND device
226*ed99f773SBoris Brezillon  *
227*ed99f773SBoris Brezillon  * Return: the number of bits per cell.
228*ed99f773SBoris Brezillon  */
229*ed99f773SBoris Brezillon static inline unsigned int nanddev_bits_per_cell(const struct nand_device *nand)
230*ed99f773SBoris Brezillon {
231*ed99f773SBoris Brezillon 	return nand->memorg.bits_per_cell;
232*ed99f773SBoris Brezillon }
233*ed99f773SBoris Brezillon 
234*ed99f773SBoris Brezillon /**
235*ed99f773SBoris Brezillon  * nanddev_page_size() - Get NAND page size
236*ed99f773SBoris Brezillon  * @nand: NAND device
237*ed99f773SBoris Brezillon  *
238*ed99f773SBoris Brezillon  * Return: the page size.
239*ed99f773SBoris Brezillon  */
240*ed99f773SBoris Brezillon static inline size_t nanddev_page_size(const struct nand_device *nand)
241*ed99f773SBoris Brezillon {
242*ed99f773SBoris Brezillon 	return nand->memorg.pagesize;
243*ed99f773SBoris Brezillon }
244*ed99f773SBoris Brezillon 
245*ed99f773SBoris Brezillon /**
246*ed99f773SBoris Brezillon  * nanddev_per_page_oobsize() - Get NAND OOB size
247*ed99f773SBoris Brezillon  * @nand: NAND device
248*ed99f773SBoris Brezillon  *
249*ed99f773SBoris Brezillon  * Return: the OOB size.
250*ed99f773SBoris Brezillon  */
251*ed99f773SBoris Brezillon static inline unsigned int
252*ed99f773SBoris Brezillon nanddev_per_page_oobsize(const struct nand_device *nand)
253*ed99f773SBoris Brezillon {
254*ed99f773SBoris Brezillon 	return nand->memorg.oobsize;
255*ed99f773SBoris Brezillon }
256*ed99f773SBoris Brezillon 
257*ed99f773SBoris Brezillon /**
258*ed99f773SBoris Brezillon  * nanddev_pages_per_eraseblock() - Get the number of pages per eraseblock
259*ed99f773SBoris Brezillon  * @nand: NAND device
260*ed99f773SBoris Brezillon  *
261*ed99f773SBoris Brezillon  * Return: the number of pages per eraseblock.
262*ed99f773SBoris Brezillon  */
263*ed99f773SBoris Brezillon static inline unsigned int
264*ed99f773SBoris Brezillon nanddev_pages_per_eraseblock(const struct nand_device *nand)
265*ed99f773SBoris Brezillon {
266*ed99f773SBoris Brezillon 	return nand->memorg.pages_per_eraseblock;
267*ed99f773SBoris Brezillon }
268*ed99f773SBoris Brezillon 
269*ed99f773SBoris Brezillon /**
270*ed99f773SBoris Brezillon  * nanddev_per_page_oobsize() - Get NAND erase block size
271*ed99f773SBoris Brezillon  * @nand: NAND device
272*ed99f773SBoris Brezillon  *
273*ed99f773SBoris Brezillon  * Return: the eraseblock size.
274*ed99f773SBoris Brezillon  */
275*ed99f773SBoris Brezillon static inline size_t nanddev_eraseblock_size(const struct nand_device *nand)
276*ed99f773SBoris Brezillon {
277*ed99f773SBoris Brezillon 	return nand->memorg.pagesize * nand->memorg.pages_per_eraseblock;
278*ed99f773SBoris Brezillon }
279*ed99f773SBoris Brezillon 
280*ed99f773SBoris Brezillon /**
281*ed99f773SBoris Brezillon  * nanddev_eraseblocks_per_lun() - Get the number of eraseblocks per LUN
282*ed99f773SBoris Brezillon  * @nand: NAND device
283*ed99f773SBoris Brezillon  *
284*ed99f773SBoris Brezillon  * Return: the number of eraseblocks per LUN.
285*ed99f773SBoris Brezillon  */
286*ed99f773SBoris Brezillon static inline unsigned int
287*ed99f773SBoris Brezillon nanddev_eraseblocks_per_lun(const struct nand_device *nand)
288*ed99f773SBoris Brezillon {
289*ed99f773SBoris Brezillon 	return nand->memorg.eraseblocks_per_lun;
290*ed99f773SBoris Brezillon }
291*ed99f773SBoris Brezillon 
292*ed99f773SBoris Brezillon /**
293*ed99f773SBoris Brezillon  * nanddev_target_size() - Get the total size provided by a single target/die
294*ed99f773SBoris Brezillon  * @nand: NAND device
295*ed99f773SBoris Brezillon  *
296*ed99f773SBoris Brezillon  * Return: the total size exposed by a single target/die in bytes.
297*ed99f773SBoris Brezillon  */
298*ed99f773SBoris Brezillon static inline u64 nanddev_target_size(const struct nand_device *nand)
299*ed99f773SBoris Brezillon {
300*ed99f773SBoris Brezillon 	return (u64)nand->memorg.luns_per_target *
301*ed99f773SBoris Brezillon 	       nand->memorg.eraseblocks_per_lun *
302*ed99f773SBoris Brezillon 	       nand->memorg.pages_per_eraseblock *
303*ed99f773SBoris Brezillon 	       nand->memorg.pagesize;
304*ed99f773SBoris Brezillon }
305*ed99f773SBoris Brezillon 
306*ed99f773SBoris Brezillon /**
307*ed99f773SBoris Brezillon  * nanddev_ntarget() - Get the total of targets
308*ed99f773SBoris Brezillon  * @nand: NAND device
309*ed99f773SBoris Brezillon  *
310*ed99f773SBoris Brezillon  * Return: the number of targets/dies exposed by @nand.
311*ed99f773SBoris Brezillon  */
312*ed99f773SBoris Brezillon static inline unsigned int nanddev_ntargets(const struct nand_device *nand)
313*ed99f773SBoris Brezillon {
314*ed99f773SBoris Brezillon 	return nand->memorg.ntargets;
315*ed99f773SBoris Brezillon }
316*ed99f773SBoris Brezillon 
317*ed99f773SBoris Brezillon /**
318*ed99f773SBoris Brezillon  * nanddev_neraseblocks() - Get the total number of erasablocks
319*ed99f773SBoris Brezillon  * @nand: NAND device
320*ed99f773SBoris Brezillon  *
321*ed99f773SBoris Brezillon  * Return: the total number of eraseblocks exposed by @nand.
322*ed99f773SBoris Brezillon  */
323*ed99f773SBoris Brezillon static inline unsigned int nanddev_neraseblocks(const struct nand_device *nand)
324*ed99f773SBoris Brezillon {
325*ed99f773SBoris Brezillon 	return (u64)nand->memorg.luns_per_target *
326*ed99f773SBoris Brezillon 	       nand->memorg.eraseblocks_per_lun *
327*ed99f773SBoris Brezillon 	       nand->memorg.pages_per_eraseblock;
328*ed99f773SBoris Brezillon }
329*ed99f773SBoris Brezillon 
330*ed99f773SBoris Brezillon /**
331*ed99f773SBoris Brezillon  * nanddev_size() - Get NAND size
332*ed99f773SBoris Brezillon  * @nand: NAND device
333*ed99f773SBoris Brezillon  *
334*ed99f773SBoris Brezillon  * Return: the total size (in bytes) exposed by @nand.
335*ed99f773SBoris Brezillon  */
336*ed99f773SBoris Brezillon static inline u64 nanddev_size(const struct nand_device *nand)
337*ed99f773SBoris Brezillon {
338*ed99f773SBoris Brezillon 	return nanddev_target_size(nand) * nanddev_ntargets(nand);
339*ed99f773SBoris Brezillon }
340*ed99f773SBoris Brezillon 
341*ed99f773SBoris Brezillon /**
342*ed99f773SBoris Brezillon  * nanddev_get_memorg() - Extract memory organization info from a NAND device
343*ed99f773SBoris Brezillon  * @nand: NAND device
344*ed99f773SBoris Brezillon  *
345*ed99f773SBoris Brezillon  * This can be used by the upper layer to fill the memorg info before calling
346*ed99f773SBoris Brezillon  * nanddev_init().
347*ed99f773SBoris Brezillon  *
348*ed99f773SBoris Brezillon  * Return: the memorg object embedded in the NAND device.
349*ed99f773SBoris Brezillon  */
350*ed99f773SBoris Brezillon static inline struct nand_memory_organization *
351*ed99f773SBoris Brezillon nanddev_get_memorg(struct nand_device *nand)
352*ed99f773SBoris Brezillon {
353*ed99f773SBoris Brezillon 	return &nand->memorg;
354*ed99f773SBoris Brezillon }
355*ed99f773SBoris Brezillon 
356*ed99f773SBoris Brezillon int nanddev_init(struct nand_device *nand, const struct nand_ops *ops,
357*ed99f773SBoris Brezillon 		 struct module *owner);
358*ed99f773SBoris Brezillon void nanddev_cleanup(struct nand_device *nand);
359*ed99f773SBoris Brezillon 
360*ed99f773SBoris Brezillon /**
361*ed99f773SBoris Brezillon  * nanddev_register() - Register a NAND device
362*ed99f773SBoris Brezillon  * @nand: NAND device
363*ed99f773SBoris Brezillon  *
364*ed99f773SBoris Brezillon  * Register a NAND device.
365*ed99f773SBoris Brezillon  * This function is just a wrapper around mtd_device_register()
366*ed99f773SBoris Brezillon  * registering the MTD device embedded in @nand.
367*ed99f773SBoris Brezillon  *
368*ed99f773SBoris Brezillon  * Return: 0 in case of success, a negative error code otherwise.
369*ed99f773SBoris Brezillon  */
370*ed99f773SBoris Brezillon static inline int nanddev_register(struct nand_device *nand)
371*ed99f773SBoris Brezillon {
372*ed99f773SBoris Brezillon 	return mtd_device_register(nand->mtd, NULL, 0);
373*ed99f773SBoris Brezillon }
374*ed99f773SBoris Brezillon 
375*ed99f773SBoris Brezillon /**
376*ed99f773SBoris Brezillon  * nanddev_unregister() - Unregister a NAND device
377*ed99f773SBoris Brezillon  * @nand: NAND device
378*ed99f773SBoris Brezillon  *
379*ed99f773SBoris Brezillon  * Unregister a NAND device.
380*ed99f773SBoris Brezillon  * This function is just a wrapper around mtd_device_unregister()
381*ed99f773SBoris Brezillon  * unregistering the MTD device embedded in @nand.
382*ed99f773SBoris Brezillon  *
383*ed99f773SBoris Brezillon  * Return: 0 in case of success, a negative error code otherwise.
384*ed99f773SBoris Brezillon  */
385*ed99f773SBoris Brezillon static inline int nanddev_unregister(struct nand_device *nand)
386*ed99f773SBoris Brezillon {
387*ed99f773SBoris Brezillon 	return mtd_device_unregister(nand->mtd);
388*ed99f773SBoris Brezillon }
389*ed99f773SBoris Brezillon 
390*ed99f773SBoris Brezillon /**
391*ed99f773SBoris Brezillon  * nanddev_set_of_node() - Attach a DT node to a NAND device
392*ed99f773SBoris Brezillon  * @nand: NAND device
393*ed99f773SBoris Brezillon  * @np: DT node
394*ed99f773SBoris Brezillon  *
395*ed99f773SBoris Brezillon  * Attach a DT node to a NAND device.
396*ed99f773SBoris Brezillon  */
397*ed99f773SBoris Brezillon static inline void nanddev_set_of_node(struct nand_device *nand,
398*ed99f773SBoris Brezillon 				       const struct device_node *np)
399*ed99f773SBoris Brezillon {
400*ed99f773SBoris Brezillon 	mtd_set_of_node(nand->mtd, np);
401*ed99f773SBoris Brezillon }
402*ed99f773SBoris Brezillon 
403*ed99f773SBoris Brezillon /**
404*ed99f773SBoris Brezillon  * nanddev_get_of_node() - Retrieve the DT node attached to a NAND device
405*ed99f773SBoris Brezillon  * @nand: NAND device
406*ed99f773SBoris Brezillon  *
407*ed99f773SBoris Brezillon  * Return: the DT node attached to @nand.
408*ed99f773SBoris Brezillon  */
409*ed99f773SBoris Brezillon static inline const struct device_node *nanddev_get_of_node(struct nand_device *nand)
410*ed99f773SBoris Brezillon {
411*ed99f773SBoris Brezillon 	return mtd_get_of_node(nand->mtd);
412*ed99f773SBoris Brezillon }
413*ed99f773SBoris Brezillon 
414*ed99f773SBoris Brezillon /**
415*ed99f773SBoris Brezillon  * nanddev_offs_to_pos() - Convert an absolute NAND offset into a NAND position
416*ed99f773SBoris Brezillon  * @nand: NAND device
417*ed99f773SBoris Brezillon  * @offs: absolute NAND offset (usually passed by the MTD layer)
418*ed99f773SBoris Brezillon  * @pos: a NAND position object to fill in
419*ed99f773SBoris Brezillon  *
420*ed99f773SBoris Brezillon  * Converts @offs into a nand_pos representation.
421*ed99f773SBoris Brezillon  *
422*ed99f773SBoris Brezillon  * Return: the offset within the NAND page pointed by @pos.
423*ed99f773SBoris Brezillon  */
424*ed99f773SBoris Brezillon static inline unsigned int nanddev_offs_to_pos(struct nand_device *nand,
425*ed99f773SBoris Brezillon 					       loff_t offs,
426*ed99f773SBoris Brezillon 					       struct nand_pos *pos)
427*ed99f773SBoris Brezillon {
428*ed99f773SBoris Brezillon 	unsigned int pageoffs;
429*ed99f773SBoris Brezillon 	u64 tmp = offs;
430*ed99f773SBoris Brezillon 
431*ed99f773SBoris Brezillon 	pageoffs = do_div(tmp, nand->memorg.pagesize);
432*ed99f773SBoris Brezillon 	pos->page = do_div(tmp, nand->memorg.pages_per_eraseblock);
433*ed99f773SBoris Brezillon 	pos->eraseblock = do_div(tmp, nand->memorg.eraseblocks_per_lun);
434*ed99f773SBoris Brezillon 	pos->plane = pos->eraseblock % nand->memorg.planes_per_lun;
435*ed99f773SBoris Brezillon 	pos->lun = do_div(tmp, nand->memorg.luns_per_target);
436*ed99f773SBoris Brezillon 	pos->target = tmp;
437*ed99f773SBoris Brezillon 
438*ed99f773SBoris Brezillon 	return pageoffs;
439*ed99f773SBoris Brezillon }
440*ed99f773SBoris Brezillon 
441*ed99f773SBoris Brezillon /**
442*ed99f773SBoris Brezillon  * nanddev_pos_cmp() - Compare two NAND positions
443*ed99f773SBoris Brezillon  * @a: First NAND position
444*ed99f773SBoris Brezillon  * @b: Second NAND position
445*ed99f773SBoris Brezillon  *
446*ed99f773SBoris Brezillon  * Compares two NAND positions.
447*ed99f773SBoris Brezillon  *
448*ed99f773SBoris Brezillon  * Return: -1 if @a < @b, 0 if @a == @b and 1 if @a > @b.
449*ed99f773SBoris Brezillon  */
450*ed99f773SBoris Brezillon static inline int nanddev_pos_cmp(const struct nand_pos *a,
451*ed99f773SBoris Brezillon 				  const struct nand_pos *b)
452*ed99f773SBoris Brezillon {
453*ed99f773SBoris Brezillon 	if (a->target != b->target)
454*ed99f773SBoris Brezillon 		return a->target < b->target ? -1 : 1;
455*ed99f773SBoris Brezillon 
456*ed99f773SBoris Brezillon 	if (a->lun != b->lun)
457*ed99f773SBoris Brezillon 		return a->lun < b->lun ? -1 : 1;
458*ed99f773SBoris Brezillon 
459*ed99f773SBoris Brezillon 	if (a->eraseblock != b->eraseblock)
460*ed99f773SBoris Brezillon 		return a->eraseblock < b->eraseblock ? -1 : 1;
461*ed99f773SBoris Brezillon 
462*ed99f773SBoris Brezillon 	if (a->page != b->page)
463*ed99f773SBoris Brezillon 		return a->page < b->page ? -1 : 1;
464*ed99f773SBoris Brezillon 
465*ed99f773SBoris Brezillon 	return 0;
466*ed99f773SBoris Brezillon }
467*ed99f773SBoris Brezillon 
468*ed99f773SBoris Brezillon /**
469*ed99f773SBoris Brezillon  * nanddev_pos_to_offs() - Convert a NAND position into an absolute offset
470*ed99f773SBoris Brezillon  * @nand: NAND device
471*ed99f773SBoris Brezillon  * @pos: the NAND position to convert
472*ed99f773SBoris Brezillon  *
473*ed99f773SBoris Brezillon  * Converts @pos NAND position into an absolute offset.
474*ed99f773SBoris Brezillon  *
475*ed99f773SBoris Brezillon  * Return: the absolute offset. Note that @pos points to the beginning of a
476*ed99f773SBoris Brezillon  *	   page, if one wants to point to a specific offset within this page
477*ed99f773SBoris Brezillon  *	   the returned offset has to be adjusted manually.
478*ed99f773SBoris Brezillon  */
479*ed99f773SBoris Brezillon static inline loff_t nanddev_pos_to_offs(struct nand_device *nand,
480*ed99f773SBoris Brezillon 					 const struct nand_pos *pos)
481*ed99f773SBoris Brezillon {
482*ed99f773SBoris Brezillon 	unsigned int npages;
483*ed99f773SBoris Brezillon 
484*ed99f773SBoris Brezillon 	npages = pos->page +
485*ed99f773SBoris Brezillon 		 ((pos->eraseblock +
486*ed99f773SBoris Brezillon 		   (pos->lun +
487*ed99f773SBoris Brezillon 		    (pos->target * nand->memorg.luns_per_target)) *
488*ed99f773SBoris Brezillon 		   nand->memorg.eraseblocks_per_lun) *
489*ed99f773SBoris Brezillon 		  nand->memorg.pages_per_eraseblock);
490*ed99f773SBoris Brezillon 
491*ed99f773SBoris Brezillon 	return (loff_t)npages * nand->memorg.pagesize;
492*ed99f773SBoris Brezillon }
493*ed99f773SBoris Brezillon 
494*ed99f773SBoris Brezillon /**
495*ed99f773SBoris Brezillon  * nanddev_pos_to_row() - Extract a row address from a NAND position
496*ed99f773SBoris Brezillon  * @nand: NAND device
497*ed99f773SBoris Brezillon  * @pos: the position to convert
498*ed99f773SBoris Brezillon  *
499*ed99f773SBoris Brezillon  * Converts a NAND position into a row address that can then be passed to the
500*ed99f773SBoris Brezillon  * device.
501*ed99f773SBoris Brezillon  *
502*ed99f773SBoris Brezillon  * Return: the row address extracted from @pos.
503*ed99f773SBoris Brezillon  */
504*ed99f773SBoris Brezillon static inline unsigned int nanddev_pos_to_row(struct nand_device *nand,
505*ed99f773SBoris Brezillon 					      const struct nand_pos *pos)
506*ed99f773SBoris Brezillon {
507*ed99f773SBoris Brezillon 	return (pos->lun << nand->rowconv.lun_addr_shift) |
508*ed99f773SBoris Brezillon 	       (pos->eraseblock << nand->rowconv.eraseblock_addr_shift) |
509*ed99f773SBoris Brezillon 	       pos->page;
510*ed99f773SBoris Brezillon }
511*ed99f773SBoris Brezillon 
512*ed99f773SBoris Brezillon /**
513*ed99f773SBoris Brezillon  * nanddev_pos_next_target() - Move a position to the next target/die
514*ed99f773SBoris Brezillon  * @nand: NAND device
515*ed99f773SBoris Brezillon  * @pos: the position to update
516*ed99f773SBoris Brezillon  *
517*ed99f773SBoris Brezillon  * Updates @pos to point to the start of the next target/die. Useful when you
518*ed99f773SBoris Brezillon  * want to iterate over all targets/dies of a NAND device.
519*ed99f773SBoris Brezillon  */
520*ed99f773SBoris Brezillon static inline void nanddev_pos_next_target(struct nand_device *nand,
521*ed99f773SBoris Brezillon 					   struct nand_pos *pos)
522*ed99f773SBoris Brezillon {
523*ed99f773SBoris Brezillon 	pos->page = 0;
524*ed99f773SBoris Brezillon 	pos->plane = 0;
525*ed99f773SBoris Brezillon 	pos->eraseblock = 0;
526*ed99f773SBoris Brezillon 	pos->lun = 0;
527*ed99f773SBoris Brezillon 	pos->target++;
528*ed99f773SBoris Brezillon }
529*ed99f773SBoris Brezillon 
530*ed99f773SBoris Brezillon /**
531*ed99f773SBoris Brezillon  * nanddev_pos_next_lun() - Move a position to the next LUN
532*ed99f773SBoris Brezillon  * @nand: NAND device
533*ed99f773SBoris Brezillon  * @pos: the position to update
534*ed99f773SBoris Brezillon  *
535*ed99f773SBoris Brezillon  * Updates @pos to point to the start of the next LUN. Useful when you want to
536*ed99f773SBoris Brezillon  * iterate over all LUNs of a NAND device.
537*ed99f773SBoris Brezillon  */
538*ed99f773SBoris Brezillon static inline void nanddev_pos_next_lun(struct nand_device *nand,
539*ed99f773SBoris Brezillon 					struct nand_pos *pos)
540*ed99f773SBoris Brezillon {
541*ed99f773SBoris Brezillon 	if (pos->lun >= nand->memorg.luns_per_target - 1)
542*ed99f773SBoris Brezillon 		return nanddev_pos_next_target(nand, pos);
543*ed99f773SBoris Brezillon 
544*ed99f773SBoris Brezillon 	pos->lun++;
545*ed99f773SBoris Brezillon 	pos->page = 0;
546*ed99f773SBoris Brezillon 	pos->plane = 0;
547*ed99f773SBoris Brezillon 	pos->eraseblock = 0;
548*ed99f773SBoris Brezillon }
549*ed99f773SBoris Brezillon 
550*ed99f773SBoris Brezillon /**
551*ed99f773SBoris Brezillon  * nanddev_pos_next_eraseblock() - Move a position to the next eraseblock
552*ed99f773SBoris Brezillon  * @nand: NAND device
553*ed99f773SBoris Brezillon  * @pos: the position to update
554*ed99f773SBoris Brezillon  *
555*ed99f773SBoris Brezillon  * Updates @pos to point to the start of the next eraseblock. Useful when you
556*ed99f773SBoris Brezillon  * want to iterate over all eraseblocks of a NAND device.
557*ed99f773SBoris Brezillon  */
558*ed99f773SBoris Brezillon static inline void nanddev_pos_next_eraseblock(struct nand_device *nand,
559*ed99f773SBoris Brezillon 					       struct nand_pos *pos)
560*ed99f773SBoris Brezillon {
561*ed99f773SBoris Brezillon 	if (pos->eraseblock >= nand->memorg.eraseblocks_per_lun - 1)
562*ed99f773SBoris Brezillon 		return nanddev_pos_next_lun(nand, pos);
563*ed99f773SBoris Brezillon 
564*ed99f773SBoris Brezillon 	pos->eraseblock++;
565*ed99f773SBoris Brezillon 	pos->page = 0;
566*ed99f773SBoris Brezillon 	pos->plane = pos->eraseblock % nand->memorg.planes_per_lun;
567*ed99f773SBoris Brezillon }
568*ed99f773SBoris Brezillon 
569*ed99f773SBoris Brezillon /**
570*ed99f773SBoris Brezillon  * nanddev_pos_next_eraseblock() - Move a position to the next page
571*ed99f773SBoris Brezillon  * @nand: NAND device
572*ed99f773SBoris Brezillon  * @pos: the position to update
573*ed99f773SBoris Brezillon  *
574*ed99f773SBoris Brezillon  * Updates @pos to point to the start of the next page. Useful when you want to
575*ed99f773SBoris Brezillon  * iterate over all pages of a NAND device.
576*ed99f773SBoris Brezillon  */
577*ed99f773SBoris Brezillon static inline void nanddev_pos_next_page(struct nand_device *nand,
578*ed99f773SBoris Brezillon 					 struct nand_pos *pos)
579*ed99f773SBoris Brezillon {
580*ed99f773SBoris Brezillon 	if (pos->page >= nand->memorg.pages_per_eraseblock - 1)
581*ed99f773SBoris Brezillon 		return nanddev_pos_next_eraseblock(nand, pos);
582*ed99f773SBoris Brezillon 
583*ed99f773SBoris Brezillon 	pos->page++;
584*ed99f773SBoris Brezillon }
585*ed99f773SBoris Brezillon 
586*ed99f773SBoris Brezillon /**
587*ed99f773SBoris Brezillon  * nand_io_iter_init - Initialize a NAND I/O iterator
588*ed99f773SBoris Brezillon  * @nand: NAND device
589*ed99f773SBoris Brezillon  * @offs: absolute offset
590*ed99f773SBoris Brezillon  * @req: MTD request
591*ed99f773SBoris Brezillon  * @iter: NAND I/O iterator
592*ed99f773SBoris Brezillon  *
593*ed99f773SBoris Brezillon  * Initializes a NAND iterator based on the information passed by the MTD
594*ed99f773SBoris Brezillon  * layer.
595*ed99f773SBoris Brezillon  */
596*ed99f773SBoris Brezillon static inline void nanddev_io_iter_init(struct nand_device *nand,
597*ed99f773SBoris Brezillon 					loff_t offs, struct mtd_oob_ops *req,
598*ed99f773SBoris Brezillon 					struct nand_io_iter *iter)
599*ed99f773SBoris Brezillon {
600*ed99f773SBoris Brezillon 	struct mtd_info *mtd = nanddev_to_mtd(nand);
601*ed99f773SBoris Brezillon 
602*ed99f773SBoris Brezillon 	iter->req.dataoffs = nanddev_offs_to_pos(nand, offs, &iter->req.pos);
603*ed99f773SBoris Brezillon 	iter->req.ooboffs = req->ooboffs;
604*ed99f773SBoris Brezillon 	iter->oobbytes_per_page = mtd_oobavail(mtd, req);
605*ed99f773SBoris Brezillon 	iter->dataleft = req->len;
606*ed99f773SBoris Brezillon 	iter->oobleft = req->ooblen;
607*ed99f773SBoris Brezillon 	iter->req.databuf.in = req->datbuf;
608*ed99f773SBoris Brezillon 	iter->req.datalen = min_t(unsigned int,
609*ed99f773SBoris Brezillon 				  nand->memorg.pagesize - iter->req.dataoffs,
610*ed99f773SBoris Brezillon 				  iter->dataleft);
611*ed99f773SBoris Brezillon 	iter->req.oobbuf.in = req->oobbuf;
612*ed99f773SBoris Brezillon 	iter->req.ooblen = min_t(unsigned int,
613*ed99f773SBoris Brezillon 				 iter->oobbytes_per_page - iter->req.ooboffs,
614*ed99f773SBoris Brezillon 				 iter->oobleft);
615*ed99f773SBoris Brezillon }
616*ed99f773SBoris Brezillon 
617*ed99f773SBoris Brezillon /**
618*ed99f773SBoris Brezillon  * nand_io_iter_next_page - Move to the next page
619*ed99f773SBoris Brezillon  * @nand: NAND device
620*ed99f773SBoris Brezillon  * @iter: NAND I/O iterator
621*ed99f773SBoris Brezillon  *
622*ed99f773SBoris Brezillon  * Updates the @iter to point to the next page.
623*ed99f773SBoris Brezillon  */
624*ed99f773SBoris Brezillon static inline void nanddev_io_iter_next_page(struct nand_device *nand,
625*ed99f773SBoris Brezillon 					     struct nand_io_iter *iter)
626*ed99f773SBoris Brezillon {
627*ed99f773SBoris Brezillon 	nanddev_pos_next_page(nand, &iter->req.pos);
628*ed99f773SBoris Brezillon 	iter->dataleft -= iter->req.datalen;
629*ed99f773SBoris Brezillon 	iter->req.databuf.in += iter->req.datalen;
630*ed99f773SBoris Brezillon 	iter->oobleft -= iter->req.ooblen;
631*ed99f773SBoris Brezillon 	iter->req.oobbuf.in += iter->req.ooblen;
632*ed99f773SBoris Brezillon 	iter->req.dataoffs = 0;
633*ed99f773SBoris Brezillon 	iter->req.ooboffs = 0;
634*ed99f773SBoris Brezillon 	iter->req.datalen = min_t(unsigned int, nand->memorg.pagesize,
635*ed99f773SBoris Brezillon 				  iter->dataleft);
636*ed99f773SBoris Brezillon 	iter->req.ooblen = min_t(unsigned int, iter->oobbytes_per_page,
637*ed99f773SBoris Brezillon 				 iter->oobleft);
638*ed99f773SBoris Brezillon }
639*ed99f773SBoris Brezillon 
640*ed99f773SBoris Brezillon /**
641*ed99f773SBoris Brezillon  * nand_io_iter_end - Should end iteration or not
642*ed99f773SBoris Brezillon  * @nand: NAND device
643*ed99f773SBoris Brezillon  * @iter: NAND I/O iterator
644*ed99f773SBoris Brezillon  *
645*ed99f773SBoris Brezillon  * Check whether @iter has reached the end of the NAND portion it was asked to
646*ed99f773SBoris Brezillon  * iterate on or not.
647*ed99f773SBoris Brezillon  *
648*ed99f773SBoris Brezillon  * Return: true if @iter has reached the end of the iteration request, false
649*ed99f773SBoris Brezillon  *	   otherwise.
650*ed99f773SBoris Brezillon  */
651*ed99f773SBoris Brezillon static inline bool nanddev_io_iter_end(struct nand_device *nand,
652*ed99f773SBoris Brezillon 				       const struct nand_io_iter *iter)
653*ed99f773SBoris Brezillon {
654*ed99f773SBoris Brezillon 	if (iter->dataleft || iter->oobleft)
655*ed99f773SBoris Brezillon 		return false;
656*ed99f773SBoris Brezillon 
657*ed99f773SBoris Brezillon 	return true;
658*ed99f773SBoris Brezillon }
659*ed99f773SBoris Brezillon 
660*ed99f773SBoris Brezillon /**
661*ed99f773SBoris Brezillon  * nand_io_for_each_page - Iterate over all NAND pages contained in an MTD I/O
662*ed99f773SBoris Brezillon  *			   request
663*ed99f773SBoris Brezillon  * @nand: NAND device
664*ed99f773SBoris Brezillon  * @start: start address to read/write from
665*ed99f773SBoris Brezillon  * @req: MTD I/O request
666*ed99f773SBoris Brezillon  * @iter: NAND I/O iterator
667*ed99f773SBoris Brezillon  *
668*ed99f773SBoris Brezillon  * Should be used for iterate over pages that are contained in an MTD request.
669*ed99f773SBoris Brezillon  */
670*ed99f773SBoris Brezillon #define nanddev_io_for_each_page(nand, start, req, iter)		\
671*ed99f773SBoris Brezillon 	for (nanddev_io_iter_init(nand, start, req, iter);		\
672*ed99f773SBoris Brezillon 	     !nanddev_io_iter_end(nand, iter);				\
673*ed99f773SBoris Brezillon 	     nanddev_io_iter_next_page(nand, iter))
674*ed99f773SBoris Brezillon 
675*ed99f773SBoris Brezillon bool nanddev_isbad(struct nand_device *nand, const struct nand_pos *pos);
676*ed99f773SBoris Brezillon bool nanddev_isreserved(struct nand_device *nand, const struct nand_pos *pos);
677*ed99f773SBoris Brezillon int nanddev_erase(struct nand_device *nand, const struct nand_pos *pos);
678*ed99f773SBoris Brezillon int nanddev_markbad(struct nand_device *nand, const struct nand_pos *pos);
679*ed99f773SBoris Brezillon 
680*ed99f773SBoris Brezillon /* BBT related functions */
681*ed99f773SBoris Brezillon enum nand_bbt_block_status {
682*ed99f773SBoris Brezillon 	NAND_BBT_BLOCK_STATUS_UNKNOWN,
683*ed99f773SBoris Brezillon 	NAND_BBT_BLOCK_GOOD,
684*ed99f773SBoris Brezillon 	NAND_BBT_BLOCK_WORN,
685*ed99f773SBoris Brezillon 	NAND_BBT_BLOCK_RESERVED,
686*ed99f773SBoris Brezillon 	NAND_BBT_BLOCK_FACTORY_BAD,
687*ed99f773SBoris Brezillon 	NAND_BBT_BLOCK_NUM_STATUS,
688*ed99f773SBoris Brezillon };
689*ed99f773SBoris Brezillon 
690*ed99f773SBoris Brezillon int nanddev_bbt_init(struct nand_device *nand);
691*ed99f773SBoris Brezillon void nanddev_bbt_cleanup(struct nand_device *nand);
692*ed99f773SBoris Brezillon int nanddev_bbt_update(struct nand_device *nand);
693*ed99f773SBoris Brezillon int nanddev_bbt_get_block_status(const struct nand_device *nand,
694*ed99f773SBoris Brezillon 				 unsigned int entry);
695*ed99f773SBoris Brezillon int nanddev_bbt_set_block_status(struct nand_device *nand, unsigned int entry,
696*ed99f773SBoris Brezillon 				 enum nand_bbt_block_status status);
697*ed99f773SBoris Brezillon int nanddev_bbt_markbad(struct nand_device *nand, unsigned int block);
698*ed99f773SBoris Brezillon 
699*ed99f773SBoris Brezillon /**
700*ed99f773SBoris Brezillon  * nanddev_bbt_pos_to_entry() - Convert a NAND position into a BBT entry
701*ed99f773SBoris Brezillon  * @nand: NAND device
702*ed99f773SBoris Brezillon  * @pos: the NAND position we want to get BBT entry for
703*ed99f773SBoris Brezillon  *
704*ed99f773SBoris Brezillon  * Return the BBT entry used to store information about the eraseblock pointed
705*ed99f773SBoris Brezillon  * by @pos.
706*ed99f773SBoris Brezillon  *
707*ed99f773SBoris Brezillon  * Return: the BBT entry storing information about eraseblock pointed by @pos.
708*ed99f773SBoris Brezillon  */
709*ed99f773SBoris Brezillon static inline unsigned int nanddev_bbt_pos_to_entry(struct nand_device *nand,
710*ed99f773SBoris Brezillon 						    const struct nand_pos *pos)
711*ed99f773SBoris Brezillon {
712*ed99f773SBoris Brezillon 	return pos->eraseblock +
713*ed99f773SBoris Brezillon 	       ((pos->lun + (pos->target * nand->memorg.luns_per_target)) *
714*ed99f773SBoris Brezillon 		nand->memorg.eraseblocks_per_lun);
715*ed99f773SBoris Brezillon }
716*ed99f773SBoris Brezillon 
717*ed99f773SBoris Brezillon /**
718*ed99f773SBoris Brezillon  * nanddev_bbt_is_initialized() - Check if the BBT has been initialized
719*ed99f773SBoris Brezillon  * @nand: NAND device
720*ed99f773SBoris Brezillon  *
721*ed99f773SBoris Brezillon  * Return: true if the BBT has been initialized, false otherwise.
722*ed99f773SBoris Brezillon  */
723*ed99f773SBoris Brezillon static inline bool nanddev_bbt_is_initialized(struct nand_device *nand)
724*ed99f773SBoris Brezillon {
725*ed99f773SBoris Brezillon 	return !!nand->bbt.cache;
726*ed99f773SBoris Brezillon }
727*ed99f773SBoris Brezillon 
728*ed99f773SBoris Brezillon /* MTD -> NAND helper functions. */
729*ed99f773SBoris Brezillon int nanddev_mtd_erase(struct mtd_info *mtd, struct erase_info *einfo);
730*ed99f773SBoris Brezillon 
731*ed99f773SBoris Brezillon #endif /* __LINUX_MTD_NAND_H */
732