.. | .. |
---|
12 | 12 | |
---|
13 | 13 | #include <linux/mtd/mtd.h> |
---|
14 | 14 | |
---|
| 15 | +struct nand_device; |
---|
| 16 | + |
---|
15 | 17 | /** |
---|
16 | 18 | * struct nand_memory_organization - Memory organization structure |
---|
17 | 19 | * @bits_per_cell: number of bits per NAND cell |
---|
.. | .. |
---|
19 | 21 | * @oobsize: OOB area size |
---|
20 | 22 | * @pages_per_eraseblock: number of pages per eraseblock |
---|
21 | 23 | * @eraseblocks_per_lun: number of eraseblocks per LUN (Logical Unit Number) |
---|
| 24 | + * @max_bad_eraseblocks_per_lun: maximum number of eraseblocks per LUN |
---|
22 | 25 | * @planes_per_lun: number of planes per LUN |
---|
23 | 26 | * @luns_per_target: number of LUN per target (target is a synonym for die) |
---|
24 | 27 | * @ntargets: total number of targets exposed by the NAND device |
---|
.. | .. |
---|
29 | 32 | unsigned int oobsize; |
---|
30 | 33 | unsigned int pages_per_eraseblock; |
---|
31 | 34 | unsigned int eraseblocks_per_lun; |
---|
| 35 | + unsigned int max_bad_eraseblocks_per_lun; |
---|
32 | 36 | unsigned int planes_per_lun; |
---|
33 | 37 | unsigned int luns_per_target; |
---|
34 | 38 | unsigned int ntargets; |
---|
35 | 39 | }; |
---|
36 | 40 | |
---|
37 | | -#define NAND_MEMORG(bpc, ps, os, ppe, epl, ppl, lpt, nt) \ |
---|
| 41 | +#define NAND_MEMORG(bpc, ps, os, ppe, epl, mbb, ppl, lpt, nt) \ |
---|
38 | 42 | { \ |
---|
39 | 43 | .bits_per_cell = (bpc), \ |
---|
40 | 44 | .pagesize = (ps), \ |
---|
41 | 45 | .oobsize = (os), \ |
---|
42 | 46 | .pages_per_eraseblock = (ppe), \ |
---|
43 | 47 | .eraseblocks_per_lun = (epl), \ |
---|
| 48 | + .max_bad_eraseblocks_per_lun = (mbb), \ |
---|
44 | 49 | .planes_per_lun = (ppl), \ |
---|
45 | 50 | .luns_per_target = (lpt), \ |
---|
46 | 51 | .ntargets = (nt), \ |
---|
.. | .. |
---|
78 | 83 | }; |
---|
79 | 84 | |
---|
80 | 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 | +/** |
---|
81 | 96 | * struct nand_page_io_req - NAND I/O request object |
---|
| 97 | + * @type: the type of page I/O: read or write |
---|
82 | 98 | * @pos: the position this I/O request is targeting |
---|
83 | 99 | * @dataoffs: the offset within the page |
---|
84 | 100 | * @datalen: number of data bytes to read from/write to this page |
---|
.. | .. |
---|
94 | 110 | * specific commands/operations. |
---|
95 | 111 | */ |
---|
96 | 112 | struct nand_page_io_req { |
---|
| 113 | + enum nand_page_io_req_type type; |
---|
97 | 114 | struct nand_pos pos; |
---|
98 | 115 | unsigned int dataoffs; |
---|
99 | 116 | unsigned int datalen; |
---|
.. | .. |
---|
110 | 127 | int mode; |
---|
111 | 128 | }; |
---|
112 | 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 | + |
---|
113 | 134 | /** |
---|
114 | | - * struct nand_ecc_req - NAND ECC requirements |
---|
115 | | - * @strength: ECC strength |
---|
116 | | - * @step_size: ECC step/block size |
---|
| 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 |
---|
117 | 141 | */ |
---|
118 | | -struct nand_ecc_req { |
---|
| 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; |
---|
119 | 191 | unsigned int strength; |
---|
120 | 192 | unsigned int step_size; |
---|
| 193 | + unsigned int flags; |
---|
121 | 194 | }; |
---|
122 | 195 | |
---|
123 | 196 | #define NAND_ECCREQ(str, stp) { .strength = (str), .step_size = (stp) } |
---|
124 | 197 | |
---|
| 198 | +/* NAND ECC misc flags */ |
---|
| 199 | +#define NAND_ECC_MAXIMIZE_STRENGTH BIT(0) |
---|
| 200 | + |
---|
| 201 | +/* nand_bbt option */ |
---|
| 202 | +#define NANDDEV_BBT_SCANNED BIT(0) |
---|
| 203 | + |
---|
| 204 | +/* The maximum number of blocks to scan for a bbt */ |
---|
| 205 | +#define NANDDEV_BBT_SCAN_MAXBLOCKS 4 |
---|
| 206 | + |
---|
125 | 207 | /** |
---|
126 | 208 | * struct nand_bbt - bad block table object |
---|
127 | 209 | * @cache: in memory BBT cache |
---|
| 210 | + * @option: the option of BBT |
---|
| 211 | + * @version: current memory BBT cache version |
---|
128 | 212 | */ |
---|
129 | 213 | struct nand_bbt { |
---|
130 | 214 | unsigned long *cache; |
---|
| 215 | +#ifdef CONFIG_MTD_NAND_BBT_USING_FLASH |
---|
| 216 | + unsigned int option; |
---|
| 217 | + unsigned int version; |
---|
| 218 | +#endif |
---|
131 | 219 | }; |
---|
132 | | - |
---|
133 | | -struct nand_device; |
---|
134 | 220 | |
---|
135 | 221 | /** |
---|
136 | 222 | * struct nand_ops - NAND operations |
---|
.. | .. |
---|
155 | 241 | }; |
---|
156 | 242 | |
---|
157 | 243 | /** |
---|
| 244 | + * struct nand_ecc_context - Context for the ECC engine |
---|
| 245 | + * @conf: basic ECC engine parameters |
---|
| 246 | + * @total: total number of bytes used for storing ECC codes, this is used by |
---|
| 247 | + * generic OOB layouts |
---|
| 248 | + * @priv: ECC engine driver private data |
---|
| 249 | + */ |
---|
| 250 | +struct nand_ecc_context { |
---|
| 251 | + struct nand_ecc_props conf; |
---|
| 252 | + unsigned int total; |
---|
| 253 | + void *priv; |
---|
| 254 | +}; |
---|
| 255 | + |
---|
| 256 | +/** |
---|
| 257 | + * struct nand_ecc_engine_ops - ECC engine operations |
---|
| 258 | + * @init_ctx: given a desired user configuration for the pointed NAND device, |
---|
| 259 | + * requests the ECC engine driver to setup a configuration with |
---|
| 260 | + * values it supports. |
---|
| 261 | + * @cleanup_ctx: clean the context initialized by @init_ctx. |
---|
| 262 | + * @prepare_io_req: is called before reading/writing a page to prepare the I/O |
---|
| 263 | + * request to be performed with ECC correction. |
---|
| 264 | + * @finish_io_req: is called after reading/writing a page to terminate the I/O |
---|
| 265 | + * request and ensure proper ECC correction. |
---|
| 266 | + */ |
---|
| 267 | +struct nand_ecc_engine_ops { |
---|
| 268 | + int (*init_ctx)(struct nand_device *nand); |
---|
| 269 | + void (*cleanup_ctx)(struct nand_device *nand); |
---|
| 270 | + int (*prepare_io_req)(struct nand_device *nand, |
---|
| 271 | + struct nand_page_io_req *req); |
---|
| 272 | + int (*finish_io_req)(struct nand_device *nand, |
---|
| 273 | + struct nand_page_io_req *req); |
---|
| 274 | +}; |
---|
| 275 | + |
---|
| 276 | +/** |
---|
| 277 | + * struct nand_ecc_engine - ECC engine abstraction for NAND devices |
---|
| 278 | + * @ops: ECC engine operations |
---|
| 279 | + */ |
---|
| 280 | +struct nand_ecc_engine { |
---|
| 281 | + struct nand_ecc_engine_ops *ops; |
---|
| 282 | +}; |
---|
| 283 | + |
---|
| 284 | +void of_get_nand_ecc_user_config(struct nand_device *nand); |
---|
| 285 | +int nand_ecc_init_ctx(struct nand_device *nand); |
---|
| 286 | +void nand_ecc_cleanup_ctx(struct nand_device *nand); |
---|
| 287 | +int nand_ecc_prepare_io_req(struct nand_device *nand, |
---|
| 288 | + struct nand_page_io_req *req); |
---|
| 289 | +int nand_ecc_finish_io_req(struct nand_device *nand, |
---|
| 290 | + struct nand_page_io_req *req); |
---|
| 291 | +bool nand_ecc_is_strong_enough(struct nand_device *nand); |
---|
| 292 | + |
---|
| 293 | +/** |
---|
| 294 | + * struct nand_ecc - Information relative to the ECC |
---|
| 295 | + * @defaults: Default values, depend on the underlying subsystem |
---|
| 296 | + * @requirements: ECC requirements from the NAND chip perspective |
---|
| 297 | + * @user_conf: User desires in terms of ECC parameters |
---|
| 298 | + * @ctx: ECC context for the ECC engine, derived from the device @requirements |
---|
| 299 | + * the @user_conf and the @defaults |
---|
| 300 | + * @ondie_engine: On-die ECC engine reference, if any |
---|
| 301 | + * @engine: ECC engine actually bound |
---|
| 302 | + */ |
---|
| 303 | +struct nand_ecc { |
---|
| 304 | + struct nand_ecc_props defaults; |
---|
| 305 | + struct nand_ecc_props requirements; |
---|
| 306 | + struct nand_ecc_props user_conf; |
---|
| 307 | + struct nand_ecc_context ctx; |
---|
| 308 | + struct nand_ecc_engine *ondie_engine; |
---|
| 309 | + struct nand_ecc_engine *engine; |
---|
| 310 | +}; |
---|
| 311 | + |
---|
| 312 | +/** |
---|
158 | 313 | * struct nand_device - NAND device |
---|
159 | 314 | * @mtd: MTD instance attached to the NAND device |
---|
160 | 315 | * @memorg: memory layout |
---|
161 | | - * @eccreq: ECC requirements |
---|
| 316 | + * @ecc: NAND ECC object attached to the NAND device |
---|
162 | 317 | * @rowconv: position to row address converter |
---|
163 | 318 | * @bbt: bad block table info |
---|
164 | 319 | * @ops: NAND operations attached to the NAND device |
---|
.. | .. |
---|
166 | 321 | * Generic NAND object. Specialized NAND layers (raw NAND, SPI NAND, OneNAND) |
---|
167 | 322 | * should declare their own NAND object embedding a nand_device struct (that's |
---|
168 | 323 | * how inheritance is done). |
---|
169 | | - * struct_nand_device->memorg and struct_nand_device->eccreq should be filled |
---|
170 | | - * at device detection time to reflect the NAND device |
---|
| 324 | + * struct_nand_device->memorg and struct_nand_device->ecc.requirements should |
---|
| 325 | + * be filled at device detection time to reflect the NAND device |
---|
171 | 326 | * capabilities/requirements. Once this is done nanddev_init() can be called. |
---|
172 | 327 | * It will take care of converting NAND information into MTD ones, which means |
---|
173 | 328 | * the specialized NAND layers should never manually tweak |
---|
.. | .. |
---|
176 | 331 | struct nand_device { |
---|
177 | 332 | struct mtd_info mtd; |
---|
178 | 333 | struct nand_memory_organization memorg; |
---|
179 | | - struct nand_ecc_req eccreq; |
---|
| 334 | + struct nand_ecc ecc; |
---|
180 | 335 | struct nand_row_converter rowconv; |
---|
181 | 336 | struct nand_bbt bbt; |
---|
182 | 337 | const struct nand_ops *ops; |
---|
.. | .. |
---|
269 | 424 | } |
---|
270 | 425 | |
---|
271 | 426 | /** |
---|
| 427 | + * nanddev_pages_per_target() - Get the number of pages per target |
---|
| 428 | + * @nand: NAND device |
---|
| 429 | + * |
---|
| 430 | + * Return: the number of pages per target. |
---|
| 431 | + */ |
---|
| 432 | +static inline unsigned int |
---|
| 433 | +nanddev_pages_per_target(const struct nand_device *nand) |
---|
| 434 | +{ |
---|
| 435 | + return nand->memorg.pages_per_eraseblock * |
---|
| 436 | + nand->memorg.eraseblocks_per_lun * |
---|
| 437 | + nand->memorg.luns_per_target; |
---|
| 438 | +} |
---|
| 439 | + |
---|
| 440 | +/** |
---|
272 | 441 | * nanddev_per_page_oobsize() - Get NAND erase block size |
---|
273 | 442 | * @nand: NAND device |
---|
274 | 443 | * |
---|
.. | .. |
---|
289 | 458 | nanddev_eraseblocks_per_lun(const struct nand_device *nand) |
---|
290 | 459 | { |
---|
291 | 460 | return nand->memorg.eraseblocks_per_lun; |
---|
| 461 | +} |
---|
| 462 | + |
---|
| 463 | +/** |
---|
| 464 | + * nanddev_eraseblocks_per_target() - Get the number of eraseblocks per target |
---|
| 465 | + * @nand: NAND device |
---|
| 466 | + * |
---|
| 467 | + * Return: the number of eraseblocks per target. |
---|
| 468 | + */ |
---|
| 469 | +static inline unsigned int |
---|
| 470 | +nanddev_eraseblocks_per_target(const struct nand_device *nand) |
---|
| 471 | +{ |
---|
| 472 | + return nand->memorg.eraseblocks_per_lun * nand->memorg.luns_per_target; |
---|
292 | 473 | } |
---|
293 | 474 | |
---|
294 | 475 | /** |
---|
.. | .. |
---|
317 | 498 | } |
---|
318 | 499 | |
---|
319 | 500 | /** |
---|
320 | | - * nanddev_neraseblocks() - Get the total number of erasablocks |
---|
| 501 | + * nanddev_neraseblocks() - Get the total number of eraseblocks |
---|
321 | 502 | * @nand: NAND device |
---|
322 | 503 | * |
---|
323 | 504 | * Return: the total number of eraseblocks exposed by @nand. |
---|
.. | .. |
---|
352 | 533 | nanddev_get_memorg(struct nand_device *nand) |
---|
353 | 534 | { |
---|
354 | 535 | return &nand->memorg; |
---|
| 536 | +} |
---|
| 537 | + |
---|
| 538 | +/** |
---|
| 539 | + * nanddev_get_ecc_conf() - Extract the ECC configuration from a NAND device |
---|
| 540 | + * @nand: NAND device |
---|
| 541 | + */ |
---|
| 542 | +static inline const struct nand_ecc_props * |
---|
| 543 | +nanddev_get_ecc_conf(struct nand_device *nand) |
---|
| 544 | +{ |
---|
| 545 | + return &nand->ecc.ctx.conf; |
---|
| 546 | +} |
---|
| 547 | + |
---|
| 548 | +/** |
---|
| 549 | + * nanddev_get_ecc_requirements() - Extract the ECC requirements from a NAND |
---|
| 550 | + * device |
---|
| 551 | + * @nand: NAND device |
---|
| 552 | + */ |
---|
| 553 | +static inline const struct nand_ecc_props * |
---|
| 554 | +nanddev_get_ecc_requirements(struct nand_device *nand) |
---|
| 555 | +{ |
---|
| 556 | + return &nand->ecc.requirements; |
---|
| 557 | +} |
---|
| 558 | + |
---|
| 559 | +/** |
---|
| 560 | + * nanddev_set_ecc_requirements() - Assign the ECC requirements of a NAND |
---|
| 561 | + * device |
---|
| 562 | + * @nand: NAND device |
---|
| 563 | + * @reqs: Requirements |
---|
| 564 | + */ |
---|
| 565 | +static inline void |
---|
| 566 | +nanddev_set_ecc_requirements(struct nand_device *nand, |
---|
| 567 | + const struct nand_ecc_props *reqs) |
---|
| 568 | +{ |
---|
| 569 | + nand->ecc.requirements = *reqs; |
---|
355 | 570 | } |
---|
356 | 571 | |
---|
357 | 572 | int nanddev_init(struct nand_device *nand, const struct nand_ops *ops, |
---|
.. | .. |
---|
595 | 810 | * layer. |
---|
596 | 811 | */ |
---|
597 | 812 | static inline void nanddev_io_iter_init(struct nand_device *nand, |
---|
| 813 | + enum nand_page_io_req_type reqtype, |
---|
598 | 814 | loff_t offs, struct mtd_oob_ops *req, |
---|
599 | 815 | struct nand_io_iter *iter) |
---|
600 | 816 | { |
---|
601 | 817 | struct mtd_info *mtd = nanddev_to_mtd(nand); |
---|
602 | 818 | |
---|
| 819 | + iter->req.type = reqtype; |
---|
603 | 820 | iter->req.mode = req->mode; |
---|
604 | 821 | iter->req.dataoffs = nanddev_offs_to_pos(nand, offs, &iter->req.pos); |
---|
605 | 822 | iter->req.ooboffs = req->ooboffs; |
---|
.. | .. |
---|
669 | 886 | * |
---|
670 | 887 | * Should be used for iterate over pages that are contained in an MTD request. |
---|
671 | 888 | */ |
---|
672 | | -#define nanddev_io_for_each_page(nand, start, req, iter) \ |
---|
673 | | - for (nanddev_io_iter_init(nand, start, req, iter); \ |
---|
| 889 | +#define nanddev_io_for_each_page(nand, type, start, req, iter) \ |
---|
| 890 | + for (nanddev_io_iter_init(nand, type, start, req, iter); \ |
---|
674 | 891 | !nanddev_io_iter_end(nand, iter); \ |
---|
675 | 892 | nanddev_io_iter_next_page(nand, iter)) |
---|
676 | 893 | |
---|
.. | .. |
---|
729 | 946 | |
---|
730 | 947 | /* MTD -> NAND helper functions. */ |
---|
731 | 948 | int nanddev_mtd_erase(struct mtd_info *mtd, struct erase_info *einfo); |
---|
| 949 | +int nanddev_mtd_max_bad_blocks(struct mtd_info *mtd, loff_t offs, size_t len); |
---|
732 | 950 | |
---|
733 | 951 | #endif /* __LINUX_MTD_NAND_H */ |
---|