1932394acSWolfgang Denk /* 2ff94bc40SHeiko Schocher * Copyright © 1999-2010 David Woodhouse <dwmw2@infradead.org> et al. 3932394acSWolfgang Denk * 478e9e71cSTom Rini * SPDX-License-Identifier: GPL-2.0+ 5ff94bc40SHeiko Schocher * 6932394acSWolfgang Denk */ 7932394acSWolfgang Denk 8932394acSWolfgang Denk #ifndef __MTD_MTD_H__ 9932394acSWolfgang Denk #define __MTD_MTD_H__ 10cfa460adSWilliam Juul 11ff94bc40SHeiko Schocher #ifndef __UBOOT__ 12932394acSWolfgang Denk #include <linux/types.h> 13ff94bc40SHeiko Schocher #include <linux/uio.h> 14ff94bc40SHeiko Schocher #include <linux/notifier.h> 15ff94bc40SHeiko Schocher #include <linux/device.h> 16ff94bc40SHeiko Schocher 17ff94bc40SHeiko Schocher #include <mtd/mtd-abi.h> 18ff94bc40SHeiko Schocher 19ff94bc40SHeiko Schocher #include <asm/div64.h> 20ff94bc40SHeiko Schocher #else 21ff94bc40SHeiko Schocher #include <linux/compat.h> 22dfe64e2cSSergey Lapin #include <mtd/mtd-abi.h> 231221ce45SMasahiro Yamada #include <linux/errno.h> 24c7314be4SMiquel Raynal #include <linux/list.h> 25ff94bc40SHeiko Schocher #include <div64.h> 26c7314be4SMiquel Raynal #if IS_ENABLED(CONFIG_DM) 27c7314be4SMiquel Raynal #include <dm/device.h> 28c7314be4SMiquel Raynal #endif 29932394acSWolfgang Denk 30cfa460adSWilliam Juul #define MAX_MTD_DEVICES 32 31ff94bc40SHeiko Schocher #endif 32932394acSWolfgang Denk 33932394acSWolfgang Denk #define MTD_ERASE_PENDING 0x01 34932394acSWolfgang Denk #define MTD_ERASING 0x02 35932394acSWolfgang Denk #define MTD_ERASE_SUSPEND 0x04 36932394acSWolfgang Denk #define MTD_ERASE_DONE 0x08 37932394acSWolfgang Denk #define MTD_ERASE_FAILED 0x10 38932394acSWolfgang Denk 398d2effeaSStefan Roese #define MTD_FAIL_ADDR_UNKNOWN -1LL 408d2effeaSStefan Roese 41d438d508SKyungmin Park /* 42ff94bc40SHeiko Schocher * If the erase fails, fail_addr might indicate exactly which block failed. If 43ff94bc40SHeiko Schocher * fail_addr = MTD_FAIL_ADDR_UNKNOWN, the failure was not at the device level 44ff94bc40SHeiko Schocher * or was not specific to any particular block. 45d438d508SKyungmin Park */ 46932394acSWolfgang Denk struct erase_info { 47932394acSWolfgang Denk struct mtd_info *mtd; 488d2effeaSStefan Roese uint64_t addr; 498d2effeaSStefan Roese uint64_t len; 508d2effeaSStefan Roese uint64_t fail_addr; 51932394acSWolfgang Denk u_long time; 52932394acSWolfgang Denk u_long retries; 53ff94bc40SHeiko Schocher unsigned dev; 54ff94bc40SHeiko Schocher unsigned cell; 55932394acSWolfgang Denk void (*callback) (struct erase_info *self); 56932394acSWolfgang Denk u_long priv; 57932394acSWolfgang Denk u_char state; 58932394acSWolfgang Denk struct erase_info *next; 596d41419fSMarek Vasut int scrub; 60932394acSWolfgang Denk }; 61932394acSWolfgang Denk 62932394acSWolfgang Denk struct mtd_erase_region_info { 638d2effeaSStefan Roese uint64_t offset; /* At which this region starts, from the beginning of the MTD */ 64ff94bc40SHeiko Schocher uint32_t erasesize; /* For this region */ 65ff94bc40SHeiko Schocher uint32_t numblocks; /* Number of blocks of erasesize in this region */ 66cfa460adSWilliam Juul unsigned long *lockmap; /* If keeping bitmap of locks */ 67cfa460adSWilliam Juul }; 68cfa460adSWilliam Juul 69cfa460adSWilliam Juul /** 70cfa460adSWilliam Juul * struct mtd_oob_ops - oob operation operands 71cfa460adSWilliam Juul * @mode: operation mode 72cfa460adSWilliam Juul * 73cfa460adSWilliam Juul * @len: number of data bytes to write/read 74cfa460adSWilliam Juul * 75cfa460adSWilliam Juul * @retlen: number of data bytes written/read 76cfa460adSWilliam Juul * 77cfa460adSWilliam Juul * @ooblen: number of oob bytes to write/read 78cfa460adSWilliam Juul * @oobretlen: number of oob bytes written/read 79cfa460adSWilliam Juul * @ooboffs: offset of oob data in the oob area (only relevant when 80dfe64e2cSSergey Lapin * mode = MTD_OPS_PLACE_OOB or MTD_OPS_RAW) 81cfa460adSWilliam Juul * @datbuf: data buffer - if NULL only oob data are read/written 82cfa460adSWilliam Juul * @oobbuf: oob data buffer 83cfa460adSWilliam Juul * 84ff94bc40SHeiko Schocher * Note, it is allowed to read more than one OOB area at one go, but not write. 85cfa460adSWilliam Juul * The interface assumes that the OOB write requests program only one page's 86cfa460adSWilliam Juul * OOB area. 87cfa460adSWilliam Juul */ 88cfa460adSWilliam Juul struct mtd_oob_ops { 89dfe64e2cSSergey Lapin unsigned int mode; 90cfa460adSWilliam Juul size_t len; 91cfa460adSWilliam Juul size_t retlen; 92cfa460adSWilliam Juul size_t ooblen; 93cfa460adSWilliam Juul size_t oobretlen; 94cfa460adSWilliam Juul uint32_t ooboffs; 95cfa460adSWilliam Juul uint8_t *datbuf; 96cfa460adSWilliam Juul uint8_t *oobbuf; 97932394acSWolfgang Denk }; 98932394acSWolfgang Denk 9968ec9c85SPrabhakar Kushwaha #ifdef CONFIG_SYS_NAND_MAX_OOBFREE 10068ec9c85SPrabhakar Kushwaha #define MTD_MAX_OOBFREE_ENTRIES_LARGE CONFIG_SYS_NAND_MAX_OOBFREE 10168ec9c85SPrabhakar Kushwaha #else 10268ec9c85SPrabhakar Kushwaha #define MTD_MAX_OOBFREE_ENTRIES_LARGE 32 10368ec9c85SPrabhakar Kushwaha #endif 10468ec9c85SPrabhakar Kushwaha 10568ec9c85SPrabhakar Kushwaha #ifdef CONFIG_SYS_NAND_MAX_ECCPOS 10668ec9c85SPrabhakar Kushwaha #define MTD_MAX_ECCPOS_ENTRIES_LARGE CONFIG_SYS_NAND_MAX_ECCPOS 10768ec9c85SPrabhakar Kushwaha #else 1082580a2a7SSiva Durga Prasad Paladugu #define MTD_MAX_ECCPOS_ENTRIES_LARGE 680 10968ec9c85SPrabhakar Kushwaha #endif 110c44c4cceSBoris Brezillon /** 111c44c4cceSBoris Brezillon * struct mtd_oob_region - oob region definition 112c44c4cceSBoris Brezillon * @offset: region offset 113c44c4cceSBoris Brezillon * @length: region length 114c44c4cceSBoris Brezillon * 115c44c4cceSBoris Brezillon * This structure describes a region of the OOB area, and is used 116c44c4cceSBoris Brezillon * to retrieve ECC or free bytes sections. 117c44c4cceSBoris Brezillon * Each section is defined by an offset within the OOB area and a 118c44c4cceSBoris Brezillon * length. 119c44c4cceSBoris Brezillon */ 120c44c4cceSBoris Brezillon struct mtd_oob_region { 121c44c4cceSBoris Brezillon u32 offset; 122c44c4cceSBoris Brezillon u32 length; 123c44c4cceSBoris Brezillon }; 124c44c4cceSBoris Brezillon 125c44c4cceSBoris Brezillon /* 126c44c4cceSBoris Brezillon * struct mtd_ooblayout_ops - NAND OOB layout operations 127c44c4cceSBoris Brezillon * @ecc: function returning an ECC region in the OOB area. 128c44c4cceSBoris Brezillon * Should return -ERANGE if %section exceeds the total number of 129c44c4cceSBoris Brezillon * ECC sections. 130c44c4cceSBoris Brezillon * @free: function returning a free region in the OOB area. 131c44c4cceSBoris Brezillon * Should return -ERANGE if %section exceeds the total number of 132c44c4cceSBoris Brezillon * free sections. 133c44c4cceSBoris Brezillon */ 134c44c4cceSBoris Brezillon struct mtd_ooblayout_ops { 135c44c4cceSBoris Brezillon int (*ecc)(struct mtd_info *mtd, int section, 136c44c4cceSBoris Brezillon struct mtd_oob_region *oobecc); 137*301f8dd1SSimon Glass int (*rfree)(struct mtd_info *mtd, int section, 138c44c4cceSBoris Brezillon struct mtd_oob_region *oobfree); 139c44c4cceSBoris Brezillon }; 14068ec9c85SPrabhakar Kushwaha 14168ec9c85SPrabhakar Kushwaha /* 142ff94bc40SHeiko Schocher * Internal ECC layout control structure. For historical reasons, there is a 143ff94bc40SHeiko Schocher * similar, smaller struct nand_ecclayout_user (in mtd-abi.h) that is retained 144ff94bc40SHeiko Schocher * for export to user-space via the ECCGETLAYOUT ioctl. 145ff94bc40SHeiko Schocher * nand_ecclayout should be expandable in the future simply by the above macros. 14668ec9c85SPrabhakar Kushwaha */ 14768ec9c85SPrabhakar Kushwaha struct nand_ecclayout { 148ff94bc40SHeiko Schocher __u32 eccbytes; 149ff94bc40SHeiko Schocher __u32 eccpos[MTD_MAX_ECCPOS_ENTRIES_LARGE]; 150ff94bc40SHeiko Schocher __u32 oobavail; 15168ec9c85SPrabhakar Kushwaha struct nand_oobfree oobfree[MTD_MAX_OOBFREE_ENTRIES_LARGE]; 15268ec9c85SPrabhakar Kushwaha }; 15368ec9c85SPrabhakar Kushwaha 154ff94bc40SHeiko Schocher struct module; /* only needed for owner field in mtd_info */ 155ff94bc40SHeiko Schocher 156932394acSWolfgang Denk struct mtd_info { 157932394acSWolfgang Denk u_char type; 158ff94bc40SHeiko Schocher uint32_t flags; 159ff94bc40SHeiko Schocher uint64_t size; // Total size of the MTD 160932394acSWolfgang Denk 161fa82f871SAlbert ARIBAUD /* "Major" erase size for the device. Naïve users may take this 162932394acSWolfgang Denk * to be the only erase size available, or may use the more detailed 163932394acSWolfgang Denk * information below if they desire 164932394acSWolfgang Denk */ 165ff94bc40SHeiko Schocher uint32_t erasesize; 166cfa460adSWilliam Juul /* Minimal writable flash unit size. In case of NOR flash it is 1 (even 167cfa460adSWilliam Juul * though individual bits can be cleared), in case of NAND flash it is 168cfa460adSWilliam Juul * one NAND page (or half, or one-fourths of it), in case of ECC-ed NOR 169cfa460adSWilliam Juul * it is of ECC block size, etc. It is illegal to have writesize = 0. 170cfa460adSWilliam Juul * Any driver registering a struct mtd_info must ensure a writesize of 171cfa460adSWilliam Juul * 1 or larger. 172cfa460adSWilliam Juul */ 173ff94bc40SHeiko Schocher uint32_t writesize; 174932394acSWolfgang Denk 175ff94bc40SHeiko Schocher /* 176ff94bc40SHeiko Schocher * Size of the write buffer used by the MTD. MTD devices having a write 177ff94bc40SHeiko Schocher * buffer can write multiple writesize chunks at a time. E.g. while 178ff94bc40SHeiko Schocher * writing 4 * writesize bytes to a device with 2 * writesize bytes 179ff94bc40SHeiko Schocher * buffer the MTD driver can (but doesn't have to) do 2 writesize 180ff94bc40SHeiko Schocher * operations, but not 4. Currently, all NANDs have writebufsize 181ff94bc40SHeiko Schocher * equivalent to writesize (NAND page size). Some NOR flashes do have 182ff94bc40SHeiko Schocher * writebufsize greater than writesize. 183ff94bc40SHeiko Schocher */ 184ff94bc40SHeiko Schocher uint32_t writebufsize; 185ff94bc40SHeiko Schocher 186ff94bc40SHeiko Schocher uint32_t oobsize; // Amount of OOB data per block (e.g. 16) 187ff94bc40SHeiko Schocher uint32_t oobavail; // Available OOB bytes per block 188ff94bc40SHeiko Schocher 189ff94bc40SHeiko Schocher /* 190ff94bc40SHeiko Schocher * If erasesize is a power of 2 then the shift is stored in 191ff94bc40SHeiko Schocher * erasesize_shift otherwise erasesize_shift is zero. Ditto writesize. 192ff94bc40SHeiko Schocher */ 193ff94bc40SHeiko Schocher unsigned int erasesize_shift; 194ff94bc40SHeiko Schocher unsigned int writesize_shift; 195ff94bc40SHeiko Schocher /* Masks based on erasesize_shift and writesize_shift */ 196ff94bc40SHeiko Schocher unsigned int erasesize_mask; 197ff94bc40SHeiko Schocher unsigned int writesize_mask; 198932394acSWolfgang Denk 199dfe64e2cSSergey Lapin /* 200dfe64e2cSSergey Lapin * read ops return -EUCLEAN if max number of bitflips corrected on any 201dfe64e2cSSergey Lapin * one region comprising an ecc step equals or exceeds this value. 202dfe64e2cSSergey Lapin * Settable by driver, else defaults to ecc_strength. User can override 203dfe64e2cSSergey Lapin * in sysfs. N.B. The meaning of the -EUCLEAN return code has changed; 204dfe64e2cSSergey Lapin * see Documentation/ABI/testing/sysfs-class-mtd for more detail. 205dfe64e2cSSergey Lapin */ 206dfe64e2cSSergey Lapin unsigned int bitflip_threshold; 207dfe64e2cSSergey Lapin 208ff94bc40SHeiko Schocher // Kernel-only stuff starts here. 209ff94bc40SHeiko Schocher #ifndef __UBOOT__ 210c45912d8SScott Wood const char *name; 211ff94bc40SHeiko Schocher #else 212ff94bc40SHeiko Schocher char *name; 213ff94bc40SHeiko Schocher #endif 214932394acSWolfgang Denk int index; 215932394acSWolfgang Denk 216c44c4cceSBoris Brezillon /* OOB layout description */ 217c44c4cceSBoris Brezillon const struct mtd_ooblayout_ops *ooblayout; 218c44c4cceSBoris Brezillon 219dfe64e2cSSergey Lapin /* ECC layout structure pointer - read only! */ 220cfa460adSWilliam Juul struct nand_ecclayout *ecclayout; 221932394acSWolfgang Denk 222ff94bc40SHeiko Schocher /* the ecc step size. */ 223ff94bc40SHeiko Schocher unsigned int ecc_step_size; 224ff94bc40SHeiko Schocher 225dfe64e2cSSergey Lapin /* max number of correctible bit errors per ecc step */ 226dfe64e2cSSergey Lapin unsigned int ecc_strength; 227dfe64e2cSSergey Lapin 228932394acSWolfgang Denk /* Data for variable erase regions. If numeraseregions is zero, 229932394acSWolfgang Denk * it means that the whole device has erasesize as given above. 230932394acSWolfgang Denk */ 231932394acSWolfgang Denk int numeraseregions; 232932394acSWolfgang Denk struct mtd_erase_region_info *eraseregions; 233932394acSWolfgang Denk 234c45912d8SScott Wood /* 235dfe64e2cSSergey Lapin * Do not call via these pointers, use corresponding mtd_*() 236dfe64e2cSSergey Lapin * wrappers instead. 237c45912d8SScott Wood */ 238dfe64e2cSSergey Lapin int (*_erase) (struct mtd_info *mtd, struct erase_info *instr); 239ff94bc40SHeiko Schocher #ifndef __UBOOT__ 240dfe64e2cSSergey Lapin int (*_point) (struct mtd_info *mtd, loff_t from, size_t len, 241ff94bc40SHeiko Schocher size_t *retlen, void **virt, resource_size_t *phys); 242ff94bc40SHeiko Schocher int (*_unpoint) (struct mtd_info *mtd, loff_t from, size_t len); 243ff94bc40SHeiko Schocher #endif 244ff94bc40SHeiko Schocher unsigned long (*_get_unmapped_area) (struct mtd_info *mtd, 245ff94bc40SHeiko Schocher unsigned long len, 246ff94bc40SHeiko Schocher unsigned long offset, 247ff94bc40SHeiko Schocher unsigned long flags); 248dfe64e2cSSergey Lapin int (*_read) (struct mtd_info *mtd, loff_t from, size_t len, 249dfe64e2cSSergey Lapin size_t *retlen, u_char *buf); 250dfe64e2cSSergey Lapin int (*_write) (struct mtd_info *mtd, loff_t to, size_t len, 251dfe64e2cSSergey Lapin size_t *retlen, const u_char *buf); 252ff94bc40SHeiko Schocher int (*_panic_write) (struct mtd_info *mtd, loff_t to, size_t len, 253ff94bc40SHeiko Schocher size_t *retlen, const u_char *buf); 254dfe64e2cSSergey Lapin int (*_read_oob) (struct mtd_info *mtd, loff_t from, 255cfa460adSWilliam Juul struct mtd_oob_ops *ops); 256dfe64e2cSSergey Lapin int (*_write_oob) (struct mtd_info *mtd, loff_t to, 257cfa460adSWilliam Juul struct mtd_oob_ops *ops); 2584e67c571SHeiko Schocher int (*_get_fact_prot_info) (struct mtd_info *mtd, size_t len, 2594e67c571SHeiko Schocher size_t *retlen, struct otp_info *buf); 260dfe64e2cSSergey Lapin int (*_read_fact_prot_reg) (struct mtd_info *mtd, loff_t from, 261dfe64e2cSSergey Lapin size_t len, size_t *retlen, u_char *buf); 2624e67c571SHeiko Schocher int (*_get_user_prot_info) (struct mtd_info *mtd, size_t len, 2634e67c571SHeiko Schocher size_t *retlen, struct otp_info *buf); 264dfe64e2cSSergey Lapin int (*_read_user_prot_reg) (struct mtd_info *mtd, loff_t from, 265dfe64e2cSSergey Lapin size_t len, size_t *retlen, u_char *buf); 266ff94bc40SHeiko Schocher int (*_write_user_prot_reg) (struct mtd_info *mtd, loff_t to, 267ff94bc40SHeiko Schocher size_t len, size_t *retlen, u_char *buf); 268dfe64e2cSSergey Lapin int (*_lock_user_prot_reg) (struct mtd_info *mtd, loff_t from, 269dfe64e2cSSergey Lapin size_t len); 270ff94bc40SHeiko Schocher #ifndef __UBOOT__ 271ff94bc40SHeiko Schocher int (*_writev) (struct mtd_info *mtd, const struct kvec *vecs, 272ff94bc40SHeiko Schocher unsigned long count, loff_t to, size_t *retlen); 273ff94bc40SHeiko Schocher #endif 274dfe64e2cSSergey Lapin void (*_sync) (struct mtd_info *mtd); 275dfe64e2cSSergey Lapin int (*_lock) (struct mtd_info *mtd, loff_t ofs, uint64_t len); 276dfe64e2cSSergey Lapin int (*_unlock) (struct mtd_info *mtd, loff_t ofs, uint64_t len); 277ff94bc40SHeiko Schocher int (*_is_locked) (struct mtd_info *mtd, loff_t ofs, uint64_t len); 27886a720aaSEzequiel Garcia int (*_block_isreserved) (struct mtd_info *mtd, loff_t ofs); 279dfe64e2cSSergey Lapin int (*_block_isbad) (struct mtd_info *mtd, loff_t ofs); 280dfe64e2cSSergey Lapin int (*_block_markbad) (struct mtd_info *mtd, loff_t ofs); 281ff94bc40SHeiko Schocher #ifndef __UBOOT__ 282ff94bc40SHeiko Schocher int (*_suspend) (struct mtd_info *mtd); 283ff94bc40SHeiko Schocher void (*_resume) (struct mtd_info *mtd); 2840195a7bbSHeiko Schocher void (*_reboot) (struct mtd_info *mtd); 285ff94bc40SHeiko Schocher #endif 286932394acSWolfgang Denk /* 287dfe64e2cSSergey Lapin * If the driver is something smart, like UBI, it may need to maintain 288dfe64e2cSSergey Lapin * its own reference counting. The below functions are only for driver. 289932394acSWolfgang Denk */ 290dfe64e2cSSergey Lapin int (*_get_device) (struct mtd_info *mtd); 291dfe64e2cSSergey Lapin void (*_put_device) (struct mtd_info *mtd); 292cfa460adSWilliam Juul 293ff94bc40SHeiko Schocher #ifndef __UBOOT__ 294ff94bc40SHeiko Schocher /* Backing device capabilities for this device 295ff94bc40SHeiko Schocher * - provides mmap capabilities 296932394acSWolfgang Denk */ 297ff94bc40SHeiko Schocher struct backing_dev_info *backing_dev_info; 298ff94bc40SHeiko Schocher 299cfa460adSWilliam Juul struct notifier_block reboot_notifier; /* default mode before reboot */ 300cfa460adSWilliam Juul #endif 301cfa460adSWilliam Juul 302cfa460adSWilliam Juul /* ECC status information */ 303cfa460adSWilliam Juul struct mtd_ecc_stats ecc_stats; 304cfa460adSWilliam Juul /* Subpage shift (NAND) */ 305cfa460adSWilliam Juul int subpage_sft; 306cfa460adSWilliam Juul 307932394acSWolfgang Denk void *priv; 308932394acSWolfgang Denk 309932394acSWolfgang Denk struct module *owner; 310ff94bc40SHeiko Schocher #ifndef __UBOOT__ 311ff94bc40SHeiko Schocher struct device dev; 312d8587993SThomas Chou #else 313d8587993SThomas Chou struct udevice *dev; 314ff94bc40SHeiko Schocher #endif 315932394acSWolfgang Denk int usecount; 316c7314be4SMiquel Raynal 317c7314be4SMiquel Raynal /* MTD devices do not have any parent. MTD partitions do. */ 318c7314be4SMiquel Raynal struct mtd_info *parent; 319c7314be4SMiquel Raynal 320c7314be4SMiquel Raynal /* 321c7314be4SMiquel Raynal * Offset of the partition relatively to the parent offset. 322c7314be4SMiquel Raynal * Is 0 for real MTD devices (ie. not partitions). 323c7314be4SMiquel Raynal */ 324c7314be4SMiquel Raynal u64 offset; 325c7314be4SMiquel Raynal 326c7314be4SMiquel Raynal /* 327c7314be4SMiquel Raynal * List node used to add an MTD partition to the parent 328c7314be4SMiquel Raynal * partition list. 329c7314be4SMiquel Raynal */ 330c7314be4SMiquel Raynal struct list_head node; 331c7314be4SMiquel Raynal 332c7314be4SMiquel Raynal /* 333c7314be4SMiquel Raynal * List of partitions attached to this MTD device (the parent 334c7314be4SMiquel Raynal * MTD device can itself be a partition). 335c7314be4SMiquel Raynal */ 336c7314be4SMiquel Raynal struct list_head partitions; 337932394acSWolfgang Denk }; 338932394acSWolfgang Denk 339c7314be4SMiquel Raynal #if IS_ENABLED(CONFIG_DM) 340c7314be4SMiquel Raynal static inline void mtd_set_of_node(struct mtd_info *mtd, 341c7314be4SMiquel Raynal const struct device_node *np) 342c7314be4SMiquel Raynal { 343c7314be4SMiquel Raynal mtd->dev->node.np = np; 344c7314be4SMiquel Raynal } 345c7314be4SMiquel Raynal 346c7314be4SMiquel Raynal static inline const struct device_node *mtd_get_of_node(struct mtd_info *mtd) 347c7314be4SMiquel Raynal { 348c7314be4SMiquel Raynal return mtd->dev->node.np; 349c7314be4SMiquel Raynal } 350c7314be4SMiquel Raynal #else 351c7314be4SMiquel Raynal struct device_node; 352c7314be4SMiquel Raynal 353c7314be4SMiquel Raynal static inline void mtd_set_of_node(struct mtd_info *mtd, 354c7314be4SMiquel Raynal const struct device_node *np) 355c7314be4SMiquel Raynal { 356c7314be4SMiquel Raynal } 357c7314be4SMiquel Raynal 358c7314be4SMiquel Raynal static inline const struct device_node *mtd_get_of_node(struct mtd_info *mtd) 359c7314be4SMiquel Raynal { 360c7314be4SMiquel Raynal return NULL; 361c7314be4SMiquel Raynal } 362c7314be4SMiquel Raynal #endif 363c7314be4SMiquel Raynal 364c7314be4SMiquel Raynal static inline bool mtd_is_partition(const struct mtd_info *mtd) 365c7314be4SMiquel Raynal { 366c7314be4SMiquel Raynal return mtd->parent; 367c7314be4SMiquel Raynal } 368c7314be4SMiquel Raynal 369c7314be4SMiquel Raynal static inline bool mtd_has_partitions(const struct mtd_info *mtd) 370c7314be4SMiquel Raynal { 371c7314be4SMiquel Raynal return !list_empty(&mtd->partitions); 372c7314be4SMiquel Raynal } 373c7314be4SMiquel Raynal 374ef964b01SBoris Brezillon bool mtd_partitions_used(struct mtd_info *master); 375ef964b01SBoris Brezillon 376c44c4cceSBoris Brezillon int mtd_ooblayout_ecc(struct mtd_info *mtd, int section, 377c44c4cceSBoris Brezillon struct mtd_oob_region *oobecc); 378c44c4cceSBoris Brezillon int mtd_ooblayout_find_eccregion(struct mtd_info *mtd, int eccbyte, 379c44c4cceSBoris Brezillon int *section, 380c44c4cceSBoris Brezillon struct mtd_oob_region *oobregion); 381c44c4cceSBoris Brezillon int mtd_ooblayout_get_eccbytes(struct mtd_info *mtd, u8 *eccbuf, 382c44c4cceSBoris Brezillon const u8 *oobbuf, int start, int nbytes); 383c44c4cceSBoris Brezillon int mtd_ooblayout_set_eccbytes(struct mtd_info *mtd, const u8 *eccbuf, 384c44c4cceSBoris Brezillon u8 *oobbuf, int start, int nbytes); 385c44c4cceSBoris Brezillon int mtd_ooblayout_free(struct mtd_info *mtd, int section, 386c44c4cceSBoris Brezillon struct mtd_oob_region *oobfree); 387c44c4cceSBoris Brezillon int mtd_ooblayout_get_databytes(struct mtd_info *mtd, u8 *databuf, 388c44c4cceSBoris Brezillon const u8 *oobbuf, int start, int nbytes); 389c44c4cceSBoris Brezillon int mtd_ooblayout_set_databytes(struct mtd_info *mtd, const u8 *databuf, 390c44c4cceSBoris Brezillon u8 *oobbuf, int start, int nbytes); 391c44c4cceSBoris Brezillon int mtd_ooblayout_count_freebytes(struct mtd_info *mtd); 392c44c4cceSBoris Brezillon int mtd_ooblayout_count_eccbytes(struct mtd_info *mtd); 393c44c4cceSBoris Brezillon 394c44c4cceSBoris Brezillon static inline void mtd_set_ooblayout(struct mtd_info *mtd, 395c44c4cceSBoris Brezillon const struct mtd_ooblayout_ops *ooblayout) 396c44c4cceSBoris Brezillon { 397c44c4cceSBoris Brezillon mtd->ooblayout = ooblayout; 398c44c4cceSBoris Brezillon } 399c44c4cceSBoris Brezillon 400ceee07b6SScott Wood static inline int mtd_oobavail(struct mtd_info *mtd, struct mtd_oob_ops *ops) 401ceee07b6SScott Wood { 402ceee07b6SScott Wood return ops->mode == MTD_OPS_AUTO_OOB ? mtd->oobavail : mtd->oobsize; 403ceee07b6SScott Wood } 404ceee07b6SScott Wood 405dfe64e2cSSergey Lapin int mtd_erase(struct mtd_info *mtd, struct erase_info *instr); 406ff94bc40SHeiko Schocher #ifndef __UBOOT__ 407ff94bc40SHeiko Schocher int mtd_point(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, 408ff94bc40SHeiko Schocher void **virt, resource_size_t *phys); 409ff94bc40SHeiko Schocher int mtd_unpoint(struct mtd_info *mtd, loff_t from, size_t len); 410ff94bc40SHeiko Schocher #endif 411ff94bc40SHeiko Schocher unsigned long mtd_get_unmapped_area(struct mtd_info *mtd, unsigned long len, 412ff94bc40SHeiko Schocher unsigned long offset, unsigned long flags); 413dfe64e2cSSergey Lapin int mtd_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, 414dfe64e2cSSergey Lapin u_char *buf); 415dfe64e2cSSergey Lapin int mtd_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, 416dfe64e2cSSergey Lapin const u_char *buf); 417dfe64e2cSSergey Lapin int mtd_panic_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, 418dfe64e2cSSergey Lapin const u_char *buf); 419dfe64e2cSSergey Lapin 420dfe64e2cSSergey Lapin int mtd_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops); 42186db6a45SEzequiel Garcia int mtd_write_oob(struct mtd_info *mtd, loff_t to, struct mtd_oob_ops *ops); 422dfe64e2cSSergey Lapin 4234e67c571SHeiko Schocher int mtd_get_fact_prot_info(struct mtd_info *mtd, size_t len, size_t *retlen, 4244e67c571SHeiko Schocher struct otp_info *buf); 425dfe64e2cSSergey Lapin int mtd_read_fact_prot_reg(struct mtd_info *mtd, loff_t from, size_t len, 426dfe64e2cSSergey Lapin size_t *retlen, u_char *buf); 4274e67c571SHeiko Schocher int mtd_get_user_prot_info(struct mtd_info *mtd, size_t len, size_t *retlen, 4284e67c571SHeiko Schocher struct otp_info *buf); 429dfe64e2cSSergey Lapin int mtd_read_user_prot_reg(struct mtd_info *mtd, loff_t from, size_t len, 430dfe64e2cSSergey Lapin size_t *retlen, u_char *buf); 431dfe64e2cSSergey Lapin int mtd_write_user_prot_reg(struct mtd_info *mtd, loff_t to, size_t len, 432dfe64e2cSSergey Lapin size_t *retlen, u_char *buf); 433dfe64e2cSSergey Lapin int mtd_lock_user_prot_reg(struct mtd_info *mtd, loff_t from, size_t len); 434dfe64e2cSSergey Lapin 435ff94bc40SHeiko Schocher #ifndef __UBOOT__ 436dfe64e2cSSergey Lapin int mtd_writev(struct mtd_info *mtd, const struct kvec *vecs, 437dfe64e2cSSergey Lapin unsigned long count, loff_t to, size_t *retlen); 438dfe64e2cSSergey Lapin #endif 439dfe64e2cSSergey Lapin 440dfe64e2cSSergey Lapin static inline void mtd_sync(struct mtd_info *mtd) 441dfe64e2cSSergey Lapin { 442dfe64e2cSSergey Lapin if (mtd->_sync) 443dfe64e2cSSergey Lapin mtd->_sync(mtd); 444dfe64e2cSSergey Lapin } 445dfe64e2cSSergey Lapin 446dfe64e2cSSergey Lapin int mtd_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len); 447dfe64e2cSSergey Lapin int mtd_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len); 448dfe64e2cSSergey Lapin int mtd_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len); 44986a720aaSEzequiel Garcia int mtd_block_isreserved(struct mtd_info *mtd, loff_t ofs); 450dfe64e2cSSergey Lapin int mtd_block_isbad(struct mtd_info *mtd, loff_t ofs); 451dfe64e2cSSergey Lapin int mtd_block_markbad(struct mtd_info *mtd, loff_t ofs); 452dfe64e2cSSergey Lapin 453ff94bc40SHeiko Schocher #ifndef __UBOOT__ 454ff94bc40SHeiko Schocher static inline int mtd_suspend(struct mtd_info *mtd) 455ff94bc40SHeiko Schocher { 456ff94bc40SHeiko Schocher return mtd->_suspend ? mtd->_suspend(mtd) : 0; 457ff94bc40SHeiko Schocher } 458ff94bc40SHeiko Schocher 459ff94bc40SHeiko Schocher static inline void mtd_resume(struct mtd_info *mtd) 460ff94bc40SHeiko Schocher { 461ff94bc40SHeiko Schocher if (mtd->_resume) 462ff94bc40SHeiko Schocher mtd->_resume(mtd); 463ff94bc40SHeiko Schocher } 464ff94bc40SHeiko Schocher #endif 465ff94bc40SHeiko Schocher 4668d2effeaSStefan Roese static inline uint32_t mtd_div_by_eb(uint64_t sz, struct mtd_info *mtd) 4678d2effeaSStefan Roese { 468ff94bc40SHeiko Schocher if (mtd->erasesize_shift) 469ff94bc40SHeiko Schocher return sz >> mtd->erasesize_shift; 4708d2effeaSStefan Roese do_div(sz, mtd->erasesize); 4718d2effeaSStefan Roese return sz; 4728d2effeaSStefan Roese } 4738d2effeaSStefan Roese 4748d2effeaSStefan Roese static inline uint32_t mtd_mod_by_eb(uint64_t sz, struct mtd_info *mtd) 4758d2effeaSStefan Roese { 476ff94bc40SHeiko Schocher if (mtd->erasesize_shift) 477ff94bc40SHeiko Schocher return sz & mtd->erasesize_mask; 4788d2effeaSStefan Roese return do_div(sz, mtd->erasesize); 4798d2effeaSStefan Roese } 480932394acSWolfgang Denk 481ff94bc40SHeiko Schocher static inline uint32_t mtd_div_by_ws(uint64_t sz, struct mtd_info *mtd) 482ff94bc40SHeiko Schocher { 483ff94bc40SHeiko Schocher if (mtd->writesize_shift) 484ff94bc40SHeiko Schocher return sz >> mtd->writesize_shift; 485ff94bc40SHeiko Schocher do_div(sz, mtd->writesize); 486ff94bc40SHeiko Schocher return sz; 487ff94bc40SHeiko Schocher } 488ff94bc40SHeiko Schocher 489ff94bc40SHeiko Schocher static inline uint32_t mtd_mod_by_ws(uint64_t sz, struct mtd_info *mtd) 490ff94bc40SHeiko Schocher { 491ff94bc40SHeiko Schocher if (mtd->writesize_shift) 492ff94bc40SHeiko Schocher return sz & mtd->writesize_mask; 493ff94bc40SHeiko Schocher return do_div(sz, mtd->writesize); 494ff94bc40SHeiko Schocher } 495ff94bc40SHeiko Schocher 496dfe64e2cSSergey Lapin static inline int mtd_has_oob(const struct mtd_info *mtd) 497dfe64e2cSSergey Lapin { 498dfe64e2cSSergey Lapin return mtd->_read_oob && mtd->_write_oob; 499dfe64e2cSSergey Lapin } 500dfe64e2cSSergey Lapin 501ff94bc40SHeiko Schocher static inline int mtd_type_is_nand(const struct mtd_info *mtd) 502ff94bc40SHeiko Schocher { 503ff94bc40SHeiko Schocher return mtd->type == MTD_NANDFLASH || mtd->type == MTD_MLCNANDFLASH; 504ff94bc40SHeiko Schocher } 505ff94bc40SHeiko Schocher 506dfe64e2cSSergey Lapin static inline int mtd_can_have_bb(const struct mtd_info *mtd) 507dfe64e2cSSergey Lapin { 508dfe64e2cSSergey Lapin return !!mtd->_block_isbad; 509dfe64e2cSSergey Lapin } 510dfe64e2cSSergey Lapin 511932394acSWolfgang Denk /* Kernel-side ioctl definitions */ 512932394acSWolfgang Denk 513ff94bc40SHeiko Schocher struct mtd_partition; 514ff94bc40SHeiko Schocher struct mtd_part_parser_data; 515932394acSWolfgang Denk 516ff94bc40SHeiko Schocher extern int mtd_device_parse_register(struct mtd_info *mtd, 517ff94bc40SHeiko Schocher const char * const *part_probe_types, 518ff94bc40SHeiko Schocher struct mtd_part_parser_data *parser_data, 519ff94bc40SHeiko Schocher const struct mtd_partition *defparts, 520ff94bc40SHeiko Schocher int defnr_parts); 521ff94bc40SHeiko Schocher #define mtd_device_register(master, parts, nr_parts) \ 522ff94bc40SHeiko Schocher mtd_device_parse_register(master, NULL, NULL, parts, nr_parts) 523ff94bc40SHeiko Schocher extern int mtd_device_unregister(struct mtd_info *master); 524932394acSWolfgang Denk extern struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num); 525ff94bc40SHeiko Schocher extern int __get_mtd_device(struct mtd_info *mtd); 526ff94bc40SHeiko Schocher extern void __put_mtd_device(struct mtd_info *mtd); 527cfa460adSWilliam Juul extern struct mtd_info *get_mtd_device_nm(const char *name); 528932394acSWolfgang Denk extern void put_mtd_device(struct mtd_info *mtd); 529ff94bc40SHeiko Schocher 530ff94bc40SHeiko Schocher 531ff94bc40SHeiko Schocher #ifndef __UBOOT__ 532932394acSWolfgang Denk struct mtd_notifier { 533932394acSWolfgang Denk void (*add)(struct mtd_info *mtd); 534932394acSWolfgang Denk void (*remove)(struct mtd_info *mtd); 535932394acSWolfgang Denk struct list_head list; 536932394acSWolfgang Denk }; 537932394acSWolfgang Denk 538ff94bc40SHeiko Schocher 539932394acSWolfgang Denk extern void register_mtd_user (struct mtd_notifier *new); 540932394acSWolfgang Denk extern int unregister_mtd_user (struct mtd_notifier *old); 541932394acSWolfgang Denk #endif 542ff94bc40SHeiko Schocher void *mtd_kmalloc_up_to(const struct mtd_info *mtd, size_t *size); 543932394acSWolfgang Denk 544932394acSWolfgang Denk #ifdef CONFIG_MTD_PARTITIONS 545932394acSWolfgang Denk void mtd_erase_callback(struct erase_info *instr); 546932394acSWolfgang Denk #else 547932394acSWolfgang Denk static inline void mtd_erase_callback(struct erase_info *instr) 548932394acSWolfgang Denk { 549932394acSWolfgang Denk if (instr->callback) 550932394acSWolfgang Denk instr->callback(instr); 551932394acSWolfgang Denk } 552932394acSWolfgang Denk #endif 553932394acSWolfgang Denk 554ff94bc40SHeiko Schocher #ifdef __UBOOT__ 555932394acSWolfgang Denk /* 556932394acSWolfgang Denk * Debugging macro and defines 557932394acSWolfgang Denk */ 558932394acSWolfgang Denk #define MTD_DEBUG_LEVEL0 (0) /* Quiet */ 559932394acSWolfgang Denk #define MTD_DEBUG_LEVEL1 (1) /* Audible */ 560932394acSWolfgang Denk #define MTD_DEBUG_LEVEL2 (2) /* Loud */ 561932394acSWolfgang Denk #define MTD_DEBUG_LEVEL3 (3) /* Noisy */ 562932394acSWolfgang Denk 563932394acSWolfgang Denk #ifdef CONFIG_MTD_DEBUG 5643167c538SScott Wood #define MTDDEBUG(n, args...) \ 565932394acSWolfgang Denk do { \ 566932394acSWolfgang Denk if (n <= CONFIG_MTD_DEBUG_VERBOSE) \ 567932394acSWolfgang Denk printk(KERN_INFO args); \ 568932394acSWolfgang Denk } while(0) 569932394acSWolfgang Denk #else /* CONFIG_MTD_DEBUG */ 570c45912d8SScott Wood #define MTDDEBUG(n, args...) \ 571c45912d8SScott Wood do { \ 572c45912d8SScott Wood if (0) \ 573c45912d8SScott Wood printk(KERN_INFO args); \ 574c45912d8SScott Wood } while(0) 575932394acSWolfgang Denk #endif /* CONFIG_MTD_DEBUG */ 576ff94bc40SHeiko Schocher #endif 577dfe64e2cSSergey Lapin 578dfe64e2cSSergey Lapin static inline int mtd_is_bitflip(int err) { 579dfe64e2cSSergey Lapin return err == -EUCLEAN; 580dfe64e2cSSergey Lapin } 581dfe64e2cSSergey Lapin 582dfe64e2cSSergey Lapin static inline int mtd_is_eccerr(int err) { 583dfe64e2cSSergey Lapin return err == -EBADMSG; 584dfe64e2cSSergey Lapin } 585dfe64e2cSSergey Lapin 586dfe64e2cSSergey Lapin static inline int mtd_is_bitflip_or_eccerr(int err) { 587dfe64e2cSSergey Lapin return mtd_is_bitflip(err) || mtd_is_eccerr(err); 588dfe64e2cSSergey Lapin } 589932394acSWolfgang Denk 5900195a7bbSHeiko Schocher unsigned mtd_mmap_capabilities(struct mtd_info *mtd); 5910195a7bbSHeiko Schocher 592ff94bc40SHeiko Schocher #ifdef __UBOOT__ 593ff94bc40SHeiko Schocher /* drivers/mtd/mtdcore.h */ 594ff94bc40SHeiko Schocher int add_mtd_device(struct mtd_info *mtd); 595ddf7bcfaSHeiko Schocher int del_mtd_device(struct mtd_info *mtd); 596002d1762SBoris Brezillon 597002d1762SBoris Brezillon #ifdef CONFIG_MTD_PARTITIONS 598ff94bc40SHeiko Schocher int add_mtd_partitions(struct mtd_info *, const struct mtd_partition *, int); 599ff94bc40SHeiko Schocher int del_mtd_partitions(struct mtd_info *); 600002d1762SBoris Brezillon #else 601002d1762SBoris Brezillon static inline int add_mtd_partitions(struct mtd_info *mtd, 602002d1762SBoris Brezillon const struct mtd_partition *parts, 603002d1762SBoris Brezillon int nparts) 604002d1762SBoris Brezillon { 605002d1762SBoris Brezillon return 0; 606002d1762SBoris Brezillon } 607002d1762SBoris Brezillon 608002d1762SBoris Brezillon static inline int del_mtd_partitions(struct mtd_info *mtd) 609002d1762SBoris Brezillon { 610002d1762SBoris Brezillon return 0; 611002d1762SBoris Brezillon } 612002d1762SBoris Brezillon #endif 61309c32807SHeiko Schocher 614ac199d13SMiquel Raynal struct mtd_info *__mtd_next_device(int i); 615ac199d13SMiquel Raynal #define mtd_for_each_device(mtd) \ 616ac199d13SMiquel Raynal for ((mtd) = __mtd_next_device(0); \ 617ac199d13SMiquel Raynal (mtd) != NULL; \ 618ac199d13SMiquel Raynal (mtd) = __mtd_next_device(mtd->index + 1)) 619ac199d13SMiquel Raynal 62009c32807SHeiko Schocher int mtd_arg_off(const char *arg, int *idx, loff_t *off, loff_t *size, 621f18d1116SMasahiro Yamada loff_t *maxsize, int devtype, uint64_t chipsize); 62209c32807SHeiko Schocher int mtd_arg_off_size(int argc, char *const argv[], int *idx, loff_t *off, 623f18d1116SMasahiro Yamada loff_t *size, loff_t *maxsize, int devtype, 624f18d1116SMasahiro Yamada uint64_t chipsize); 62559441ac3SSteve Rae 62659441ac3SSteve Rae /* drivers/mtd/mtdcore.c */ 62759441ac3SSteve Rae void mtd_get_len_incl_bad(struct mtd_info *mtd, uint64_t offset, 62859441ac3SSteve Rae const uint64_t length, uint64_t *len_incl_bad, 62959441ac3SSteve Rae int *truncated); 63090108c6cSBoris Brezillon bool mtd_dev_list_updated(void); 63150466819SMiquel Raynal 63250466819SMiquel Raynal /* drivers/mtd/mtd_uboot.c */ 63350466819SMiquel Raynal int mtd_search_alternate_name(const char *mtdname, char *altname, 63450466819SMiquel Raynal unsigned int max_len); 63550466819SMiquel Raynal 636ff94bc40SHeiko Schocher #endif 637932394acSWolfgang Denk #endif /* __MTD_MTD_H__ */ 638