162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright © 1999-2010 David Woodhouse <dwmw2@infradead.org> et al. 462306a36Sopenharmony_ci */ 562306a36Sopenharmony_ci 662306a36Sopenharmony_ci#ifndef __MTD_MTD_H__ 762306a36Sopenharmony_ci#define __MTD_MTD_H__ 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#include <linux/types.h> 1062306a36Sopenharmony_ci#include <linux/uio.h> 1162306a36Sopenharmony_ci#include <linux/list.h> 1262306a36Sopenharmony_ci#include <linux/notifier.h> 1362306a36Sopenharmony_ci#include <linux/device.h> 1462306a36Sopenharmony_ci#include <linux/of.h> 1562306a36Sopenharmony_ci#include <linux/nvmem-provider.h> 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci#include <mtd/mtd-abi.h> 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci#include <asm/div64.h> 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci#define MTD_FAIL_ADDR_UNKNOWN -1LL 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_cistruct mtd_info; 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci/* 2662306a36Sopenharmony_ci * If the erase fails, fail_addr might indicate exactly which block failed. If 2762306a36Sopenharmony_ci * fail_addr = MTD_FAIL_ADDR_UNKNOWN, the failure was not at the device level 2862306a36Sopenharmony_ci * or was not specific to any particular block. 2962306a36Sopenharmony_ci */ 3062306a36Sopenharmony_cistruct erase_info { 3162306a36Sopenharmony_ci uint64_t addr; 3262306a36Sopenharmony_ci uint64_t len; 3362306a36Sopenharmony_ci uint64_t fail_addr; 3462306a36Sopenharmony_ci}; 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_cistruct mtd_erase_region_info { 3762306a36Sopenharmony_ci uint64_t offset; /* At which this region starts, from the beginning of the MTD */ 3862306a36Sopenharmony_ci uint32_t erasesize; /* For this region */ 3962306a36Sopenharmony_ci uint32_t numblocks; /* Number of blocks of erasesize in this region */ 4062306a36Sopenharmony_ci unsigned long *lockmap; /* If keeping bitmap of locks */ 4162306a36Sopenharmony_ci}; 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_cistruct mtd_req_stats { 4462306a36Sopenharmony_ci unsigned int uncorrectable_errors; 4562306a36Sopenharmony_ci unsigned int corrected_bitflips; 4662306a36Sopenharmony_ci unsigned int max_bitflips; 4762306a36Sopenharmony_ci}; 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ci/** 5062306a36Sopenharmony_ci * struct mtd_oob_ops - oob operation operands 5162306a36Sopenharmony_ci * @mode: operation mode 5262306a36Sopenharmony_ci * 5362306a36Sopenharmony_ci * @len: number of data bytes to write/read 5462306a36Sopenharmony_ci * 5562306a36Sopenharmony_ci * @retlen: number of data bytes written/read 5662306a36Sopenharmony_ci * 5762306a36Sopenharmony_ci * @ooblen: number of oob bytes to write/read 5862306a36Sopenharmony_ci * @oobretlen: number of oob bytes written/read 5962306a36Sopenharmony_ci * @ooboffs: offset of oob data in the oob area (only relevant when 6062306a36Sopenharmony_ci * mode = MTD_OPS_PLACE_OOB or MTD_OPS_RAW) 6162306a36Sopenharmony_ci * @datbuf: data buffer - if NULL only oob data are read/written 6262306a36Sopenharmony_ci * @oobbuf: oob data buffer 6362306a36Sopenharmony_ci * 6462306a36Sopenharmony_ci * Note, some MTD drivers do not allow you to write more than one OOB area at 6562306a36Sopenharmony_ci * one go. If you try to do that on such an MTD device, -EINVAL will be 6662306a36Sopenharmony_ci * returned. If you want to make your implementation portable on all kind of MTD 6762306a36Sopenharmony_ci * devices you should split the write request into several sub-requests when the 6862306a36Sopenharmony_ci * request crosses a page boundary. 6962306a36Sopenharmony_ci */ 7062306a36Sopenharmony_cistruct mtd_oob_ops { 7162306a36Sopenharmony_ci unsigned int mode; 7262306a36Sopenharmony_ci size_t len; 7362306a36Sopenharmony_ci size_t retlen; 7462306a36Sopenharmony_ci size_t ooblen; 7562306a36Sopenharmony_ci size_t oobretlen; 7662306a36Sopenharmony_ci uint32_t ooboffs; 7762306a36Sopenharmony_ci uint8_t *datbuf; 7862306a36Sopenharmony_ci uint8_t *oobbuf; 7962306a36Sopenharmony_ci struct mtd_req_stats *stats; 8062306a36Sopenharmony_ci}; 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci/** 8362306a36Sopenharmony_ci * struct mtd_oob_region - oob region definition 8462306a36Sopenharmony_ci * @offset: region offset 8562306a36Sopenharmony_ci * @length: region length 8662306a36Sopenharmony_ci * 8762306a36Sopenharmony_ci * This structure describes a region of the OOB area, and is used 8862306a36Sopenharmony_ci * to retrieve ECC or free bytes sections. 8962306a36Sopenharmony_ci * Each section is defined by an offset within the OOB area and a 9062306a36Sopenharmony_ci * length. 9162306a36Sopenharmony_ci */ 9262306a36Sopenharmony_cistruct mtd_oob_region { 9362306a36Sopenharmony_ci u32 offset; 9462306a36Sopenharmony_ci u32 length; 9562306a36Sopenharmony_ci}; 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci/* 9862306a36Sopenharmony_ci * struct mtd_ooblayout_ops - NAND OOB layout operations 9962306a36Sopenharmony_ci * @ecc: function returning an ECC region in the OOB area. 10062306a36Sopenharmony_ci * Should return -ERANGE if %section exceeds the total number of 10162306a36Sopenharmony_ci * ECC sections. 10262306a36Sopenharmony_ci * @free: function returning a free region in the OOB area. 10362306a36Sopenharmony_ci * Should return -ERANGE if %section exceeds the total number of 10462306a36Sopenharmony_ci * free sections. 10562306a36Sopenharmony_ci */ 10662306a36Sopenharmony_cistruct mtd_ooblayout_ops { 10762306a36Sopenharmony_ci int (*ecc)(struct mtd_info *mtd, int section, 10862306a36Sopenharmony_ci struct mtd_oob_region *oobecc); 10962306a36Sopenharmony_ci int (*free)(struct mtd_info *mtd, int section, 11062306a36Sopenharmony_ci struct mtd_oob_region *oobfree); 11162306a36Sopenharmony_ci}; 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci/** 11462306a36Sopenharmony_ci * struct mtd_pairing_info - page pairing information 11562306a36Sopenharmony_ci * 11662306a36Sopenharmony_ci * @pair: pair id 11762306a36Sopenharmony_ci * @group: group id 11862306a36Sopenharmony_ci * 11962306a36Sopenharmony_ci * The term "pair" is used here, even though TLC NANDs might group pages by 3 12062306a36Sopenharmony_ci * (3 bits in a single cell). A pair should regroup all pages that are sharing 12162306a36Sopenharmony_ci * the same cell. Pairs are then indexed in ascending order. 12262306a36Sopenharmony_ci * 12362306a36Sopenharmony_ci * @group is defining the position of a page in a given pair. It can also be 12462306a36Sopenharmony_ci * seen as the bit position in the cell: page attached to bit 0 belongs to 12562306a36Sopenharmony_ci * group 0, page attached to bit 1 belongs to group 1, etc. 12662306a36Sopenharmony_ci * 12762306a36Sopenharmony_ci * Example: 12862306a36Sopenharmony_ci * The H27UCG8T2BTR-BC datasheet describes the following pairing scheme: 12962306a36Sopenharmony_ci * 13062306a36Sopenharmony_ci * group-0 group-1 13162306a36Sopenharmony_ci * 13262306a36Sopenharmony_ci * pair-0 page-0 page-4 13362306a36Sopenharmony_ci * pair-1 page-1 page-5 13462306a36Sopenharmony_ci * pair-2 page-2 page-8 13562306a36Sopenharmony_ci * ... 13662306a36Sopenharmony_ci * pair-127 page-251 page-255 13762306a36Sopenharmony_ci * 13862306a36Sopenharmony_ci * 13962306a36Sopenharmony_ci * Note that the "group" and "pair" terms were extracted from Samsung and 14062306a36Sopenharmony_ci * Hynix datasheets, and might be referenced under other names in other 14162306a36Sopenharmony_ci * datasheets (Micron is describing this concept as "shared pages"). 14262306a36Sopenharmony_ci */ 14362306a36Sopenharmony_cistruct mtd_pairing_info { 14462306a36Sopenharmony_ci int pair; 14562306a36Sopenharmony_ci int group; 14662306a36Sopenharmony_ci}; 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci/** 14962306a36Sopenharmony_ci * struct mtd_pairing_scheme - page pairing scheme description 15062306a36Sopenharmony_ci * 15162306a36Sopenharmony_ci * @ngroups: number of groups. Should be related to the number of bits 15262306a36Sopenharmony_ci * per cell. 15362306a36Sopenharmony_ci * @get_info: converts a write-unit (page number within an erase block) into 15462306a36Sopenharmony_ci * mtd_pairing information (pair + group). This function should 15562306a36Sopenharmony_ci * fill the info parameter based on the wunit index or return 15662306a36Sopenharmony_ci * -EINVAL if the wunit parameter is invalid. 15762306a36Sopenharmony_ci * @get_wunit: converts pairing information into a write-unit (page) number. 15862306a36Sopenharmony_ci * This function should return the wunit index pointed by the 15962306a36Sopenharmony_ci * pairing information described in the info argument. It should 16062306a36Sopenharmony_ci * return -EINVAL, if there's no wunit corresponding to the 16162306a36Sopenharmony_ci * passed pairing information. 16262306a36Sopenharmony_ci * 16362306a36Sopenharmony_ci * See mtd_pairing_info documentation for a detailed explanation of the 16462306a36Sopenharmony_ci * pair and group concepts. 16562306a36Sopenharmony_ci * 16662306a36Sopenharmony_ci * The mtd_pairing_scheme structure provides a generic solution to represent 16762306a36Sopenharmony_ci * NAND page pairing scheme. Instead of exposing two big tables to do the 16862306a36Sopenharmony_ci * write-unit <-> (pair + group) conversions, we ask the MTD drivers to 16962306a36Sopenharmony_ci * implement the ->get_info() and ->get_wunit() functions. 17062306a36Sopenharmony_ci * 17162306a36Sopenharmony_ci * MTD users will then be able to query these information by using the 17262306a36Sopenharmony_ci * mtd_pairing_info_to_wunit() and mtd_wunit_to_pairing_info() helpers. 17362306a36Sopenharmony_ci * 17462306a36Sopenharmony_ci * @ngroups is here to help MTD users iterating over all the pages in a 17562306a36Sopenharmony_ci * given pair. This value can be retrieved by MTD users using the 17662306a36Sopenharmony_ci * mtd_pairing_groups() helper. 17762306a36Sopenharmony_ci * 17862306a36Sopenharmony_ci * Examples are given in the mtd_pairing_info_to_wunit() and 17962306a36Sopenharmony_ci * mtd_wunit_to_pairing_info() documentation. 18062306a36Sopenharmony_ci */ 18162306a36Sopenharmony_cistruct mtd_pairing_scheme { 18262306a36Sopenharmony_ci int ngroups; 18362306a36Sopenharmony_ci int (*get_info)(struct mtd_info *mtd, int wunit, 18462306a36Sopenharmony_ci struct mtd_pairing_info *info); 18562306a36Sopenharmony_ci int (*get_wunit)(struct mtd_info *mtd, 18662306a36Sopenharmony_ci const struct mtd_pairing_info *info); 18762306a36Sopenharmony_ci}; 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_cistruct module; /* only needed for owner field in mtd_info */ 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_ci/** 19262306a36Sopenharmony_ci * struct mtd_debug_info - debugging information for an MTD device. 19362306a36Sopenharmony_ci * 19462306a36Sopenharmony_ci * @dfs_dir: direntry object of the MTD device debugfs directory 19562306a36Sopenharmony_ci */ 19662306a36Sopenharmony_cistruct mtd_debug_info { 19762306a36Sopenharmony_ci struct dentry *dfs_dir; 19862306a36Sopenharmony_ci}; 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_ci/** 20162306a36Sopenharmony_ci * struct mtd_part - MTD partition specific fields 20262306a36Sopenharmony_ci * 20362306a36Sopenharmony_ci * @node: list node used to add an MTD partition to the parent partition list 20462306a36Sopenharmony_ci * @offset: offset of the partition relatively to the parent offset 20562306a36Sopenharmony_ci * @size: partition size. Should be equal to mtd->size unless 20662306a36Sopenharmony_ci * MTD_SLC_ON_MLC_EMULATION is set 20762306a36Sopenharmony_ci * @flags: original flags (before the mtdpart logic decided to tweak them based 20862306a36Sopenharmony_ci * on flash constraints, like eraseblock/pagesize alignment) 20962306a36Sopenharmony_ci * 21062306a36Sopenharmony_ci * This struct is embedded in mtd_info and contains partition-specific 21162306a36Sopenharmony_ci * properties/fields. 21262306a36Sopenharmony_ci */ 21362306a36Sopenharmony_cistruct mtd_part { 21462306a36Sopenharmony_ci struct list_head node; 21562306a36Sopenharmony_ci u64 offset; 21662306a36Sopenharmony_ci u64 size; 21762306a36Sopenharmony_ci u32 flags; 21862306a36Sopenharmony_ci}; 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_ci/** 22162306a36Sopenharmony_ci * struct mtd_master - MTD master specific fields 22262306a36Sopenharmony_ci * 22362306a36Sopenharmony_ci * @partitions_lock: lock protecting accesses to the partition list. Protects 22462306a36Sopenharmony_ci * not only the master partition list, but also all 22562306a36Sopenharmony_ci * sub-partitions. 22662306a36Sopenharmony_ci * @suspended: et to 1 when the device is suspended, 0 otherwise 22762306a36Sopenharmony_ci * 22862306a36Sopenharmony_ci * This struct is embedded in mtd_info and contains master-specific 22962306a36Sopenharmony_ci * properties/fields. The master is the root MTD device from the MTD partition 23062306a36Sopenharmony_ci * point of view. 23162306a36Sopenharmony_ci */ 23262306a36Sopenharmony_cistruct mtd_master { 23362306a36Sopenharmony_ci struct mutex partitions_lock; 23462306a36Sopenharmony_ci struct mutex chrdev_lock; 23562306a36Sopenharmony_ci unsigned int suspended : 1; 23662306a36Sopenharmony_ci}; 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_cistruct mtd_info { 23962306a36Sopenharmony_ci u_char type; 24062306a36Sopenharmony_ci uint32_t flags; 24162306a36Sopenharmony_ci uint64_t size; // Total size of the MTD 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_ci /* "Major" erase size for the device. Naïve users may take this 24462306a36Sopenharmony_ci * to be the only erase size available, or may use the more detailed 24562306a36Sopenharmony_ci * information below if they desire 24662306a36Sopenharmony_ci */ 24762306a36Sopenharmony_ci uint32_t erasesize; 24862306a36Sopenharmony_ci /* Minimal writable flash unit size. In case of NOR flash it is 1 (even 24962306a36Sopenharmony_ci * though individual bits can be cleared), in case of NAND flash it is 25062306a36Sopenharmony_ci * one NAND page (or half, or one-fourths of it), in case of ECC-ed NOR 25162306a36Sopenharmony_ci * it is of ECC block size, etc. It is illegal to have writesize = 0. 25262306a36Sopenharmony_ci * Any driver registering a struct mtd_info must ensure a writesize of 25362306a36Sopenharmony_ci * 1 or larger. 25462306a36Sopenharmony_ci */ 25562306a36Sopenharmony_ci uint32_t writesize; 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_ci /* 25862306a36Sopenharmony_ci * Size of the write buffer used by the MTD. MTD devices having a write 25962306a36Sopenharmony_ci * buffer can write multiple writesize chunks at a time. E.g. while 26062306a36Sopenharmony_ci * writing 4 * writesize bytes to a device with 2 * writesize bytes 26162306a36Sopenharmony_ci * buffer the MTD driver can (but doesn't have to) do 2 writesize 26262306a36Sopenharmony_ci * operations, but not 4. Currently, all NANDs have writebufsize 26362306a36Sopenharmony_ci * equivalent to writesize (NAND page size). Some NOR flashes do have 26462306a36Sopenharmony_ci * writebufsize greater than writesize. 26562306a36Sopenharmony_ci */ 26662306a36Sopenharmony_ci uint32_t writebufsize; 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_ci uint32_t oobsize; // Amount of OOB data per block (e.g. 16) 26962306a36Sopenharmony_ci uint32_t oobavail; // Available OOB bytes per block 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_ci /* 27262306a36Sopenharmony_ci * If erasesize is a power of 2 then the shift is stored in 27362306a36Sopenharmony_ci * erasesize_shift otherwise erasesize_shift is zero. Ditto writesize. 27462306a36Sopenharmony_ci */ 27562306a36Sopenharmony_ci unsigned int erasesize_shift; 27662306a36Sopenharmony_ci unsigned int writesize_shift; 27762306a36Sopenharmony_ci /* Masks based on erasesize_shift and writesize_shift */ 27862306a36Sopenharmony_ci unsigned int erasesize_mask; 27962306a36Sopenharmony_ci unsigned int writesize_mask; 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_ci /* 28262306a36Sopenharmony_ci * read ops return -EUCLEAN if max number of bitflips corrected on any 28362306a36Sopenharmony_ci * one region comprising an ecc step equals or exceeds this value. 28462306a36Sopenharmony_ci * Settable by driver, else defaults to ecc_strength. User can override 28562306a36Sopenharmony_ci * in sysfs. N.B. The meaning of the -EUCLEAN return code has changed; 28662306a36Sopenharmony_ci * see Documentation/ABI/testing/sysfs-class-mtd for more detail. 28762306a36Sopenharmony_ci */ 28862306a36Sopenharmony_ci unsigned int bitflip_threshold; 28962306a36Sopenharmony_ci 29062306a36Sopenharmony_ci /* Kernel-only stuff starts here. */ 29162306a36Sopenharmony_ci const char *name; 29262306a36Sopenharmony_ci int index; 29362306a36Sopenharmony_ci 29462306a36Sopenharmony_ci /* OOB layout description */ 29562306a36Sopenharmony_ci const struct mtd_ooblayout_ops *ooblayout; 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_ci /* NAND pairing scheme, only provided for MLC/TLC NANDs */ 29862306a36Sopenharmony_ci const struct mtd_pairing_scheme *pairing; 29962306a36Sopenharmony_ci 30062306a36Sopenharmony_ci /* the ecc step size. */ 30162306a36Sopenharmony_ci unsigned int ecc_step_size; 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_ci /* max number of correctible bit errors per ecc step */ 30462306a36Sopenharmony_ci unsigned int ecc_strength; 30562306a36Sopenharmony_ci 30662306a36Sopenharmony_ci /* Data for variable erase regions. If numeraseregions is zero, 30762306a36Sopenharmony_ci * it means that the whole device has erasesize as given above. 30862306a36Sopenharmony_ci */ 30962306a36Sopenharmony_ci int numeraseregions; 31062306a36Sopenharmony_ci struct mtd_erase_region_info *eraseregions; 31162306a36Sopenharmony_ci 31262306a36Sopenharmony_ci /* 31362306a36Sopenharmony_ci * Do not call via these pointers, use corresponding mtd_*() 31462306a36Sopenharmony_ci * wrappers instead. 31562306a36Sopenharmony_ci */ 31662306a36Sopenharmony_ci int (*_erase) (struct mtd_info *mtd, struct erase_info *instr); 31762306a36Sopenharmony_ci int (*_point) (struct mtd_info *mtd, loff_t from, size_t len, 31862306a36Sopenharmony_ci size_t *retlen, void **virt, resource_size_t *phys); 31962306a36Sopenharmony_ci int (*_unpoint) (struct mtd_info *mtd, loff_t from, size_t len); 32062306a36Sopenharmony_ci int (*_read) (struct mtd_info *mtd, loff_t from, size_t len, 32162306a36Sopenharmony_ci size_t *retlen, u_char *buf); 32262306a36Sopenharmony_ci int (*_write) (struct mtd_info *mtd, loff_t to, size_t len, 32362306a36Sopenharmony_ci size_t *retlen, const u_char *buf); 32462306a36Sopenharmony_ci int (*_panic_write) (struct mtd_info *mtd, loff_t to, size_t len, 32562306a36Sopenharmony_ci size_t *retlen, const u_char *buf); 32662306a36Sopenharmony_ci int (*_read_oob) (struct mtd_info *mtd, loff_t from, 32762306a36Sopenharmony_ci struct mtd_oob_ops *ops); 32862306a36Sopenharmony_ci int (*_write_oob) (struct mtd_info *mtd, loff_t to, 32962306a36Sopenharmony_ci struct mtd_oob_ops *ops); 33062306a36Sopenharmony_ci int (*_get_fact_prot_info) (struct mtd_info *mtd, size_t len, 33162306a36Sopenharmony_ci size_t *retlen, struct otp_info *buf); 33262306a36Sopenharmony_ci int (*_read_fact_prot_reg) (struct mtd_info *mtd, loff_t from, 33362306a36Sopenharmony_ci size_t len, size_t *retlen, u_char *buf); 33462306a36Sopenharmony_ci int (*_get_user_prot_info) (struct mtd_info *mtd, size_t len, 33562306a36Sopenharmony_ci size_t *retlen, struct otp_info *buf); 33662306a36Sopenharmony_ci int (*_read_user_prot_reg) (struct mtd_info *mtd, loff_t from, 33762306a36Sopenharmony_ci size_t len, size_t *retlen, u_char *buf); 33862306a36Sopenharmony_ci int (*_write_user_prot_reg) (struct mtd_info *mtd, loff_t to, 33962306a36Sopenharmony_ci size_t len, size_t *retlen, 34062306a36Sopenharmony_ci const u_char *buf); 34162306a36Sopenharmony_ci int (*_lock_user_prot_reg) (struct mtd_info *mtd, loff_t from, 34262306a36Sopenharmony_ci size_t len); 34362306a36Sopenharmony_ci int (*_erase_user_prot_reg) (struct mtd_info *mtd, loff_t from, 34462306a36Sopenharmony_ci size_t len); 34562306a36Sopenharmony_ci int (*_writev) (struct mtd_info *mtd, const struct kvec *vecs, 34662306a36Sopenharmony_ci unsigned long count, loff_t to, size_t *retlen); 34762306a36Sopenharmony_ci void (*_sync) (struct mtd_info *mtd); 34862306a36Sopenharmony_ci int (*_lock) (struct mtd_info *mtd, loff_t ofs, uint64_t len); 34962306a36Sopenharmony_ci int (*_unlock) (struct mtd_info *mtd, loff_t ofs, uint64_t len); 35062306a36Sopenharmony_ci int (*_is_locked) (struct mtd_info *mtd, loff_t ofs, uint64_t len); 35162306a36Sopenharmony_ci int (*_block_isreserved) (struct mtd_info *mtd, loff_t ofs); 35262306a36Sopenharmony_ci int (*_block_isbad) (struct mtd_info *mtd, loff_t ofs); 35362306a36Sopenharmony_ci int (*_block_markbad) (struct mtd_info *mtd, loff_t ofs); 35462306a36Sopenharmony_ci int (*_max_bad_blocks) (struct mtd_info *mtd, loff_t ofs, size_t len); 35562306a36Sopenharmony_ci int (*_suspend) (struct mtd_info *mtd); 35662306a36Sopenharmony_ci void (*_resume) (struct mtd_info *mtd); 35762306a36Sopenharmony_ci void (*_reboot) (struct mtd_info *mtd); 35862306a36Sopenharmony_ci /* 35962306a36Sopenharmony_ci * If the driver is something smart, like UBI, it may need to maintain 36062306a36Sopenharmony_ci * its own reference counting. The below functions are only for driver. 36162306a36Sopenharmony_ci */ 36262306a36Sopenharmony_ci int (*_get_device) (struct mtd_info *mtd); 36362306a36Sopenharmony_ci void (*_put_device) (struct mtd_info *mtd); 36462306a36Sopenharmony_ci 36562306a36Sopenharmony_ci /* 36662306a36Sopenharmony_ci * flag indicates a panic write, low level drivers can take appropriate 36762306a36Sopenharmony_ci * action if required to ensure writes go through 36862306a36Sopenharmony_ci */ 36962306a36Sopenharmony_ci bool oops_panic_write; 37062306a36Sopenharmony_ci 37162306a36Sopenharmony_ci struct notifier_block reboot_notifier; /* default mode before reboot */ 37262306a36Sopenharmony_ci 37362306a36Sopenharmony_ci /* ECC status information */ 37462306a36Sopenharmony_ci struct mtd_ecc_stats ecc_stats; 37562306a36Sopenharmony_ci /* Subpage shift (NAND) */ 37662306a36Sopenharmony_ci int subpage_sft; 37762306a36Sopenharmony_ci 37862306a36Sopenharmony_ci void *priv; 37962306a36Sopenharmony_ci 38062306a36Sopenharmony_ci struct module *owner; 38162306a36Sopenharmony_ci struct device dev; 38262306a36Sopenharmony_ci struct kref refcnt; 38362306a36Sopenharmony_ci struct mtd_debug_info dbg; 38462306a36Sopenharmony_ci struct nvmem_device *nvmem; 38562306a36Sopenharmony_ci struct nvmem_device *otp_user_nvmem; 38662306a36Sopenharmony_ci struct nvmem_device *otp_factory_nvmem; 38762306a36Sopenharmony_ci 38862306a36Sopenharmony_ci /* 38962306a36Sopenharmony_ci * Parent device from the MTD partition point of view. 39062306a36Sopenharmony_ci * 39162306a36Sopenharmony_ci * MTD masters do not have any parent, MTD partitions do. The parent 39262306a36Sopenharmony_ci * MTD device can itself be a partition. 39362306a36Sopenharmony_ci */ 39462306a36Sopenharmony_ci struct mtd_info *parent; 39562306a36Sopenharmony_ci 39662306a36Sopenharmony_ci /* List of partitions attached to this MTD device */ 39762306a36Sopenharmony_ci struct list_head partitions; 39862306a36Sopenharmony_ci 39962306a36Sopenharmony_ci struct mtd_part part; 40062306a36Sopenharmony_ci struct mtd_master master; 40162306a36Sopenharmony_ci}; 40262306a36Sopenharmony_ci 40362306a36Sopenharmony_cistatic inline struct mtd_info *mtd_get_master(struct mtd_info *mtd) 40462306a36Sopenharmony_ci{ 40562306a36Sopenharmony_ci while (mtd->parent) 40662306a36Sopenharmony_ci mtd = mtd->parent; 40762306a36Sopenharmony_ci 40862306a36Sopenharmony_ci return mtd; 40962306a36Sopenharmony_ci} 41062306a36Sopenharmony_ci 41162306a36Sopenharmony_cistatic inline u64 mtd_get_master_ofs(struct mtd_info *mtd, u64 ofs) 41262306a36Sopenharmony_ci{ 41362306a36Sopenharmony_ci while (mtd->parent) { 41462306a36Sopenharmony_ci ofs += mtd->part.offset; 41562306a36Sopenharmony_ci mtd = mtd->parent; 41662306a36Sopenharmony_ci } 41762306a36Sopenharmony_ci 41862306a36Sopenharmony_ci return ofs; 41962306a36Sopenharmony_ci} 42062306a36Sopenharmony_ci 42162306a36Sopenharmony_cistatic inline bool mtd_is_partition(const struct mtd_info *mtd) 42262306a36Sopenharmony_ci{ 42362306a36Sopenharmony_ci return mtd->parent; 42462306a36Sopenharmony_ci} 42562306a36Sopenharmony_ci 42662306a36Sopenharmony_cistatic inline bool mtd_has_partitions(const struct mtd_info *mtd) 42762306a36Sopenharmony_ci{ 42862306a36Sopenharmony_ci return !list_empty(&mtd->partitions); 42962306a36Sopenharmony_ci} 43062306a36Sopenharmony_ci 43162306a36Sopenharmony_ciint mtd_ooblayout_ecc(struct mtd_info *mtd, int section, 43262306a36Sopenharmony_ci struct mtd_oob_region *oobecc); 43362306a36Sopenharmony_ciint mtd_ooblayout_find_eccregion(struct mtd_info *mtd, int eccbyte, 43462306a36Sopenharmony_ci int *section, 43562306a36Sopenharmony_ci struct mtd_oob_region *oobregion); 43662306a36Sopenharmony_ciint mtd_ooblayout_get_eccbytes(struct mtd_info *mtd, u8 *eccbuf, 43762306a36Sopenharmony_ci const u8 *oobbuf, int start, int nbytes); 43862306a36Sopenharmony_ciint mtd_ooblayout_set_eccbytes(struct mtd_info *mtd, const u8 *eccbuf, 43962306a36Sopenharmony_ci u8 *oobbuf, int start, int nbytes); 44062306a36Sopenharmony_ciint mtd_ooblayout_free(struct mtd_info *mtd, int section, 44162306a36Sopenharmony_ci struct mtd_oob_region *oobfree); 44262306a36Sopenharmony_ciint mtd_ooblayout_get_databytes(struct mtd_info *mtd, u8 *databuf, 44362306a36Sopenharmony_ci const u8 *oobbuf, int start, int nbytes); 44462306a36Sopenharmony_ciint mtd_ooblayout_set_databytes(struct mtd_info *mtd, const u8 *databuf, 44562306a36Sopenharmony_ci u8 *oobbuf, int start, int nbytes); 44662306a36Sopenharmony_ciint mtd_ooblayout_count_freebytes(struct mtd_info *mtd); 44762306a36Sopenharmony_ciint mtd_ooblayout_count_eccbytes(struct mtd_info *mtd); 44862306a36Sopenharmony_ci 44962306a36Sopenharmony_cistatic inline void mtd_set_ooblayout(struct mtd_info *mtd, 45062306a36Sopenharmony_ci const struct mtd_ooblayout_ops *ooblayout) 45162306a36Sopenharmony_ci{ 45262306a36Sopenharmony_ci mtd->ooblayout = ooblayout; 45362306a36Sopenharmony_ci} 45462306a36Sopenharmony_ci 45562306a36Sopenharmony_cistatic inline void mtd_set_pairing_scheme(struct mtd_info *mtd, 45662306a36Sopenharmony_ci const struct mtd_pairing_scheme *pairing) 45762306a36Sopenharmony_ci{ 45862306a36Sopenharmony_ci mtd->pairing = pairing; 45962306a36Sopenharmony_ci} 46062306a36Sopenharmony_ci 46162306a36Sopenharmony_cistatic inline void mtd_set_of_node(struct mtd_info *mtd, 46262306a36Sopenharmony_ci struct device_node *np) 46362306a36Sopenharmony_ci{ 46462306a36Sopenharmony_ci mtd->dev.of_node = np; 46562306a36Sopenharmony_ci if (!mtd->name) 46662306a36Sopenharmony_ci of_property_read_string(np, "label", &mtd->name); 46762306a36Sopenharmony_ci} 46862306a36Sopenharmony_ci 46962306a36Sopenharmony_cistatic inline struct device_node *mtd_get_of_node(struct mtd_info *mtd) 47062306a36Sopenharmony_ci{ 47162306a36Sopenharmony_ci return dev_of_node(&mtd->dev); 47262306a36Sopenharmony_ci} 47362306a36Sopenharmony_ci 47462306a36Sopenharmony_cistatic inline u32 mtd_oobavail(struct mtd_info *mtd, struct mtd_oob_ops *ops) 47562306a36Sopenharmony_ci{ 47662306a36Sopenharmony_ci return ops->mode == MTD_OPS_AUTO_OOB ? mtd->oobavail : mtd->oobsize; 47762306a36Sopenharmony_ci} 47862306a36Sopenharmony_ci 47962306a36Sopenharmony_cistatic inline int mtd_max_bad_blocks(struct mtd_info *mtd, 48062306a36Sopenharmony_ci loff_t ofs, size_t len) 48162306a36Sopenharmony_ci{ 48262306a36Sopenharmony_ci struct mtd_info *master = mtd_get_master(mtd); 48362306a36Sopenharmony_ci 48462306a36Sopenharmony_ci if (!master->_max_bad_blocks) 48562306a36Sopenharmony_ci return -ENOTSUPP; 48662306a36Sopenharmony_ci 48762306a36Sopenharmony_ci if (mtd->size < (len + ofs) || ofs < 0) 48862306a36Sopenharmony_ci return -EINVAL; 48962306a36Sopenharmony_ci 49062306a36Sopenharmony_ci return master->_max_bad_blocks(master, mtd_get_master_ofs(mtd, ofs), 49162306a36Sopenharmony_ci len); 49262306a36Sopenharmony_ci} 49362306a36Sopenharmony_ci 49462306a36Sopenharmony_ciint mtd_wunit_to_pairing_info(struct mtd_info *mtd, int wunit, 49562306a36Sopenharmony_ci struct mtd_pairing_info *info); 49662306a36Sopenharmony_ciint mtd_pairing_info_to_wunit(struct mtd_info *mtd, 49762306a36Sopenharmony_ci const struct mtd_pairing_info *info); 49862306a36Sopenharmony_ciint mtd_pairing_groups(struct mtd_info *mtd); 49962306a36Sopenharmony_ciint mtd_erase(struct mtd_info *mtd, struct erase_info *instr); 50062306a36Sopenharmony_ciint mtd_point(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, 50162306a36Sopenharmony_ci void **virt, resource_size_t *phys); 50262306a36Sopenharmony_ciint mtd_unpoint(struct mtd_info *mtd, loff_t from, size_t len); 50362306a36Sopenharmony_ciunsigned long mtd_get_unmapped_area(struct mtd_info *mtd, unsigned long len, 50462306a36Sopenharmony_ci unsigned long offset, unsigned long flags); 50562306a36Sopenharmony_ciint mtd_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, 50662306a36Sopenharmony_ci u_char *buf); 50762306a36Sopenharmony_ciint mtd_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, 50862306a36Sopenharmony_ci const u_char *buf); 50962306a36Sopenharmony_ciint mtd_panic_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, 51062306a36Sopenharmony_ci const u_char *buf); 51162306a36Sopenharmony_ci 51262306a36Sopenharmony_ciint mtd_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops); 51362306a36Sopenharmony_ciint mtd_write_oob(struct mtd_info *mtd, loff_t to, struct mtd_oob_ops *ops); 51462306a36Sopenharmony_ci 51562306a36Sopenharmony_ciint mtd_get_fact_prot_info(struct mtd_info *mtd, size_t len, size_t *retlen, 51662306a36Sopenharmony_ci struct otp_info *buf); 51762306a36Sopenharmony_ciint mtd_read_fact_prot_reg(struct mtd_info *mtd, loff_t from, size_t len, 51862306a36Sopenharmony_ci size_t *retlen, u_char *buf); 51962306a36Sopenharmony_ciint mtd_get_user_prot_info(struct mtd_info *mtd, size_t len, size_t *retlen, 52062306a36Sopenharmony_ci struct otp_info *buf); 52162306a36Sopenharmony_ciint mtd_read_user_prot_reg(struct mtd_info *mtd, loff_t from, size_t len, 52262306a36Sopenharmony_ci size_t *retlen, u_char *buf); 52362306a36Sopenharmony_ciint mtd_write_user_prot_reg(struct mtd_info *mtd, loff_t to, size_t len, 52462306a36Sopenharmony_ci size_t *retlen, const u_char *buf); 52562306a36Sopenharmony_ciint mtd_lock_user_prot_reg(struct mtd_info *mtd, loff_t from, size_t len); 52662306a36Sopenharmony_ciint mtd_erase_user_prot_reg(struct mtd_info *mtd, loff_t from, size_t len); 52762306a36Sopenharmony_ci 52862306a36Sopenharmony_ciint mtd_writev(struct mtd_info *mtd, const struct kvec *vecs, 52962306a36Sopenharmony_ci unsigned long count, loff_t to, size_t *retlen); 53062306a36Sopenharmony_ci 53162306a36Sopenharmony_cistatic inline void mtd_sync(struct mtd_info *mtd) 53262306a36Sopenharmony_ci{ 53362306a36Sopenharmony_ci struct mtd_info *master = mtd_get_master(mtd); 53462306a36Sopenharmony_ci 53562306a36Sopenharmony_ci if (master->_sync) 53662306a36Sopenharmony_ci master->_sync(master); 53762306a36Sopenharmony_ci} 53862306a36Sopenharmony_ci 53962306a36Sopenharmony_ciint mtd_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len); 54062306a36Sopenharmony_ciint mtd_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len); 54162306a36Sopenharmony_ciint mtd_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len); 54262306a36Sopenharmony_ciint mtd_block_isreserved(struct mtd_info *mtd, loff_t ofs); 54362306a36Sopenharmony_ciint mtd_block_isbad(struct mtd_info *mtd, loff_t ofs); 54462306a36Sopenharmony_ciint mtd_block_markbad(struct mtd_info *mtd, loff_t ofs); 54562306a36Sopenharmony_ci 54662306a36Sopenharmony_cistatic inline int mtd_suspend(struct mtd_info *mtd) 54762306a36Sopenharmony_ci{ 54862306a36Sopenharmony_ci struct mtd_info *master = mtd_get_master(mtd); 54962306a36Sopenharmony_ci int ret; 55062306a36Sopenharmony_ci 55162306a36Sopenharmony_ci if (master->master.suspended) 55262306a36Sopenharmony_ci return 0; 55362306a36Sopenharmony_ci 55462306a36Sopenharmony_ci ret = master->_suspend ? master->_suspend(master) : 0; 55562306a36Sopenharmony_ci if (ret) 55662306a36Sopenharmony_ci return ret; 55762306a36Sopenharmony_ci 55862306a36Sopenharmony_ci master->master.suspended = 1; 55962306a36Sopenharmony_ci return 0; 56062306a36Sopenharmony_ci} 56162306a36Sopenharmony_ci 56262306a36Sopenharmony_cistatic inline void mtd_resume(struct mtd_info *mtd) 56362306a36Sopenharmony_ci{ 56462306a36Sopenharmony_ci struct mtd_info *master = mtd_get_master(mtd); 56562306a36Sopenharmony_ci 56662306a36Sopenharmony_ci if (!master->master.suspended) 56762306a36Sopenharmony_ci return; 56862306a36Sopenharmony_ci 56962306a36Sopenharmony_ci if (master->_resume) 57062306a36Sopenharmony_ci master->_resume(master); 57162306a36Sopenharmony_ci 57262306a36Sopenharmony_ci master->master.suspended = 0; 57362306a36Sopenharmony_ci} 57462306a36Sopenharmony_ci 57562306a36Sopenharmony_cistatic inline uint32_t mtd_div_by_eb(uint64_t sz, struct mtd_info *mtd) 57662306a36Sopenharmony_ci{ 57762306a36Sopenharmony_ci if (mtd->erasesize_shift) 57862306a36Sopenharmony_ci return sz >> mtd->erasesize_shift; 57962306a36Sopenharmony_ci do_div(sz, mtd->erasesize); 58062306a36Sopenharmony_ci return sz; 58162306a36Sopenharmony_ci} 58262306a36Sopenharmony_ci 58362306a36Sopenharmony_cistatic inline uint32_t mtd_mod_by_eb(uint64_t sz, struct mtd_info *mtd) 58462306a36Sopenharmony_ci{ 58562306a36Sopenharmony_ci if (mtd->erasesize_shift) 58662306a36Sopenharmony_ci return sz & mtd->erasesize_mask; 58762306a36Sopenharmony_ci return do_div(sz, mtd->erasesize); 58862306a36Sopenharmony_ci} 58962306a36Sopenharmony_ci 59062306a36Sopenharmony_ci/** 59162306a36Sopenharmony_ci * mtd_align_erase_req - Adjust an erase request to align things on eraseblock 59262306a36Sopenharmony_ci * boundaries. 59362306a36Sopenharmony_ci * @mtd: the MTD device this erase request applies on 59462306a36Sopenharmony_ci * @req: the erase request to adjust 59562306a36Sopenharmony_ci * 59662306a36Sopenharmony_ci * This function will adjust @req->addr and @req->len to align them on 59762306a36Sopenharmony_ci * @mtd->erasesize. Of course we expect @mtd->erasesize to be != 0. 59862306a36Sopenharmony_ci */ 59962306a36Sopenharmony_cistatic inline void mtd_align_erase_req(struct mtd_info *mtd, 60062306a36Sopenharmony_ci struct erase_info *req) 60162306a36Sopenharmony_ci{ 60262306a36Sopenharmony_ci u32 mod; 60362306a36Sopenharmony_ci 60462306a36Sopenharmony_ci if (WARN_ON(!mtd->erasesize)) 60562306a36Sopenharmony_ci return; 60662306a36Sopenharmony_ci 60762306a36Sopenharmony_ci mod = mtd_mod_by_eb(req->addr, mtd); 60862306a36Sopenharmony_ci if (mod) { 60962306a36Sopenharmony_ci req->addr -= mod; 61062306a36Sopenharmony_ci req->len += mod; 61162306a36Sopenharmony_ci } 61262306a36Sopenharmony_ci 61362306a36Sopenharmony_ci mod = mtd_mod_by_eb(req->addr + req->len, mtd); 61462306a36Sopenharmony_ci if (mod) 61562306a36Sopenharmony_ci req->len += mtd->erasesize - mod; 61662306a36Sopenharmony_ci} 61762306a36Sopenharmony_ci 61862306a36Sopenharmony_cistatic inline uint32_t mtd_div_by_ws(uint64_t sz, struct mtd_info *mtd) 61962306a36Sopenharmony_ci{ 62062306a36Sopenharmony_ci if (mtd->writesize_shift) 62162306a36Sopenharmony_ci return sz >> mtd->writesize_shift; 62262306a36Sopenharmony_ci do_div(sz, mtd->writesize); 62362306a36Sopenharmony_ci return sz; 62462306a36Sopenharmony_ci} 62562306a36Sopenharmony_ci 62662306a36Sopenharmony_cistatic inline uint32_t mtd_mod_by_ws(uint64_t sz, struct mtd_info *mtd) 62762306a36Sopenharmony_ci{ 62862306a36Sopenharmony_ci if (mtd->writesize_shift) 62962306a36Sopenharmony_ci return sz & mtd->writesize_mask; 63062306a36Sopenharmony_ci return do_div(sz, mtd->writesize); 63162306a36Sopenharmony_ci} 63262306a36Sopenharmony_ci 63362306a36Sopenharmony_cistatic inline int mtd_wunit_per_eb(struct mtd_info *mtd) 63462306a36Sopenharmony_ci{ 63562306a36Sopenharmony_ci struct mtd_info *master = mtd_get_master(mtd); 63662306a36Sopenharmony_ci 63762306a36Sopenharmony_ci return master->erasesize / mtd->writesize; 63862306a36Sopenharmony_ci} 63962306a36Sopenharmony_ci 64062306a36Sopenharmony_cistatic inline int mtd_offset_to_wunit(struct mtd_info *mtd, loff_t offs) 64162306a36Sopenharmony_ci{ 64262306a36Sopenharmony_ci return mtd_div_by_ws(mtd_mod_by_eb(offs, mtd), mtd); 64362306a36Sopenharmony_ci} 64462306a36Sopenharmony_ci 64562306a36Sopenharmony_cistatic inline loff_t mtd_wunit_to_offset(struct mtd_info *mtd, loff_t base, 64662306a36Sopenharmony_ci int wunit) 64762306a36Sopenharmony_ci{ 64862306a36Sopenharmony_ci return base + (wunit * mtd->writesize); 64962306a36Sopenharmony_ci} 65062306a36Sopenharmony_ci 65162306a36Sopenharmony_ci 65262306a36Sopenharmony_cistatic inline int mtd_has_oob(const struct mtd_info *mtd) 65362306a36Sopenharmony_ci{ 65462306a36Sopenharmony_ci struct mtd_info *master = mtd_get_master((struct mtd_info *)mtd); 65562306a36Sopenharmony_ci 65662306a36Sopenharmony_ci return master->_read_oob && master->_write_oob; 65762306a36Sopenharmony_ci} 65862306a36Sopenharmony_ci 65962306a36Sopenharmony_cistatic inline int mtd_type_is_nand(const struct mtd_info *mtd) 66062306a36Sopenharmony_ci{ 66162306a36Sopenharmony_ci return mtd->type == MTD_NANDFLASH || mtd->type == MTD_MLCNANDFLASH; 66262306a36Sopenharmony_ci} 66362306a36Sopenharmony_ci 66462306a36Sopenharmony_cistatic inline int mtd_can_have_bb(const struct mtd_info *mtd) 66562306a36Sopenharmony_ci{ 66662306a36Sopenharmony_ci struct mtd_info *master = mtd_get_master((struct mtd_info *)mtd); 66762306a36Sopenharmony_ci 66862306a36Sopenharmony_ci return !!master->_block_isbad; 66962306a36Sopenharmony_ci} 67062306a36Sopenharmony_ci 67162306a36Sopenharmony_ci /* Kernel-side ioctl definitions */ 67262306a36Sopenharmony_ci 67362306a36Sopenharmony_cistruct mtd_partition; 67462306a36Sopenharmony_cistruct mtd_part_parser_data; 67562306a36Sopenharmony_ci 67662306a36Sopenharmony_ciextern int mtd_device_parse_register(struct mtd_info *mtd, 67762306a36Sopenharmony_ci const char * const *part_probe_types, 67862306a36Sopenharmony_ci struct mtd_part_parser_data *parser_data, 67962306a36Sopenharmony_ci const struct mtd_partition *defparts, 68062306a36Sopenharmony_ci int defnr_parts); 68162306a36Sopenharmony_ci#define mtd_device_register(master, parts, nr_parts) \ 68262306a36Sopenharmony_ci mtd_device_parse_register(master, NULL, NULL, parts, nr_parts) 68362306a36Sopenharmony_ciextern int mtd_device_unregister(struct mtd_info *master); 68462306a36Sopenharmony_ciextern struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num); 68562306a36Sopenharmony_ciextern int __get_mtd_device(struct mtd_info *mtd); 68662306a36Sopenharmony_ciextern void __put_mtd_device(struct mtd_info *mtd); 68762306a36Sopenharmony_ciextern struct mtd_info *of_get_mtd_device_by_node(struct device_node *np); 68862306a36Sopenharmony_ciextern struct mtd_info *get_mtd_device_nm(const char *name); 68962306a36Sopenharmony_ciextern void put_mtd_device(struct mtd_info *mtd); 69062306a36Sopenharmony_ci 69162306a36Sopenharmony_ci 69262306a36Sopenharmony_cistruct mtd_notifier { 69362306a36Sopenharmony_ci void (*add)(struct mtd_info *mtd); 69462306a36Sopenharmony_ci void (*remove)(struct mtd_info *mtd); 69562306a36Sopenharmony_ci struct list_head list; 69662306a36Sopenharmony_ci}; 69762306a36Sopenharmony_ci 69862306a36Sopenharmony_ci 69962306a36Sopenharmony_ciextern void register_mtd_user (struct mtd_notifier *new); 70062306a36Sopenharmony_ciextern int unregister_mtd_user (struct mtd_notifier *old); 70162306a36Sopenharmony_civoid *mtd_kmalloc_up_to(const struct mtd_info *mtd, size_t *size); 70262306a36Sopenharmony_ci 70362306a36Sopenharmony_cistatic inline int mtd_is_bitflip(int err) { 70462306a36Sopenharmony_ci return err == -EUCLEAN; 70562306a36Sopenharmony_ci} 70662306a36Sopenharmony_ci 70762306a36Sopenharmony_cistatic inline int mtd_is_eccerr(int err) { 70862306a36Sopenharmony_ci return err == -EBADMSG; 70962306a36Sopenharmony_ci} 71062306a36Sopenharmony_ci 71162306a36Sopenharmony_cistatic inline int mtd_is_bitflip_or_eccerr(int err) { 71262306a36Sopenharmony_ci return mtd_is_bitflip(err) || mtd_is_eccerr(err); 71362306a36Sopenharmony_ci} 71462306a36Sopenharmony_ci 71562306a36Sopenharmony_ciunsigned mtd_mmap_capabilities(struct mtd_info *mtd); 71662306a36Sopenharmony_ci 71762306a36Sopenharmony_ci#ifdef CONFIG_DEBUG_FS 71862306a36Sopenharmony_cibool mtd_check_expert_analysis_mode(void); 71962306a36Sopenharmony_ci#else 72062306a36Sopenharmony_cistatic inline bool mtd_check_expert_analysis_mode(void) { return false; } 72162306a36Sopenharmony_ci#endif 72262306a36Sopenharmony_ci 72362306a36Sopenharmony_ci 72462306a36Sopenharmony_ci#endif /* __MTD_MTD_H__ */ 725