diff options
| author | Brian Norris <computersforpeace@gmail.com> | 2016-10-08 15:23:37 -0400 |
|---|---|---|
| committer | Brian Norris <computersforpeace@gmail.com> | 2016-10-08 23:56:54 -0400 |
| commit | 69db4aa44fdd8befc2eccd1313d841c5128c385c (patch) | |
| tree | 1b84be76e9497231ed8027cf2a22b79fab64a87c /include | |
| parent | f5b88de284932def6850e976c18d25940c1b2c3d (diff) | |
| parent | 477b0229ac9bc275f6f8d2c27a2d08b246fccd0e (diff) | |
Merge tag '4.9/mtd-pairing-scheme' of github.com:linux-nand/linux
Introduction of the MTD pairing scheme concept.
Diffstat (limited to 'include')
| -rw-r--r-- | include/linux/mtd/mtd.h | 107 |
1 files changed, 107 insertions, 0 deletions
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h index 29a170612203..13f8052b9ff9 100644 --- a/include/linux/mtd/mtd.h +++ b/include/linux/mtd/mtd.h | |||
| @@ -127,6 +127,82 @@ struct mtd_ooblayout_ops { | |||
| 127 | struct mtd_oob_region *oobfree); | 127 | struct mtd_oob_region *oobfree); |
| 128 | }; | 128 | }; |
| 129 | 129 | ||
| 130 | /** | ||
| 131 | * struct mtd_pairing_info - page pairing information | ||
| 132 | * | ||
| 133 | * @pair: pair id | ||
| 134 | * @group: group id | ||
| 135 | * | ||
| 136 | * The term "pair" is used here, even though TLC NANDs might group pages by 3 | ||
| 137 | * (3 bits in a single cell). A pair should regroup all pages that are sharing | ||
| 138 | * the same cell. Pairs are then indexed in ascending order. | ||
| 139 | * | ||
| 140 | * @group is defining the position of a page in a given pair. It can also be | ||
| 141 | * seen as the bit position in the cell: page attached to bit 0 belongs to | ||
| 142 | * group 0, page attached to bit 1 belongs to group 1, etc. | ||
| 143 | * | ||
| 144 | * Example: | ||
| 145 | * The H27UCG8T2BTR-BC datasheet describes the following pairing scheme: | ||
| 146 | * | ||
| 147 | * group-0 group-1 | ||
| 148 | * | ||
| 149 | * pair-0 page-0 page-4 | ||
| 150 | * pair-1 page-1 page-5 | ||
| 151 | * pair-2 page-2 page-8 | ||
| 152 | * ... | ||
| 153 | * pair-127 page-251 page-255 | ||
| 154 | * | ||
| 155 | * | ||
| 156 | * Note that the "group" and "pair" terms were extracted from Samsung and | ||
| 157 | * Hynix datasheets, and might be referenced under other names in other | ||
| 158 | * datasheets (Micron is describing this concept as "shared pages"). | ||
| 159 | */ | ||
| 160 | struct mtd_pairing_info { | ||
| 161 | int pair; | ||
| 162 | int group; | ||
| 163 | }; | ||
| 164 | |||
| 165 | /** | ||
| 166 | * struct mtd_pairing_scheme - page pairing scheme description | ||
| 167 | * | ||
| 168 | * @ngroups: number of groups. Should be related to the number of bits | ||
| 169 | * per cell. | ||
| 170 | * @get_info: converts a write-unit (page number within an erase block) into | ||
| 171 | * mtd_pairing information (pair + group). This function should | ||
| 172 | * fill the info parameter based on the wunit index or return | ||
| 173 | * -EINVAL if the wunit parameter is invalid. | ||
| 174 | * @get_wunit: converts pairing information into a write-unit (page) number. | ||
| 175 | * This function should return the wunit index pointed by the | ||
| 176 | * pairing information described in the info argument. It should | ||
| 177 | * return -EINVAL, if there's no wunit corresponding to the | ||
| 178 | * passed pairing information. | ||
| 179 | * | ||
| 180 | * See mtd_pairing_info documentation for a detailed explanation of the | ||
| 181 | * pair and group concepts. | ||
| 182 | * | ||
| 183 | * The mtd_pairing_scheme structure provides a generic solution to represent | ||
| 184 | * NAND page pairing scheme. Instead of exposing two big tables to do the | ||
| 185 | * write-unit <-> (pair + group) conversions, we ask the MTD drivers to | ||
| 186 | * implement the ->get_info() and ->get_wunit() functions. | ||
| 187 | * | ||
| 188 | * MTD users will then be able to query these information by using the | ||
| 189 | * mtd_pairing_info_to_wunit() and mtd_wunit_to_pairing_info() helpers. | ||
| 190 | * | ||
| 191 | * @ngroups is here to help MTD users iterating over all the pages in a | ||
| 192 | * given pair. This value can be retrieved by MTD users using the | ||
| 193 | * mtd_pairing_groups() helper. | ||
| 194 | * | ||
| 195 | * Examples are given in the mtd_pairing_info_to_wunit() and | ||
| 196 | * mtd_wunit_to_pairing_info() documentation. | ||
| 197 | */ | ||
| 198 | struct mtd_pairing_scheme { | ||
| 199 | int ngroups; | ||
| 200 | int (*get_info)(struct mtd_info *mtd, int wunit, | ||
| 201 | struct mtd_pairing_info *info); | ||
| 202 | int (*get_wunit)(struct mtd_info *mtd, | ||
| 203 | const struct mtd_pairing_info *info); | ||
| 204 | }; | ||
| 205 | |||
| 130 | struct module; /* only needed for owner field in mtd_info */ | 206 | struct module; /* only needed for owner field in mtd_info */ |
| 131 | 207 | ||
| 132 | struct mtd_info { | 208 | struct mtd_info { |
| @@ -188,6 +264,9 @@ struct mtd_info { | |||
| 188 | /* OOB layout description */ | 264 | /* OOB layout description */ |
| 189 | const struct mtd_ooblayout_ops *ooblayout; | 265 | const struct mtd_ooblayout_ops *ooblayout; |
| 190 | 266 | ||
| 267 | /* NAND pairing scheme, only provided for MLC/TLC NANDs */ | ||
| 268 | const struct mtd_pairing_scheme *pairing; | ||
| 269 | |||
| 191 | /* the ecc step size. */ | 270 | /* the ecc step size. */ |
| 192 | unsigned int ecc_step_size; | 271 | unsigned int ecc_step_size; |
| 193 | 272 | ||
| @@ -296,6 +375,12 @@ static inline void mtd_set_ooblayout(struct mtd_info *mtd, | |||
| 296 | mtd->ooblayout = ooblayout; | 375 | mtd->ooblayout = ooblayout; |
| 297 | } | 376 | } |
| 298 | 377 | ||
| 378 | static inline void mtd_set_pairing_scheme(struct mtd_info *mtd, | ||
| 379 | const struct mtd_pairing_scheme *pairing) | ||
| 380 | { | ||
| 381 | mtd->pairing = pairing; | ||
| 382 | } | ||
| 383 | |||
| 299 | static inline void mtd_set_of_node(struct mtd_info *mtd, | 384 | static inline void mtd_set_of_node(struct mtd_info *mtd, |
| 300 | struct device_node *np) | 385 | struct device_node *np) |
| 301 | { | 386 | { |
| @@ -312,6 +397,11 @@ static inline int mtd_oobavail(struct mtd_info *mtd, struct mtd_oob_ops *ops) | |||
| 312 | return ops->mode == MTD_OPS_AUTO_OOB ? mtd->oobavail : mtd->oobsize; | 397 | return ops->mode == MTD_OPS_AUTO_OOB ? mtd->oobavail : mtd->oobsize; |
| 313 | } | 398 | } |
| 314 | 399 | ||
| 400 | int mtd_wunit_to_pairing_info(struct mtd_info *mtd, int wunit, | ||
| 401 | struct mtd_pairing_info *info); | ||
| 402 | int mtd_pairing_info_to_wunit(struct mtd_info *mtd, | ||
| 403 | const struct mtd_pairing_info *info); | ||
| 404 | int mtd_pairing_groups(struct mtd_info *mtd); | ||
| 315 | int mtd_erase(struct mtd_info *mtd, struct erase_info *instr); | 405 | int mtd_erase(struct mtd_info *mtd, struct erase_info *instr); |
| 316 | int mtd_point(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, | 406 | int mtd_point(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, |
| 317 | void **virt, resource_size_t *phys); | 407 | void **virt, resource_size_t *phys); |
| @@ -397,6 +487,23 @@ static inline uint32_t mtd_mod_by_ws(uint64_t sz, struct mtd_info *mtd) | |||
| 397 | return do_div(sz, mtd->writesize); | 487 | return do_div(sz, mtd->writesize); |
| 398 | } | 488 | } |
| 399 | 489 | ||
| 490 | static inline int mtd_wunit_per_eb(struct mtd_info *mtd) | ||
| 491 | { | ||
| 492 | return mtd->erasesize / mtd->writesize; | ||
| 493 | } | ||
| 494 | |||
| 495 | static inline int mtd_offset_to_wunit(struct mtd_info *mtd, loff_t offs) | ||
| 496 | { | ||
| 497 | return mtd_div_by_ws(mtd_mod_by_eb(offs, mtd), mtd); | ||
| 498 | } | ||
| 499 | |||
| 500 | static inline loff_t mtd_wunit_to_offset(struct mtd_info *mtd, loff_t base, | ||
| 501 | int wunit) | ||
| 502 | { | ||
| 503 | return base + (wunit * mtd->writesize); | ||
| 504 | } | ||
| 505 | |||
| 506 | |||
| 400 | static inline int mtd_has_oob(const struct mtd_info *mtd) | 507 | static inline int mtd_has_oob(const struct mtd_info *mtd) |
| 401 | { | 508 | { |
| 402 | return mtd->_read_oob && mtd->_write_oob; | 509 | return mtd->_read_oob && mtd->_write_oob; |
