X-Git-Url: https://git.kernelconcepts.de/?p=karo-tx-uboot.git;a=blobdiff_plain;f=include%2Flinux%2Fmtd%2Fmtd.h;h=1526d075c7889f04e6117d230f2982d15b7cdc5a;hp=55d33dd11ebaa22ec0149eb4fc01985564856c33;hb=5ddc329341a9a143f0567494e5f874008b22e1a7;hpb=4b0708093e15b412296328bf81325cf9b69fe512 diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h index 55d33dd11e..1526d075c7 100644 --- a/include/linux/mtd/mtd.h +++ b/include/linux/mtd/mtd.h @@ -1,84 +1,68 @@ /* - * $Id: mtd.h,v 1.61 2005/11/07 11:14:54 gleixner Exp $ - * - * Copyright (C) 1999-2003 David Woodhouse et al. + * Copyright © 1999-2010 David Woodhouse et al. * * Released under GPL + * */ #ifndef __MTD_MTD_H__ #define __MTD_MTD_H__ +#define __UBOOT__ +#ifndef __UBOOT__ #include -#include +#include +#include +#include + +#include + +#include +#else +#include +#include +#include +#include -#define MTD_CHAR_MAJOR 90 -#define MTD_BLOCK_MAJOR 31 #define MAX_MTD_DEVICES 32 +#endif #define MTD_ERASE_PENDING 0x01 #define MTD_ERASING 0x02 #define MTD_ERASE_SUSPEND 0x04 -#define MTD_ERASE_DONE 0x08 -#define MTD_ERASE_FAILED 0x10 +#define MTD_ERASE_DONE 0x08 +#define MTD_ERASE_FAILED 0x10 + +#define MTD_FAIL_ADDR_UNKNOWN -1LL /* - * Enumeration for NAND/OneNAND flash chip state + * If the erase fails, fail_addr might indicate exactly which block failed. If + * fail_addr = MTD_FAIL_ADDR_UNKNOWN, the failure was not at the device level + * or was not specific to any particular block. */ -enum { - FL_READY, - FL_READING, - FL_WRITING, - FL_ERASING, - FL_SYNCING, - FL_CACHEDPRG, - FL_RESETING, - FL_UNLOCKING, - FL_LOCKING, - FL_PM_SUSPENDED, -}; - -/* If the erase fails, fail_addr might indicate exactly which block failed. If - fail_addr = 0xffffffff, the failure was not at the device level or was not - specific to any particular block. */ struct erase_info { struct mtd_info *mtd; - u_int32_t addr; - u_int32_t len; - u_int32_t fail_addr; + uint64_t addr; + uint64_t len; + uint64_t fail_addr; u_long time; u_long retries; - u_int dev; - u_int cell; + unsigned dev; + unsigned cell; void (*callback) (struct erase_info *self); u_long priv; u_char state; struct erase_info *next; + int scrub; }; struct mtd_erase_region_info { - u_int32_t offset; /* At which this region starts, from the beginning of the MTD */ - u_int32_t erasesize; /* For this region */ - u_int32_t numblocks; /* Number of blocks of erasesize in this region */ + uint64_t offset; /* At which this region starts, from the beginning of the MTD */ + uint32_t erasesize; /* For this region */ + uint32_t numblocks; /* Number of blocks of erasesize in this region */ unsigned long *lockmap; /* If keeping bitmap of locks */ }; -/* - * oob operation modes - * - * MTD_OOB_PLACE: oob data are placed at the given offset - * MTD_OOB_AUTO: oob data are automatically placed at the free areas - * which are defined by the ecclayout - * MTD_OOB_RAW: mode to read raw data+oob in one chunk. The oob data - * is inserted into the data. Thats a raw image of the - * flash contents. - */ -typedef enum { - MTD_OOB_PLACE, - MTD_OOB_AUTO, - MTD_OOB_RAW, -} mtd_oob_mode_t; - /** * struct mtd_oob_ops - oob operation operands * @mode: operation mode @@ -90,16 +74,16 @@ typedef enum { * @ooblen: number of oob bytes to write/read * @oobretlen: number of oob bytes written/read * @ooboffs: offset of oob data in the oob area (only relevant when - * mode = MTD_OOB_PLACE) + * mode = MTD_OPS_PLACE_OOB or MTD_OPS_RAW) * @datbuf: data buffer - if NULL only oob data are read/written * @oobbuf: oob data buffer * - * Note, it is allowed to read more then one OOB area at one go, but not write. + * Note, it is allowed to read more than one OOB area at one go, but not write. * The interface assumes that the OOB write requests program only one page's * OOB area. */ struct mtd_oob_ops { - mtd_oob_mode_t mode; + unsigned int mode; size_t len; size_t retlen; size_t ooblen; @@ -109,16 +93,43 @@ struct mtd_oob_ops { uint8_t *oobbuf; }; +#ifdef CONFIG_SYS_NAND_MAX_OOBFREE +#define MTD_MAX_OOBFREE_ENTRIES_LARGE CONFIG_SYS_NAND_MAX_OOBFREE +#else +#define MTD_MAX_OOBFREE_ENTRIES_LARGE 32 +#endif + +#ifdef CONFIG_SYS_NAND_MAX_ECCPOS +#define MTD_MAX_ECCPOS_ENTRIES_LARGE CONFIG_SYS_NAND_MAX_ECCPOS +#else +#define MTD_MAX_ECCPOS_ENTRIES_LARGE 640 +#endif + +/* + * Internal ECC layout control structure. For historical reasons, there is a + * similar, smaller struct nand_ecclayout_user (in mtd-abi.h) that is retained + * for export to user-space via the ECCGETLAYOUT ioctl. + * nand_ecclayout should be expandable in the future simply by the above macros. + */ +struct nand_ecclayout { + __u32 eccbytes; + __u32 eccpos[MTD_MAX_ECCPOS_ENTRIES_LARGE]; + __u32 oobavail; + struct nand_oobfree oobfree[MTD_MAX_OOBFREE_ENTRIES_LARGE]; +}; + +struct module; /* only needed for owner field in mtd_info */ + struct mtd_info { u_char type; - u_int32_t flags; - u_int32_t size; /* Total size of the MTD */ + uint32_t flags; + uint64_t size; // Total size of the MTD /* "Major" erase size for the device. Naïve users may take this * to be the only erase size available, or may use the more detailed * information below if they desire */ - u_int32_t erasesize; + uint32_t erasesize; /* Minimal writable flash unit size. In case of NOR flash it is 1 (even * though individual bits can be cleared), in case of NAND flash it is * one NAND page (or half, or one-fourths of it), in case of ECC-ed NOR @@ -126,79 +137,127 @@ struct mtd_info { * Any driver registering a struct mtd_info must ensure a writesize of * 1 or larger. */ - u_int32_t writesize; + uint32_t writesize; - u_int32_t oobsize; /* Amount of OOB data per block (e.g. 16) */ - u_int32_t oobavail; /* Available OOB bytes per block */ + /* + * Size of the write buffer used by the MTD. MTD devices having a write + * buffer can write multiple writesize chunks at a time. E.g. while + * writing 4 * writesize bytes to a device with 2 * writesize bytes + * buffer the MTD driver can (but doesn't have to) do 2 writesize + * operations, but not 4. Currently, all NANDs have writebufsize + * equivalent to writesize (NAND page size). Some NOR flashes do have + * writebufsize greater than writesize. + */ + uint32_t writebufsize; + + uint32_t oobsize; // Amount of OOB data per block (e.g. 16) + uint32_t oobavail; // Available OOB bytes per block - /* Kernel-only stuff starts here. */ + /* + * If erasesize is a power of 2 then the shift is stored in + * erasesize_shift otherwise erasesize_shift is zero. Ditto writesize. + */ + unsigned int erasesize_shift; + unsigned int writesize_shift; + /* Masks based on erasesize_shift and writesize_shift */ + unsigned int erasesize_mask; + unsigned int writesize_mask; + + /* + * read ops return -EUCLEAN if max number of bitflips corrected on any + * one region comprising an ecc step equals or exceeds this value. + * Settable by driver, else defaults to ecc_strength. User can override + * in sysfs. N.B. The meaning of the -EUCLEAN return code has changed; + * see Documentation/ABI/testing/sysfs-class-mtd for more detail. + */ + unsigned int bitflip_threshold; + + // Kernel-only stuff starts here. +#ifndef __UBOOT__ + const char *name; +#else char *name; +#endif int index; - /* ecc layout structure pointer - read only ! */ + /* ECC layout structure pointer - read only! */ struct nand_ecclayout *ecclayout; + /* the ecc step size. */ + unsigned int ecc_step_size; + + /* max number of correctible bit errors per ecc step */ + unsigned int ecc_strength; + /* Data for variable erase regions. If numeraseregions is zero, * it means that the whole device has erasesize as given above. */ int numeraseregions; struct mtd_erase_region_info *eraseregions; - int (*erase) (struct mtd_info *mtd, struct erase_info *instr); - - /* This stuff for eXecute-In-Place */ - int (*point) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char **mtdbuf); - - /* We probably shouldn't allow XIP if the unpoint isn't a NULL */ - void (*unpoint) (struct mtd_info *mtd, u_char * addr, loff_t from, size_t len); - - - int (*read) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf); - int (*write) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf); - - int (*read_oob) (struct mtd_info *mtd, loff_t from, - struct mtd_oob_ops *ops); - int (*write_oob) (struct mtd_info *mtd, loff_t to, - struct mtd_oob_ops *ops); - /* - * Methods to access the protection register area, present in some - * flash devices. The user data is one time programmable but the - * factory data is read only. + * Do not call via these pointers, use corresponding mtd_*() + * wrappers instead. */ - int (*get_fact_prot_info) (struct mtd_info *mtd, struct otp_info *buf, size_t len); - int (*read_fact_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf); - int (*get_user_prot_info) (struct mtd_info *mtd, struct otp_info *buf, size_t len); - int (*read_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf); - int (*write_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf); - int (*lock_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len); - -/* XXX U-BOOT XXX */ -#if 0 - /* kvec-based read/write methods. - NB: The 'count' parameter is the number of _vectors_, each of - which contains an (ofs, len) tuple. - */ - int (*writev) (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, loff_t to, size_t *retlen); + int (*_erase) (struct mtd_info *mtd, struct erase_info *instr); +#ifndef __UBOOT__ + int (*_point) (struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, void **virt, resource_size_t *phys); + int (*_unpoint) (struct mtd_info *mtd, loff_t from, size_t len); #endif + unsigned long (*_get_unmapped_area) (struct mtd_info *mtd, + unsigned long len, + unsigned long offset, + unsigned long flags); + int (*_read) (struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *buf); + int (*_write) (struct mtd_info *mtd, loff_t to, size_t len, + size_t *retlen, const u_char *buf); + int (*_panic_write) (struct mtd_info *mtd, loff_t to, size_t len, + size_t *retlen, const u_char *buf); + int (*_read_oob) (struct mtd_info *mtd, loff_t from, + struct mtd_oob_ops *ops); + int (*_write_oob) (struct mtd_info *mtd, loff_t to, + struct mtd_oob_ops *ops); + int (*_get_fact_prot_info) (struct mtd_info *mtd, size_t len, + size_t *retlen, struct otp_info *buf); + int (*_read_fact_prot_reg) (struct mtd_info *mtd, loff_t from, + size_t len, size_t *retlen, u_char *buf); + int (*_get_user_prot_info) (struct mtd_info *mtd, size_t len, + size_t *retlen, struct otp_info *buf); + int (*_read_user_prot_reg) (struct mtd_info *mtd, loff_t from, + size_t len, size_t *retlen, u_char *buf); + int (*_write_user_prot_reg) (struct mtd_info *mtd, loff_t to, + size_t len, size_t *retlen, u_char *buf); + int (*_lock_user_prot_reg) (struct mtd_info *mtd, loff_t from, + size_t len); +#ifndef __UBOOT__ + int (*_writev) (struct mtd_info *mtd, const struct kvec *vecs, + unsigned long count, loff_t to, size_t *retlen); +#endif + void (*_sync) (struct mtd_info *mtd); + int (*_lock) (struct mtd_info *mtd, loff_t ofs, uint64_t len); + int (*_unlock) (struct mtd_info *mtd, loff_t ofs, uint64_t len); + int (*_is_locked) (struct mtd_info *mtd, loff_t ofs, uint64_t len); + int (*_block_isbad) (struct mtd_info *mtd, loff_t ofs); + int (*_block_markbad) (struct mtd_info *mtd, loff_t ofs); +#ifndef __UBOOT__ + int (*_suspend) (struct mtd_info *mtd); + void (*_resume) (struct mtd_info *mtd); +#endif + /* + * If the driver is something smart, like UBI, it may need to maintain + * its own reference counting. The below functions are only for driver. + */ + int (*_get_device) (struct mtd_info *mtd); + void (*_put_device) (struct mtd_info *mtd); - /* Sync */ - void (*sync) (struct mtd_info *mtd); - - /* Chip-supported device locking */ - int (*lock) (struct mtd_info *mtd, loff_t ofs, size_t len); - int (*unlock) (struct mtd_info *mtd, loff_t ofs, size_t len); - - /* Power Management functions */ - int (*suspend) (struct mtd_info *mtd); - void (*resume) (struct mtd_info *mtd); - - /* Bad block management functions */ - int (*block_isbad) (struct mtd_info *mtd, loff_t ofs); - int (*block_markbad) (struct mtd_info *mtd, loff_t ofs); +#ifndef __UBOOT__ + /* Backing device capabilities for this device + * - provides mmap capabilities + */ + struct backing_dev_info *backing_dev_info; -/* XXX U-BOOT XXX */ -#if 0 struct notifier_block reboot_notifier; /* default mode before reboot */ #endif @@ -210,44 +269,159 @@ struct mtd_info { void *priv; struct module *owner; +#ifndef __UBOOT__ + struct device dev; +#endif int usecount; - - /* If the driver is something smart, like UBI, it may need to maintain - * its own reference counting. The below functions are only for driver. - * The driver may register its callbacks. These callbacks are not - * supposed to be called by MTD users */ - int (*get_device) (struct mtd_info *mtd); - void (*put_device) (struct mtd_info *mtd); }; +int mtd_erase(struct mtd_info *mtd, struct erase_info *instr); +#ifndef __UBOOT__ +int mtd_point(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, + void **virt, resource_size_t *phys); +int mtd_unpoint(struct mtd_info *mtd, loff_t from, size_t len); +#endif +unsigned long mtd_get_unmapped_area(struct mtd_info *mtd, unsigned long len, + unsigned long offset, unsigned long flags); +int mtd_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, + u_char *buf); +int mtd_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, + const u_char *buf); +int mtd_panic_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, + const u_char *buf); + +int mtd_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops); + +static inline int mtd_write_oob(struct mtd_info *mtd, loff_t to, + struct mtd_oob_ops *ops) +{ + ops->retlen = ops->oobretlen = 0; + if (!mtd->_write_oob) + return -EOPNOTSUPP; + if (!(mtd->flags & MTD_WRITEABLE)) + return -EROFS; + return mtd->_write_oob(mtd, to, ops); +} - /* Kernel-side ioctl definitions */ +int mtd_get_fact_prot_info(struct mtd_info *mtd, size_t len, size_t *retlen, + struct otp_info *buf); +int mtd_read_fact_prot_reg(struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *buf); +int mtd_get_user_prot_info(struct mtd_info *mtd, size_t len, size_t *retlen, + struct otp_info *buf); +int mtd_read_user_prot_reg(struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *buf); +int mtd_write_user_prot_reg(struct mtd_info *mtd, loff_t to, size_t len, + size_t *retlen, u_char *buf); +int mtd_lock_user_prot_reg(struct mtd_info *mtd, loff_t from, size_t len); + +#ifndef __UBOOT__ +int mtd_writev(struct mtd_info *mtd, const struct kvec *vecs, + unsigned long count, loff_t to, size_t *retlen); +#endif + +static inline void mtd_sync(struct mtd_info *mtd) +{ + if (mtd->_sync) + mtd->_sync(mtd); +} + +int mtd_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len); +int mtd_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len); +int mtd_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len); +int mtd_block_isbad(struct mtd_info *mtd, loff_t ofs); +int mtd_block_markbad(struct mtd_info *mtd, loff_t ofs); + +#ifndef __UBOOT__ +static inline int mtd_suspend(struct mtd_info *mtd) +{ + return mtd->_suspend ? mtd->_suspend(mtd) : 0; +} + +static inline void mtd_resume(struct mtd_info *mtd) +{ + if (mtd->_resume) + mtd->_resume(mtd); +} +#endif + +static inline uint32_t mtd_div_by_eb(uint64_t sz, struct mtd_info *mtd) +{ + if (mtd->erasesize_shift) + return sz >> mtd->erasesize_shift; + do_div(sz, mtd->erasesize); + return sz; +} + +static inline uint32_t mtd_mod_by_eb(uint64_t sz, struct mtd_info *mtd) +{ + if (mtd->erasesize_shift) + return sz & mtd->erasesize_mask; + return do_div(sz, mtd->erasesize); +} + +static inline uint32_t mtd_div_by_ws(uint64_t sz, struct mtd_info *mtd) +{ + if (mtd->writesize_shift) + return sz >> mtd->writesize_shift; + do_div(sz, mtd->writesize); + return sz; +} + +static inline uint32_t mtd_mod_by_ws(uint64_t sz, struct mtd_info *mtd) +{ + if (mtd->writesize_shift) + return sz & mtd->writesize_mask; + return do_div(sz, mtd->writesize); +} + +static inline int mtd_has_oob(const struct mtd_info *mtd) +{ + return mtd->_read_oob && mtd->_write_oob; +} + +static inline int mtd_type_is_nand(const struct mtd_info *mtd) +{ + return mtd->type == MTD_NANDFLASH || mtd->type == MTD_MLCNANDFLASH; +} -extern int add_mtd_device(struct mtd_info *mtd); -extern int del_mtd_device (struct mtd_info *mtd); +static inline int mtd_can_have_bb(const struct mtd_info *mtd) +{ + return !!mtd->_block_isbad; +} + + /* Kernel-side ioctl definitions */ +struct mtd_partition; +struct mtd_part_parser_data; + +extern int mtd_device_parse_register(struct mtd_info *mtd, + const char * const *part_probe_types, + struct mtd_part_parser_data *parser_data, + const struct mtd_partition *defparts, + int defnr_parts); +#define mtd_device_register(master, parts, nr_parts) \ + mtd_device_parse_register(master, NULL, NULL, parts, nr_parts) +extern int mtd_device_unregister(struct mtd_info *master); extern struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num); +extern int __get_mtd_device(struct mtd_info *mtd); +extern void __put_mtd_device(struct mtd_info *mtd); extern struct mtd_info *get_mtd_device_nm(const char *name); - extern void put_mtd_device(struct mtd_info *mtd); -/* XXX U-BOOT XXX */ -#if 0 + +#ifndef __UBOOT__ struct mtd_notifier { void (*add)(struct mtd_info *mtd); void (*remove)(struct mtd_info *mtd); struct list_head list; }; + extern void register_mtd_user (struct mtd_notifier *new); extern int unregister_mtd_user (struct mtd_notifier *old); - -int default_mtd_writev(struct mtd_info *mtd, const struct kvec *vecs, - unsigned long count, loff_t to, size_t *retlen); - -int default_mtd_readv(struct mtd_info *mtd, struct kvec *vecs, - unsigned long count, loff_t from, size_t *retlen); #endif +void *mtd_kmalloc_up_to(const struct mtd_info *mtd, size_t *size); #ifdef CONFIG_MTD_PARTITIONS void mtd_erase_callback(struct erase_info *instr); @@ -259,6 +433,7 @@ static inline void mtd_erase_callback(struct erase_info *instr) } #endif +#ifdef __UBOOT__ /* * Debugging macro and defines */ @@ -268,13 +443,45 @@ static inline void mtd_erase_callback(struct erase_info *instr) #define MTD_DEBUG_LEVEL3 (3) /* Noisy */ #ifdef CONFIG_MTD_DEBUG +#define pr_debug(args...) MTDDEBUG(MTD_DEBUG_LEVEL0, args) #define MTDDEBUG(n, args...) \ do { \ if (n <= CONFIG_MTD_DEBUG_VERBOSE) \ printk(KERN_INFO args); \ } while(0) #else /* CONFIG_MTD_DEBUG */ -#define MTDDEBUG(n, args...) do { } while(0) +#define pr_debug(args...) +#define MTDDEBUG(n, args...) \ + do { \ + if (0) \ + printk(KERN_INFO args); \ + } while(0) #endif /* CONFIG_MTD_DEBUG */ +#define pr_info(args...) MTDDEBUG(MTD_DEBUG_LEVEL0, args) +#define pr_warn(args...) MTDDEBUG(MTD_DEBUG_LEVEL0, args) +#define pr_err(args...) MTDDEBUG(MTD_DEBUG_LEVEL0, args) +#define pr_crit(args...) MTDDEBUG(MTD_DEBUG_LEVEL0, args) +#define pr_cont(args...) MTDDEBUG(MTD_DEBUG_LEVEL0, args) +#define pr_notice(args...) MTDDEBUG(MTD_DEBUG_LEVEL0, args) +#endif + +static inline int mtd_is_bitflip(int err) { + return err == -EUCLEAN; +} + +static inline int mtd_is_eccerr(int err) { + return err == -EBADMSG; +} +static inline int mtd_is_bitflip_or_eccerr(int err) { + return mtd_is_bitflip(err) || mtd_is_eccerr(err); +} + +#ifdef __UBOOT__ +/* drivers/mtd/mtdcore.h */ +int add_mtd_device(struct mtd_info *mtd); +int del_mtd_device(struct mtd_info *mtd); +int add_mtd_partitions(struct mtd_info *, const struct mtd_partition *, int); +int del_mtd_partitions(struct mtd_info *); +#endif #endif /* __MTD_MTD_H__ */