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