1 | /* SPDX-License-Identifier: GPL-2.0 */ |
2 | /* |
3 | * Copyright 2017 - Free Electrons |
4 | * |
5 | * Authors: |
6 | * Boris Brezillon <boris.brezillon@free-electrons.com> |
7 | * Peter Pan <peterpandong@micron.com> |
8 | */ |
9 | |
10 | #ifndef __LINUX_MTD_NAND_H |
11 | #define __LINUX_MTD_NAND_H |
12 | |
13 | #include <linux/mtd/mtd.h> |
14 | |
15 | struct nand_device; |
16 | |
17 | /** |
18 | * struct nand_memory_organization - Memory organization structure |
19 | * @bits_per_cell: number of bits per NAND cell |
20 | * @pagesize: page size |
21 | * @oobsize: OOB area size |
22 | * @pages_per_eraseblock: number of pages per eraseblock |
23 | * @eraseblocks_per_lun: number of eraseblocks per LUN (Logical Unit Number) |
24 | * @max_bad_eraseblocks_per_lun: maximum number of eraseblocks per LUN |
25 | * @planes_per_lun: number of planes per LUN |
26 | * @luns_per_target: number of LUN per target (target is a synonym for die) |
27 | * @ntargets: total number of targets exposed by the NAND device |
28 | */ |
29 | struct nand_memory_organization { |
30 | unsigned int bits_per_cell; |
31 | unsigned int pagesize; |
32 | unsigned int oobsize; |
33 | unsigned int pages_per_eraseblock; |
34 | unsigned int eraseblocks_per_lun; |
35 | unsigned int max_bad_eraseblocks_per_lun; |
36 | unsigned int planes_per_lun; |
37 | unsigned int luns_per_target; |
38 | unsigned int ntargets; |
39 | }; |
40 | |
41 | #define NAND_MEMORG(bpc, ps, os, ppe, epl, mbb, ppl, lpt, nt) \ |
42 | { \ |
43 | .bits_per_cell = (bpc), \ |
44 | .pagesize = (ps), \ |
45 | .oobsize = (os), \ |
46 | .pages_per_eraseblock = (ppe), \ |
47 | .eraseblocks_per_lun = (epl), \ |
48 | .max_bad_eraseblocks_per_lun = (mbb), \ |
49 | .planes_per_lun = (ppl), \ |
50 | .luns_per_target = (lpt), \ |
51 | .ntargets = (nt), \ |
52 | } |
53 | |
54 | /** |
55 | * struct nand_row_converter - Information needed to convert an absolute offset |
56 | * into a row address |
57 | * @lun_addr_shift: position of the LUN identifier in the row address |
58 | * @eraseblock_addr_shift: position of the eraseblock identifier in the row |
59 | * address |
60 | */ |
61 | struct nand_row_converter { |
62 | unsigned int lun_addr_shift; |
63 | unsigned int eraseblock_addr_shift; |
64 | }; |
65 | |
66 | /** |
67 | * struct nand_pos - NAND position object |
68 | * @target: the NAND target/die |
69 | * @lun: the LUN identifier |
70 | * @plane: the plane within the LUN |
71 | * @eraseblock: the eraseblock within the LUN |
72 | * @page: the page within the LUN |
73 | * |
74 | * These information are usually used by specific sub-layers to select the |
75 | * appropriate target/die and generate a row address to pass to the device. |
76 | */ |
77 | struct nand_pos { |
78 | unsigned int target; |
79 | unsigned int lun; |
80 | unsigned int plane; |
81 | unsigned int eraseblock; |
82 | unsigned int page; |
83 | }; |
84 | |
85 | /** |
86 | * enum nand_page_io_req_type - Direction of an I/O request |
87 | * @NAND_PAGE_READ: from the chip, to the controller |
88 | * @NAND_PAGE_WRITE: from the controller, to the chip |
89 | */ |
90 | enum nand_page_io_req_type { |
91 | NAND_PAGE_READ = 0, |
92 | NAND_PAGE_WRITE, |
93 | }; |
94 | |
95 | /** |
96 | * struct nand_page_io_req - NAND I/O request object |
97 | * @type: the type of page I/O: read or write |
98 | * @pos: the position this I/O request is targeting |
99 | * @dataoffs: the offset within the page |
100 | * @datalen: number of data bytes to read from/write to this page |
101 | * @databuf: buffer to store data in or get data from |
102 | * @ooboffs: the OOB offset within the page |
103 | * @ooblen: the number of OOB bytes to read from/write to this page |
104 | * @oobbuf: buffer to store OOB data in or get OOB data from |
105 | * @mode: one of the %MTD_OPS_XXX mode |
106 | * |
107 | * This object is used to pass per-page I/O requests to NAND sub-layers. This |
108 | * way all useful information are already formatted in a useful way and |
109 | * specific NAND layers can focus on translating these information into |
110 | * specific commands/operations. |
111 | */ |
112 | struct nand_page_io_req { |
113 | enum nand_page_io_req_type type; |
114 | struct nand_pos pos; |
115 | unsigned int dataoffs; |
116 | unsigned int datalen; |
117 | union { |
118 | const void *out; |
119 | void *in; |
120 | } databuf; |
121 | unsigned int ooboffs; |
122 | unsigned int ooblen; |
123 | union { |
124 | const void *out; |
125 | void *in; |
126 | } oobbuf; |
127 | int mode; |
128 | }; |
129 | |
130 | const struct mtd_ooblayout_ops *nand_get_small_page_ooblayout(void); |
131 | const struct mtd_ooblayout_ops *nand_get_large_page_ooblayout(void); |
132 | const struct mtd_ooblayout_ops *nand_get_large_page_hamming_ooblayout(void); |
133 | |
134 | /** |
135 | * enum nand_ecc_engine_type - NAND ECC engine type |
136 | * @NAND_ECC_ENGINE_TYPE_INVALID: Invalid value |
137 | * @NAND_ECC_ENGINE_TYPE_NONE: No ECC correction |
138 | * @NAND_ECC_ENGINE_TYPE_SOFT: Software ECC correction |
139 | * @NAND_ECC_ENGINE_TYPE_ON_HOST: On host hardware ECC correction |
140 | * @NAND_ECC_ENGINE_TYPE_ON_DIE: On chip hardware ECC correction |
141 | */ |
142 | enum nand_ecc_engine_type { |
143 | NAND_ECC_ENGINE_TYPE_INVALID, |
144 | NAND_ECC_ENGINE_TYPE_NONE, |
145 | NAND_ECC_ENGINE_TYPE_SOFT, |
146 | NAND_ECC_ENGINE_TYPE_ON_HOST, |
147 | NAND_ECC_ENGINE_TYPE_ON_DIE, |
148 | }; |
149 | |
150 | /** |
151 | * enum nand_ecc_placement - NAND ECC bytes placement |
152 | * @NAND_ECC_PLACEMENT_UNKNOWN: The actual position of the ECC bytes is unknown |
153 | * @NAND_ECC_PLACEMENT_OOB: The ECC bytes are located in the OOB area |
154 | * @NAND_ECC_PLACEMENT_INTERLEAVED: Syndrome layout, there are ECC bytes |
155 | * interleaved with regular data in the main |
156 | * area |
157 | */ |
158 | enum nand_ecc_placement { |
159 | NAND_ECC_PLACEMENT_UNKNOWN, |
160 | NAND_ECC_PLACEMENT_OOB, |
161 | NAND_ECC_PLACEMENT_INTERLEAVED, |
162 | }; |
163 | |
164 | /** |
165 | * enum nand_ecc_algo - NAND ECC algorithm |
166 | * @NAND_ECC_ALGO_UNKNOWN: Unknown algorithm |
167 | * @NAND_ECC_ALGO_HAMMING: Hamming algorithm |
168 | * @NAND_ECC_ALGO_BCH: Bose-Chaudhuri-Hocquenghem algorithm |
169 | * @NAND_ECC_ALGO_RS: Reed-Solomon algorithm |
170 | */ |
171 | enum nand_ecc_algo { |
172 | NAND_ECC_ALGO_UNKNOWN, |
173 | NAND_ECC_ALGO_HAMMING, |
174 | NAND_ECC_ALGO_BCH, |
175 | NAND_ECC_ALGO_RS, |
176 | }; |
177 | |
178 | /** |
179 | * struct nand_ecc_props - NAND ECC properties |
180 | * @engine_type: ECC engine type |
181 | * @placement: OOB placement (if relevant) |
182 | * @algo: ECC algorithm (if relevant) |
183 | * @strength: ECC strength |
184 | * @step_size: Number of bytes per step |
185 | * @flags: Misc properties |
186 | */ |
187 | struct nand_ecc_props { |
188 | enum nand_ecc_engine_type engine_type; |
189 | enum nand_ecc_placement placement; |
190 | enum nand_ecc_algo algo; |
191 | unsigned int strength; |
192 | unsigned int step_size; |
193 | unsigned int flags; |
194 | }; |
195 | |
196 | #define NAND_ECCREQ(str, stp) { .strength = (str), .step_size = (stp) } |
197 | |
198 | /* NAND ECC misc flags */ |
199 | #define NAND_ECC_MAXIMIZE_STRENGTH BIT(0) |
200 | |
201 | /** |
202 | * struct nand_bbt - bad block table object |
203 | * @cache: in memory BBT cache |
204 | */ |
205 | struct nand_bbt { |
206 | unsigned long *cache; |
207 | }; |
208 | |
209 | /** |
210 | * struct nand_ops - NAND operations |
211 | * @erase: erase a specific block. No need to check if the block is bad before |
212 | * erasing, this has been taken care of by the generic NAND layer |
213 | * @markbad: mark a specific block bad. No need to check if the block is |
214 | * already marked bad, this has been taken care of by the generic |
215 | * NAND layer. This method should just write the BBM (Bad Block |
216 | * Marker) so that future call to struct_nand_ops->isbad() return |
217 | * true |
218 | * @isbad: check whether a block is bad or not. This method should just read |
219 | * the BBM and return whether the block is bad or not based on what it |
220 | * reads |
221 | * |
222 | * These are all low level operations that should be implemented by specialized |
223 | * NAND layers (SPI NAND, raw NAND, ...). |
224 | */ |
225 | struct nand_ops { |
226 | int (*erase)(struct nand_device *nand, const struct nand_pos *pos); |
227 | int (*markbad)(struct nand_device *nand, const struct nand_pos *pos); |
228 | bool (*isbad)(struct nand_device *nand, const struct nand_pos *pos); |
229 | }; |
230 | |
231 | /** |
232 | * struct nand_ecc_context - Context for the ECC engine |
233 | * @conf: basic ECC engine parameters |
234 | * @nsteps: number of ECC steps |
235 | * @total: total number of bytes used for storing ECC codes, this is used by |
236 | * generic OOB layouts |
237 | * @priv: ECC engine driver private data |
238 | */ |
239 | struct nand_ecc_context { |
240 | struct nand_ecc_props conf; |
241 | unsigned int nsteps; |
242 | unsigned int total; |
243 | void *priv; |
244 | }; |
245 | |
246 | /** |
247 | * struct nand_ecc_engine_ops - ECC engine operations |
248 | * @init_ctx: given a desired user configuration for the pointed NAND device, |
249 | * requests the ECC engine driver to setup a configuration with |
250 | * values it supports. |
251 | * @cleanup_ctx: clean the context initialized by @init_ctx. |
252 | * @prepare_io_req: is called before reading/writing a page to prepare the I/O |
253 | * request to be performed with ECC correction. |
254 | * @finish_io_req: is called after reading/writing a page to terminate the I/O |
255 | * request and ensure proper ECC correction. |
256 | */ |
257 | struct nand_ecc_engine_ops { |
258 | int (*init_ctx)(struct nand_device *nand); |
259 | void (*cleanup_ctx)(struct nand_device *nand); |
260 | int (*prepare_io_req)(struct nand_device *nand, |
261 | struct nand_page_io_req *req); |
262 | int (*finish_io_req)(struct nand_device *nand, |
263 | struct nand_page_io_req *req); |
264 | }; |
265 | |
266 | /** |
267 | * enum nand_ecc_engine_integration - How the NAND ECC engine is integrated |
268 | * @NAND_ECC_ENGINE_INTEGRATION_INVALID: Invalid value |
269 | * @NAND_ECC_ENGINE_INTEGRATION_PIPELINED: Pipelined engine, performs on-the-fly |
270 | * correction, does not need to copy |
271 | * data around |
272 | * @NAND_ECC_ENGINE_INTEGRATION_EXTERNAL: External engine, needs to bring the |
273 | * data into its own area before use |
274 | */ |
275 | enum nand_ecc_engine_integration { |
276 | NAND_ECC_ENGINE_INTEGRATION_INVALID, |
277 | NAND_ECC_ENGINE_INTEGRATION_PIPELINED, |
278 | NAND_ECC_ENGINE_INTEGRATION_EXTERNAL, |
279 | }; |
280 | |
281 | /** |
282 | * struct nand_ecc_engine - ECC engine abstraction for NAND devices |
283 | * @dev: Host device |
284 | * @node: Private field for registration time |
285 | * @ops: ECC engine operations |
286 | * @integration: How the engine is integrated with the host |
287 | * (only relevant on %NAND_ECC_ENGINE_TYPE_ON_HOST engines) |
288 | * @priv: Private data |
289 | */ |
290 | struct nand_ecc_engine { |
291 | struct device *dev; |
292 | struct list_head node; |
293 | struct nand_ecc_engine_ops *ops; |
294 | enum nand_ecc_engine_integration integration; |
295 | void *priv; |
296 | }; |
297 | |
298 | void of_get_nand_ecc_user_config(struct nand_device *nand); |
299 | int nand_ecc_init_ctx(struct nand_device *nand); |
300 | void nand_ecc_cleanup_ctx(struct nand_device *nand); |
301 | int nand_ecc_prepare_io_req(struct nand_device *nand, |
302 | struct nand_page_io_req *req); |
303 | int nand_ecc_finish_io_req(struct nand_device *nand, |
304 | struct nand_page_io_req *req); |
305 | bool nand_ecc_is_strong_enough(struct nand_device *nand); |
306 | |
307 | #if IS_REACHABLE(CONFIG_MTD_NAND_CORE) |
308 | int nand_ecc_register_on_host_hw_engine(struct nand_ecc_engine *engine); |
309 | int nand_ecc_unregister_on_host_hw_engine(struct nand_ecc_engine *engine); |
310 | #else |
311 | static inline int |
312 | nand_ecc_register_on_host_hw_engine(struct nand_ecc_engine *engine) |
313 | { |
314 | return -ENOTSUPP; |
315 | } |
316 | static inline int |
317 | nand_ecc_unregister_on_host_hw_engine(struct nand_ecc_engine *engine) |
318 | { |
319 | return -ENOTSUPP; |
320 | } |
321 | #endif |
322 | |
323 | struct nand_ecc_engine *nand_ecc_get_sw_engine(struct nand_device *nand); |
324 | struct nand_ecc_engine *nand_ecc_get_on_die_hw_engine(struct nand_device *nand); |
325 | struct nand_ecc_engine *nand_ecc_get_on_host_hw_engine(struct nand_device *nand); |
326 | void nand_ecc_put_on_host_hw_engine(struct nand_device *nand); |
327 | struct device *nand_ecc_get_engine_dev(struct device *host); |
328 | |
329 | #if IS_ENABLED(CONFIG_MTD_NAND_ECC_SW_HAMMING) |
330 | struct nand_ecc_engine *nand_ecc_sw_hamming_get_engine(void); |
331 | #else |
332 | static inline struct nand_ecc_engine *nand_ecc_sw_hamming_get_engine(void) |
333 | { |
334 | return NULL; |
335 | } |
336 | #endif /* CONFIG_MTD_NAND_ECC_SW_HAMMING */ |
337 | |
338 | #if IS_ENABLED(CONFIG_MTD_NAND_ECC_SW_BCH) |
339 | struct nand_ecc_engine *nand_ecc_sw_bch_get_engine(void); |
340 | #else |
341 | static inline struct nand_ecc_engine *nand_ecc_sw_bch_get_engine(void) |
342 | { |
343 | return NULL; |
344 | } |
345 | #endif /* CONFIG_MTD_NAND_ECC_SW_BCH */ |
346 | |
347 | /** |
348 | * struct nand_ecc_req_tweak_ctx - Help for automatically tweaking requests |
349 | * @orig_req: Pointer to the original IO request |
350 | * @nand: Related NAND device, to have access to its memory organization |
351 | * @page_buffer_size: Real size of the page buffer to use (can be set by the |
352 | * user before the tweaking mechanism initialization) |
353 | * @oob_buffer_size: Real size of the OOB buffer to use (can be set by the |
354 | * user before the tweaking mechanism initialization) |
355 | * @spare_databuf: Data bounce buffer |
356 | * @spare_oobbuf: OOB bounce buffer |
357 | * @bounce_data: Flag indicating a data bounce buffer is used |
358 | * @bounce_oob: Flag indicating an OOB bounce buffer is used |
359 | */ |
360 | struct nand_ecc_req_tweak_ctx { |
361 | struct nand_page_io_req orig_req; |
362 | struct nand_device *nand; |
363 | unsigned int page_buffer_size; |
364 | unsigned int oob_buffer_size; |
365 | void *spare_databuf; |
366 | void *spare_oobbuf; |
367 | bool bounce_data; |
368 | bool bounce_oob; |
369 | }; |
370 | |
371 | int nand_ecc_init_req_tweaking(struct nand_ecc_req_tweak_ctx *ctx, |
372 | struct nand_device *nand); |
373 | void nand_ecc_cleanup_req_tweaking(struct nand_ecc_req_tweak_ctx *ctx); |
374 | void nand_ecc_tweak_req(struct nand_ecc_req_tweak_ctx *ctx, |
375 | struct nand_page_io_req *req); |
376 | void nand_ecc_restore_req(struct nand_ecc_req_tweak_ctx *ctx, |
377 | struct nand_page_io_req *req); |
378 | |
379 | /** |
380 | * struct nand_ecc - Information relative to the ECC |
381 | * @defaults: Default values, depend on the underlying subsystem |
382 | * @requirements: ECC requirements from the NAND chip perspective |
383 | * @user_conf: User desires in terms of ECC parameters |
384 | * @ctx: ECC context for the ECC engine, derived from the device @requirements |
385 | * the @user_conf and the @defaults |
386 | * @ondie_engine: On-die ECC engine reference, if any |
387 | * @engine: ECC engine actually bound |
388 | */ |
389 | struct nand_ecc { |
390 | struct nand_ecc_props defaults; |
391 | struct nand_ecc_props requirements; |
392 | struct nand_ecc_props user_conf; |
393 | struct nand_ecc_context ctx; |
394 | struct nand_ecc_engine *ondie_engine; |
395 | struct nand_ecc_engine *engine; |
396 | }; |
397 | |
398 | /** |
399 | * struct nand_device - NAND device |
400 | * @mtd: MTD instance attached to the NAND device |
401 | * @memorg: memory layout |
402 | * @ecc: NAND ECC object attached to the NAND device |
403 | * @rowconv: position to row address converter |
404 | * @bbt: bad block table info |
405 | * @ops: NAND operations attached to the NAND device |
406 | * |
407 | * Generic NAND object. Specialized NAND layers (raw NAND, SPI NAND, OneNAND) |
408 | * should declare their own NAND object embedding a nand_device struct (that's |
409 | * how inheritance is done). |
410 | * struct_nand_device->memorg and struct_nand_device->ecc.requirements should |
411 | * be filled at device detection time to reflect the NAND device |
412 | * capabilities/requirements. Once this is done nanddev_init() can be called. |
413 | * It will take care of converting NAND information into MTD ones, which means |
414 | * the specialized NAND layers should never manually tweak |
415 | * struct_nand_device->mtd except for the ->_read/write() hooks. |
416 | */ |
417 | struct nand_device { |
418 | struct mtd_info mtd; |
419 | struct nand_memory_organization memorg; |
420 | struct nand_ecc ecc; |
421 | struct nand_row_converter rowconv; |
422 | struct nand_bbt bbt; |
423 | const struct nand_ops *ops; |
424 | }; |
425 | |
426 | /** |
427 | * struct nand_io_iter - NAND I/O iterator |
428 | * @req: current I/O request |
429 | * @oobbytes_per_page: maximum number of OOB bytes per page |
430 | * @dataleft: remaining number of data bytes to read/write |
431 | * @oobleft: remaining number of OOB bytes to read/write |
432 | * |
433 | * Can be used by specialized NAND layers to iterate over all pages covered |
434 | * by an MTD I/O request, which should greatly simplifies the boiler-plate |
435 | * code needed to read/write data from/to a NAND device. |
436 | */ |
437 | struct nand_io_iter { |
438 | struct nand_page_io_req req; |
439 | unsigned int oobbytes_per_page; |
440 | unsigned int dataleft; |
441 | unsigned int oobleft; |
442 | }; |
443 | |
444 | /** |
445 | * mtd_to_nanddev() - Get the NAND device attached to the MTD instance |
446 | * @mtd: MTD instance |
447 | * |
448 | * Return: the NAND device embedding @mtd. |
449 | */ |
450 | static inline struct nand_device *mtd_to_nanddev(struct mtd_info *mtd) |
451 | { |
452 | return container_of(mtd, struct nand_device, mtd); |
453 | } |
454 | |
455 | /** |
456 | * nanddev_to_mtd() - Get the MTD device attached to a NAND device |
457 | * @nand: NAND device |
458 | * |
459 | * Return: the MTD device embedded in @nand. |
460 | */ |
461 | static inline struct mtd_info *nanddev_to_mtd(struct nand_device *nand) |
462 | { |
463 | return &nand->mtd; |
464 | } |
465 | |
466 | /* |
467 | * nanddev_bits_per_cell() - Get the number of bits per cell |
468 | * @nand: NAND device |
469 | * |
470 | * Return: the number of bits per cell. |
471 | */ |
472 | static inline unsigned int nanddev_bits_per_cell(const struct nand_device *nand) |
473 | { |
474 | return nand->memorg.bits_per_cell; |
475 | } |
476 | |
477 | /** |
478 | * nanddev_page_size() - Get NAND page size |
479 | * @nand: NAND device |
480 | * |
481 | * Return: the page size. |
482 | */ |
483 | static inline size_t nanddev_page_size(const struct nand_device *nand) |
484 | { |
485 | return nand->memorg.pagesize; |
486 | } |
487 | |
488 | /** |
489 | * nanddev_per_page_oobsize() - Get NAND OOB size |
490 | * @nand: NAND device |
491 | * |
492 | * Return: the OOB size. |
493 | */ |
494 | static inline unsigned int |
495 | nanddev_per_page_oobsize(const struct nand_device *nand) |
496 | { |
497 | return nand->memorg.oobsize; |
498 | } |
499 | |
500 | /** |
501 | * nanddev_pages_per_eraseblock() - Get the number of pages per eraseblock |
502 | * @nand: NAND device |
503 | * |
504 | * Return: the number of pages per eraseblock. |
505 | */ |
506 | static inline unsigned int |
507 | nanddev_pages_per_eraseblock(const struct nand_device *nand) |
508 | { |
509 | return nand->memorg.pages_per_eraseblock; |
510 | } |
511 | |
512 | /** |
513 | * nanddev_pages_per_target() - Get the number of pages per target |
514 | * @nand: NAND device |
515 | * |
516 | * Return: the number of pages per target. |
517 | */ |
518 | static inline unsigned int |
519 | nanddev_pages_per_target(const struct nand_device *nand) |
520 | { |
521 | return nand->memorg.pages_per_eraseblock * |
522 | nand->memorg.eraseblocks_per_lun * |
523 | nand->memorg.luns_per_target; |
524 | } |
525 | |
526 | /** |
527 | * nanddev_per_page_oobsize() - Get NAND erase block size |
528 | * @nand: NAND device |
529 | * |
530 | * Return: the eraseblock size. |
531 | */ |
532 | static inline size_t nanddev_eraseblock_size(const struct nand_device *nand) |
533 | { |
534 | return nand->memorg.pagesize * nand->memorg.pages_per_eraseblock; |
535 | } |
536 | |
537 | /** |
538 | * nanddev_eraseblocks_per_lun() - Get the number of eraseblocks per LUN |
539 | * @nand: NAND device |
540 | * |
541 | * Return: the number of eraseblocks per LUN. |
542 | */ |
543 | static inline unsigned int |
544 | nanddev_eraseblocks_per_lun(const struct nand_device *nand) |
545 | { |
546 | return nand->memorg.eraseblocks_per_lun; |
547 | } |
548 | |
549 | /** |
550 | * nanddev_eraseblocks_per_target() - Get the number of eraseblocks per target |
551 | * @nand: NAND device |
552 | * |
553 | * Return: the number of eraseblocks per target. |
554 | */ |
555 | static inline unsigned int |
556 | nanddev_eraseblocks_per_target(const struct nand_device *nand) |
557 | { |
558 | return nand->memorg.eraseblocks_per_lun * nand->memorg.luns_per_target; |
559 | } |
560 | |
561 | /** |
562 | * nanddev_target_size() - Get the total size provided by a single target/die |
563 | * @nand: NAND device |
564 | * |
565 | * Return: the total size exposed by a single target/die in bytes. |
566 | */ |
567 | static inline u64 nanddev_target_size(const struct nand_device *nand) |
568 | { |
569 | return (u64)nand->memorg.luns_per_target * |
570 | nand->memorg.eraseblocks_per_lun * |
571 | nand->memorg.pages_per_eraseblock * |
572 | nand->memorg.pagesize; |
573 | } |
574 | |
575 | /** |
576 | * nanddev_ntarget() - Get the total of targets |
577 | * @nand: NAND device |
578 | * |
579 | * Return: the number of targets/dies exposed by @nand. |
580 | */ |
581 | static inline unsigned int nanddev_ntargets(const struct nand_device *nand) |
582 | { |
583 | return nand->memorg.ntargets; |
584 | } |
585 | |
586 | /** |
587 | * nanddev_neraseblocks() - Get the total number of eraseblocks |
588 | * @nand: NAND device |
589 | * |
590 | * Return: the total number of eraseblocks exposed by @nand. |
591 | */ |
592 | static inline unsigned int nanddev_neraseblocks(const struct nand_device *nand) |
593 | { |
594 | return nand->memorg.ntargets * nand->memorg.luns_per_target * |
595 | nand->memorg.eraseblocks_per_lun; |
596 | } |
597 | |
598 | /** |
599 | * nanddev_size() - Get NAND size |
600 | * @nand: NAND device |
601 | * |
602 | * Return: the total size (in bytes) exposed by @nand. |
603 | */ |
604 | static inline u64 nanddev_size(const struct nand_device *nand) |
605 | { |
606 | return nanddev_target_size(nand) * nanddev_ntargets(nand); |
607 | } |
608 | |
609 | /** |
610 | * nanddev_get_memorg() - Extract memory organization info from a NAND device |
611 | * @nand: NAND device |
612 | * |
613 | * This can be used by the upper layer to fill the memorg info before calling |
614 | * nanddev_init(). |
615 | * |
616 | * Return: the memorg object embedded in the NAND device. |
617 | */ |
618 | static inline struct nand_memory_organization * |
619 | nanddev_get_memorg(struct nand_device *nand) |
620 | { |
621 | return &nand->memorg; |
622 | } |
623 | |
624 | /** |
625 | * nanddev_get_ecc_conf() - Extract the ECC configuration from a NAND device |
626 | * @nand: NAND device |
627 | */ |
628 | static inline const struct nand_ecc_props * |
629 | nanddev_get_ecc_conf(struct nand_device *nand) |
630 | { |
631 | return &nand->ecc.ctx.conf; |
632 | } |
633 | |
634 | /** |
635 | * nanddev_get_ecc_nsteps() - Extract the number of ECC steps |
636 | * @nand: NAND device |
637 | */ |
638 | static inline unsigned int |
639 | nanddev_get_ecc_nsteps(struct nand_device *nand) |
640 | { |
641 | return nand->ecc.ctx.nsteps; |
642 | } |
643 | |
644 | /** |
645 | * nanddev_get_ecc_bytes_per_step() - Extract the number of ECC bytes per step |
646 | * @nand: NAND device |
647 | */ |
648 | static inline unsigned int |
649 | nanddev_get_ecc_bytes_per_step(struct nand_device *nand) |
650 | { |
651 | return nand->ecc.ctx.total / nand->ecc.ctx.nsteps; |
652 | } |
653 | |
654 | /** |
655 | * nanddev_get_ecc_requirements() - Extract the ECC requirements from a NAND |
656 | * device |
657 | * @nand: NAND device |
658 | */ |
659 | static inline const struct nand_ecc_props * |
660 | nanddev_get_ecc_requirements(struct nand_device *nand) |
661 | { |
662 | return &nand->ecc.requirements; |
663 | } |
664 | |
665 | /** |
666 | * nanddev_set_ecc_requirements() - Assign the ECC requirements of a NAND |
667 | * device |
668 | * @nand: NAND device |
669 | * @reqs: Requirements |
670 | */ |
671 | static inline void |
672 | nanddev_set_ecc_requirements(struct nand_device *nand, |
673 | const struct nand_ecc_props *reqs) |
674 | { |
675 | nand->ecc.requirements = *reqs; |
676 | } |
677 | |
678 | int nanddev_init(struct nand_device *nand, const struct nand_ops *ops, |
679 | struct module *owner); |
680 | void nanddev_cleanup(struct nand_device *nand); |
681 | |
682 | /** |
683 | * nanddev_register() - Register a NAND device |
684 | * @nand: NAND device |
685 | * |
686 | * Register a NAND device. |
687 | * This function is just a wrapper around mtd_device_register() |
688 | * registering the MTD device embedded in @nand. |
689 | * |
690 | * Return: 0 in case of success, a negative error code otherwise. |
691 | */ |
692 | static inline int nanddev_register(struct nand_device *nand) |
693 | { |
694 | return mtd_device_register(&nand->mtd, NULL, 0); |
695 | } |
696 | |
697 | /** |
698 | * nanddev_unregister() - Unregister a NAND device |
699 | * @nand: NAND device |
700 | * |
701 | * Unregister a NAND device. |
702 | * This function is just a wrapper around mtd_device_unregister() |
703 | * unregistering the MTD device embedded in @nand. |
704 | * |
705 | * Return: 0 in case of success, a negative error code otherwise. |
706 | */ |
707 | static inline int nanddev_unregister(struct nand_device *nand) |
708 | { |
709 | return mtd_device_unregister(master: &nand->mtd); |
710 | } |
711 | |
712 | /** |
713 | * nanddev_set_of_node() - Attach a DT node to a NAND device |
714 | * @nand: NAND device |
715 | * @np: DT node |
716 | * |
717 | * Attach a DT node to a NAND device. |
718 | */ |
719 | static inline void nanddev_set_of_node(struct nand_device *nand, |
720 | struct device_node *np) |
721 | { |
722 | mtd_set_of_node(mtd: &nand->mtd, np); |
723 | } |
724 | |
725 | /** |
726 | * nanddev_get_of_node() - Retrieve the DT node attached to a NAND device |
727 | * @nand: NAND device |
728 | * |
729 | * Return: the DT node attached to @nand. |
730 | */ |
731 | static inline struct device_node *nanddev_get_of_node(struct nand_device *nand) |
732 | { |
733 | return mtd_get_of_node(mtd: &nand->mtd); |
734 | } |
735 | |
736 | /** |
737 | * nanddev_offs_to_pos() - Convert an absolute NAND offset into a NAND position |
738 | * @nand: NAND device |
739 | * @offs: absolute NAND offset (usually passed by the MTD layer) |
740 | * @pos: a NAND position object to fill in |
741 | * |
742 | * Converts @offs into a nand_pos representation. |
743 | * |
744 | * Return: the offset within the NAND page pointed by @pos. |
745 | */ |
746 | static inline unsigned int nanddev_offs_to_pos(struct nand_device *nand, |
747 | loff_t offs, |
748 | struct nand_pos *pos) |
749 | { |
750 | unsigned int pageoffs; |
751 | u64 tmp = offs; |
752 | |
753 | pageoffs = do_div(tmp, nand->memorg.pagesize); |
754 | pos->page = do_div(tmp, nand->memorg.pages_per_eraseblock); |
755 | pos->eraseblock = do_div(tmp, nand->memorg.eraseblocks_per_lun); |
756 | pos->plane = pos->eraseblock % nand->memorg.planes_per_lun; |
757 | pos->lun = do_div(tmp, nand->memorg.luns_per_target); |
758 | pos->target = tmp; |
759 | |
760 | return pageoffs; |
761 | } |
762 | |
763 | /** |
764 | * nanddev_pos_cmp() - Compare two NAND positions |
765 | * @a: First NAND position |
766 | * @b: Second NAND position |
767 | * |
768 | * Compares two NAND positions. |
769 | * |
770 | * Return: -1 if @a < @b, 0 if @a == @b and 1 if @a > @b. |
771 | */ |
772 | static inline int nanddev_pos_cmp(const struct nand_pos *a, |
773 | const struct nand_pos *b) |
774 | { |
775 | if (a->target != b->target) |
776 | return a->target < b->target ? -1 : 1; |
777 | |
778 | if (a->lun != b->lun) |
779 | return a->lun < b->lun ? -1 : 1; |
780 | |
781 | if (a->eraseblock != b->eraseblock) |
782 | return a->eraseblock < b->eraseblock ? -1 : 1; |
783 | |
784 | if (a->page != b->page) |
785 | return a->page < b->page ? -1 : 1; |
786 | |
787 | return 0; |
788 | } |
789 | |
790 | /** |
791 | * nanddev_pos_to_offs() - Convert a NAND position into an absolute offset |
792 | * @nand: NAND device |
793 | * @pos: the NAND position to convert |
794 | * |
795 | * Converts @pos NAND position into an absolute offset. |
796 | * |
797 | * Return: the absolute offset. Note that @pos points to the beginning of a |
798 | * page, if one wants to point to a specific offset within this page |
799 | * the returned offset has to be adjusted manually. |
800 | */ |
801 | static inline loff_t nanddev_pos_to_offs(struct nand_device *nand, |
802 | const struct nand_pos *pos) |
803 | { |
804 | unsigned int npages; |
805 | |
806 | npages = pos->page + |
807 | ((pos->eraseblock + |
808 | (pos->lun + |
809 | (pos->target * nand->memorg.luns_per_target)) * |
810 | nand->memorg.eraseblocks_per_lun) * |
811 | nand->memorg.pages_per_eraseblock); |
812 | |
813 | return (loff_t)npages * nand->memorg.pagesize; |
814 | } |
815 | |
816 | /** |
817 | * nanddev_pos_to_row() - Extract a row address from a NAND position |
818 | * @nand: NAND device |
819 | * @pos: the position to convert |
820 | * |
821 | * Converts a NAND position into a row address that can then be passed to the |
822 | * device. |
823 | * |
824 | * Return: the row address extracted from @pos. |
825 | */ |
826 | static inline unsigned int nanddev_pos_to_row(struct nand_device *nand, |
827 | const struct nand_pos *pos) |
828 | { |
829 | return (pos->lun << nand->rowconv.lun_addr_shift) | |
830 | (pos->eraseblock << nand->rowconv.eraseblock_addr_shift) | |
831 | pos->page; |
832 | } |
833 | |
834 | /** |
835 | * nanddev_pos_next_target() - Move a position to the next target/die |
836 | * @nand: NAND device |
837 | * @pos: the position to update |
838 | * |
839 | * Updates @pos to point to the start of the next target/die. Useful when you |
840 | * want to iterate over all targets/dies of a NAND device. |
841 | */ |
842 | static inline void nanddev_pos_next_target(struct nand_device *nand, |
843 | struct nand_pos *pos) |
844 | { |
845 | pos->page = 0; |
846 | pos->plane = 0; |
847 | pos->eraseblock = 0; |
848 | pos->lun = 0; |
849 | pos->target++; |
850 | } |
851 | |
852 | /** |
853 | * nanddev_pos_next_lun() - Move a position to the next LUN |
854 | * @nand: NAND device |
855 | * @pos: the position to update |
856 | * |
857 | * Updates @pos to point to the start of the next LUN. Useful when you want to |
858 | * iterate over all LUNs of a NAND device. |
859 | */ |
860 | static inline void nanddev_pos_next_lun(struct nand_device *nand, |
861 | struct nand_pos *pos) |
862 | { |
863 | if (pos->lun >= nand->memorg.luns_per_target - 1) |
864 | return nanddev_pos_next_target(nand, pos); |
865 | |
866 | pos->lun++; |
867 | pos->page = 0; |
868 | pos->plane = 0; |
869 | pos->eraseblock = 0; |
870 | } |
871 | |
872 | /** |
873 | * nanddev_pos_next_eraseblock() - Move a position to the next eraseblock |
874 | * @nand: NAND device |
875 | * @pos: the position to update |
876 | * |
877 | * Updates @pos to point to the start of the next eraseblock. Useful when you |
878 | * want to iterate over all eraseblocks of a NAND device. |
879 | */ |
880 | static inline void nanddev_pos_next_eraseblock(struct nand_device *nand, |
881 | struct nand_pos *pos) |
882 | { |
883 | if (pos->eraseblock >= nand->memorg.eraseblocks_per_lun - 1) |
884 | return nanddev_pos_next_lun(nand, pos); |
885 | |
886 | pos->eraseblock++; |
887 | pos->page = 0; |
888 | pos->plane = pos->eraseblock % nand->memorg.planes_per_lun; |
889 | } |
890 | |
891 | /** |
892 | * nanddev_pos_next_page() - Move a position to the next page |
893 | * @nand: NAND device |
894 | * @pos: the position to update |
895 | * |
896 | * Updates @pos to point to the start of the next page. Useful when you want to |
897 | * iterate over all pages of a NAND device. |
898 | */ |
899 | static inline void nanddev_pos_next_page(struct nand_device *nand, |
900 | struct nand_pos *pos) |
901 | { |
902 | if (pos->page >= nand->memorg.pages_per_eraseblock - 1) |
903 | return nanddev_pos_next_eraseblock(nand, pos); |
904 | |
905 | pos->page++; |
906 | } |
907 | |
908 | /** |
909 | * nand_io_iter_init - Initialize a NAND I/O iterator |
910 | * @nand: NAND device |
911 | * @offs: absolute offset |
912 | * @req: MTD request |
913 | * @iter: NAND I/O iterator |
914 | * |
915 | * Initializes a NAND iterator based on the information passed by the MTD |
916 | * layer. |
917 | */ |
918 | static inline void nanddev_io_iter_init(struct nand_device *nand, |
919 | enum nand_page_io_req_type reqtype, |
920 | loff_t offs, struct mtd_oob_ops *req, |
921 | struct nand_io_iter *iter) |
922 | { |
923 | struct mtd_info *mtd = nanddev_to_mtd(nand); |
924 | |
925 | iter->req.type = reqtype; |
926 | iter->req.mode = req->mode; |
927 | iter->req.dataoffs = nanddev_offs_to_pos(nand, offs, pos: &iter->req.pos); |
928 | iter->req.ooboffs = req->ooboffs; |
929 | iter->oobbytes_per_page = mtd_oobavail(mtd, ops: req); |
930 | iter->dataleft = req->len; |
931 | iter->oobleft = req->ooblen; |
932 | iter->req.databuf.in = req->datbuf; |
933 | iter->req.datalen = min_t(unsigned int, |
934 | nand->memorg.pagesize - iter->req.dataoffs, |
935 | iter->dataleft); |
936 | iter->req.oobbuf.in = req->oobbuf; |
937 | iter->req.ooblen = min_t(unsigned int, |
938 | iter->oobbytes_per_page - iter->req.ooboffs, |
939 | iter->oobleft); |
940 | } |
941 | |
942 | /** |
943 | * nand_io_iter_next_page - Move to the next page |
944 | * @nand: NAND device |
945 | * @iter: NAND I/O iterator |
946 | * |
947 | * Updates the @iter to point to the next page. |
948 | */ |
949 | static inline void nanddev_io_iter_next_page(struct nand_device *nand, |
950 | struct nand_io_iter *iter) |
951 | { |
952 | nanddev_pos_next_page(nand, pos: &iter->req.pos); |
953 | iter->dataleft -= iter->req.datalen; |
954 | iter->req.databuf.in += iter->req.datalen; |
955 | iter->oobleft -= iter->req.ooblen; |
956 | iter->req.oobbuf.in += iter->req.ooblen; |
957 | iter->req.dataoffs = 0; |
958 | iter->req.ooboffs = 0; |
959 | iter->req.datalen = min_t(unsigned int, nand->memorg.pagesize, |
960 | iter->dataleft); |
961 | iter->req.ooblen = min_t(unsigned int, iter->oobbytes_per_page, |
962 | iter->oobleft); |
963 | } |
964 | |
965 | /** |
966 | * nand_io_iter_end - Should end iteration or not |
967 | * @nand: NAND device |
968 | * @iter: NAND I/O iterator |
969 | * |
970 | * Check whether @iter has reached the end of the NAND portion it was asked to |
971 | * iterate on or not. |
972 | * |
973 | * Return: true if @iter has reached the end of the iteration request, false |
974 | * otherwise. |
975 | */ |
976 | static inline bool nanddev_io_iter_end(struct nand_device *nand, |
977 | const struct nand_io_iter *iter) |
978 | { |
979 | if (iter->dataleft || iter->oobleft) |
980 | return false; |
981 | |
982 | return true; |
983 | } |
984 | |
985 | /** |
986 | * nand_io_for_each_page - Iterate over all NAND pages contained in an MTD I/O |
987 | * request |
988 | * @nand: NAND device |
989 | * @start: start address to read/write from |
990 | * @req: MTD I/O request |
991 | * @iter: NAND I/O iterator |
992 | * |
993 | * Should be used for iterate over pages that are contained in an MTD request. |
994 | */ |
995 | #define nanddev_io_for_each_page(nand, type, start, req, iter) \ |
996 | for (nanddev_io_iter_init(nand, type, start, req, iter); \ |
997 | !nanddev_io_iter_end(nand, iter); \ |
998 | nanddev_io_iter_next_page(nand, iter)) |
999 | |
1000 | bool nanddev_isbad(struct nand_device *nand, const struct nand_pos *pos); |
1001 | bool nanddev_isreserved(struct nand_device *nand, const struct nand_pos *pos); |
1002 | int nanddev_markbad(struct nand_device *nand, const struct nand_pos *pos); |
1003 | |
1004 | /* ECC related functions */ |
1005 | int nanddev_ecc_engine_init(struct nand_device *nand); |
1006 | void nanddev_ecc_engine_cleanup(struct nand_device *nand); |
1007 | |
1008 | static inline void *nand_to_ecc_ctx(struct nand_device *nand) |
1009 | { |
1010 | return nand->ecc.ctx.priv; |
1011 | } |
1012 | |
1013 | /* BBT related functions */ |
1014 | enum nand_bbt_block_status { |
1015 | NAND_BBT_BLOCK_STATUS_UNKNOWN, |
1016 | NAND_BBT_BLOCK_GOOD, |
1017 | NAND_BBT_BLOCK_WORN, |
1018 | NAND_BBT_BLOCK_RESERVED, |
1019 | NAND_BBT_BLOCK_FACTORY_BAD, |
1020 | NAND_BBT_BLOCK_NUM_STATUS, |
1021 | }; |
1022 | |
1023 | int nanddev_bbt_init(struct nand_device *nand); |
1024 | void nanddev_bbt_cleanup(struct nand_device *nand); |
1025 | int nanddev_bbt_update(struct nand_device *nand); |
1026 | int nanddev_bbt_get_block_status(const struct nand_device *nand, |
1027 | unsigned int entry); |
1028 | int nanddev_bbt_set_block_status(struct nand_device *nand, unsigned int entry, |
1029 | enum nand_bbt_block_status status); |
1030 | int nanddev_bbt_markbad(struct nand_device *nand, unsigned int block); |
1031 | |
1032 | /** |
1033 | * nanddev_bbt_pos_to_entry() - Convert a NAND position into a BBT entry |
1034 | * @nand: NAND device |
1035 | * @pos: the NAND position we want to get BBT entry for |
1036 | * |
1037 | * Return the BBT entry used to store information about the eraseblock pointed |
1038 | * by @pos. |
1039 | * |
1040 | * Return: the BBT entry storing information about eraseblock pointed by @pos. |
1041 | */ |
1042 | static inline unsigned int nanddev_bbt_pos_to_entry(struct nand_device *nand, |
1043 | const struct nand_pos *pos) |
1044 | { |
1045 | return pos->eraseblock + |
1046 | ((pos->lun + (pos->target * nand->memorg.luns_per_target)) * |
1047 | nand->memorg.eraseblocks_per_lun); |
1048 | } |
1049 | |
1050 | /** |
1051 | * nanddev_bbt_is_initialized() - Check if the BBT has been initialized |
1052 | * @nand: NAND device |
1053 | * |
1054 | * Return: true if the BBT has been initialized, false otherwise. |
1055 | */ |
1056 | static inline bool nanddev_bbt_is_initialized(struct nand_device *nand) |
1057 | { |
1058 | return !!nand->bbt.cache; |
1059 | } |
1060 | |
1061 | /* MTD -> NAND helper functions. */ |
1062 | int nanddev_mtd_erase(struct mtd_info *mtd, struct erase_info *einfo); |
1063 | int nanddev_mtd_max_bad_blocks(struct mtd_info *mtd, loff_t offs, size_t len); |
1064 | |
1065 | #endif /* __LINUX_MTD_NAND_H */ |
1066 | |