Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0-or-later */
0002 /*
0003  * Copyright © 2000-2010 David Woodhouse <dwmw2@infradead.org> et al.
0004  */
0005 
0006 /* Overhauled routines for dealing with different mmap regions of flash */
0007 
0008 #ifndef __LINUX_MTD_MAP_H__
0009 #define __LINUX_MTD_MAP_H__
0010 
0011 #include <linux/types.h>
0012 #include <linux/list.h>
0013 #include <linux/string.h>
0014 #include <linux/bug.h>
0015 #include <linux/kernel.h>
0016 #include <linux/io.h>
0017 
0018 #include <asm/unaligned.h>
0019 #include <asm/barrier.h>
0020 
0021 #ifdef CONFIG_MTD_MAP_BANK_WIDTH_1
0022 #define map_bankwidth(map) 1
0023 #define map_bankwidth_is_1(map) (map_bankwidth(map) == 1)
0024 #define map_bankwidth_is_large(map) (0)
0025 #define map_words(map) (1)
0026 #define MAX_MAP_BANKWIDTH 1
0027 #else
0028 #define map_bankwidth_is_1(map) (0)
0029 #endif
0030 
0031 #ifdef CONFIG_MTD_MAP_BANK_WIDTH_2
0032 # ifdef map_bankwidth
0033 #  undef map_bankwidth
0034 #  define map_bankwidth(map) ((map)->bankwidth)
0035 # else
0036 #  define map_bankwidth(map) 2
0037 #  define map_bankwidth_is_large(map) (0)
0038 #  define map_words(map) (1)
0039 # endif
0040 #define map_bankwidth_is_2(map) (map_bankwidth(map) == 2)
0041 #undef MAX_MAP_BANKWIDTH
0042 #define MAX_MAP_BANKWIDTH 2
0043 #else
0044 #define map_bankwidth_is_2(map) (0)
0045 #endif
0046 
0047 #ifdef CONFIG_MTD_MAP_BANK_WIDTH_4
0048 # ifdef map_bankwidth
0049 #  undef map_bankwidth
0050 #  define map_bankwidth(map) ((map)->bankwidth)
0051 # else
0052 #  define map_bankwidth(map) 4
0053 #  define map_bankwidth_is_large(map) (0)
0054 #  define map_words(map) (1)
0055 # endif
0056 #define map_bankwidth_is_4(map) (map_bankwidth(map) == 4)
0057 #undef MAX_MAP_BANKWIDTH
0058 #define MAX_MAP_BANKWIDTH 4
0059 #else
0060 #define map_bankwidth_is_4(map) (0)
0061 #endif
0062 
0063 /* ensure we never evaluate anything shorted than an unsigned long
0064  * to zero, and ensure we'll never miss the end of an comparison (bjd) */
0065 
0066 #define map_calc_words(map) ((map_bankwidth(map) + (sizeof(unsigned long)-1)) / sizeof(unsigned long))
0067 
0068 #ifdef CONFIG_MTD_MAP_BANK_WIDTH_8
0069 # ifdef map_bankwidth
0070 #  undef map_bankwidth
0071 #  define map_bankwidth(map) ((map)->bankwidth)
0072 #  if BITS_PER_LONG < 64
0073 #   undef map_bankwidth_is_large
0074 #   define map_bankwidth_is_large(map) (map_bankwidth(map) > BITS_PER_LONG/8)
0075 #   undef map_words
0076 #   define map_words(map) map_calc_words(map)
0077 #  endif
0078 # else
0079 #  define map_bankwidth(map) 8
0080 #  define map_bankwidth_is_large(map) (BITS_PER_LONG < 64)
0081 #  define map_words(map) map_calc_words(map)
0082 # endif
0083 #define map_bankwidth_is_8(map) (map_bankwidth(map) == 8)
0084 #undef MAX_MAP_BANKWIDTH
0085 #define MAX_MAP_BANKWIDTH 8
0086 #else
0087 #define map_bankwidth_is_8(map) (0)
0088 #endif
0089 
0090 #ifdef CONFIG_MTD_MAP_BANK_WIDTH_16
0091 # ifdef map_bankwidth
0092 #  undef map_bankwidth
0093 #  define map_bankwidth(map) ((map)->bankwidth)
0094 #  undef map_bankwidth_is_large
0095 #  define map_bankwidth_is_large(map) (map_bankwidth(map) > BITS_PER_LONG/8)
0096 #  undef map_words
0097 #  define map_words(map) map_calc_words(map)
0098 # else
0099 #  define map_bankwidth(map) 16
0100 #  define map_bankwidth_is_large(map) (1)
0101 #  define map_words(map) map_calc_words(map)
0102 # endif
0103 #define map_bankwidth_is_16(map) (map_bankwidth(map) == 16)
0104 #undef MAX_MAP_BANKWIDTH
0105 #define MAX_MAP_BANKWIDTH 16
0106 #else
0107 #define map_bankwidth_is_16(map) (0)
0108 #endif
0109 
0110 #ifdef CONFIG_MTD_MAP_BANK_WIDTH_32
0111 /* always use indirect access for 256-bit to preserve kernel stack */
0112 # undef map_bankwidth
0113 # define map_bankwidth(map) ((map)->bankwidth)
0114 # undef map_bankwidth_is_large
0115 # define map_bankwidth_is_large(map) (map_bankwidth(map) > BITS_PER_LONG/8)
0116 # undef map_words
0117 # define map_words(map) map_calc_words(map)
0118 #define map_bankwidth_is_32(map) (map_bankwidth(map) == 32)
0119 #undef MAX_MAP_BANKWIDTH
0120 #define MAX_MAP_BANKWIDTH 32
0121 #else
0122 #define map_bankwidth_is_32(map) (0)
0123 #endif
0124 
0125 #ifndef map_bankwidth
0126 #ifdef CONFIG_MTD
0127 #warning "No CONFIG_MTD_MAP_BANK_WIDTH_xx selected. No NOR chip support can work"
0128 #endif
0129 static inline int map_bankwidth(void *map)
0130 {
0131     BUG();
0132     return 0;
0133 }
0134 #define map_bankwidth_is_large(map) (0)
0135 #define map_words(map) (0)
0136 #define MAX_MAP_BANKWIDTH 1
0137 #endif
0138 
0139 static inline int map_bankwidth_supported(int w)
0140 {
0141     switch (w) {
0142 #ifdef CONFIG_MTD_MAP_BANK_WIDTH_1
0143     case 1:
0144 #endif
0145 #ifdef CONFIG_MTD_MAP_BANK_WIDTH_2
0146     case 2:
0147 #endif
0148 #ifdef CONFIG_MTD_MAP_BANK_WIDTH_4
0149     case 4:
0150 #endif
0151 #ifdef CONFIG_MTD_MAP_BANK_WIDTH_8
0152     case 8:
0153 #endif
0154 #ifdef CONFIG_MTD_MAP_BANK_WIDTH_16
0155     case 16:
0156 #endif
0157 #ifdef CONFIG_MTD_MAP_BANK_WIDTH_32
0158     case 32:
0159 #endif
0160         return 1;
0161 
0162     default:
0163         return 0;
0164     }
0165 }
0166 
0167 #define MAX_MAP_LONGS (((MAX_MAP_BANKWIDTH * 8) + BITS_PER_LONG - 1) / BITS_PER_LONG)
0168 
0169 typedef union {
0170     unsigned long x[MAX_MAP_LONGS];
0171 } map_word;
0172 
0173 /* The map stuff is very simple. You fill in your struct map_info with
0174    a handful of routines for accessing the device, making sure they handle
0175    paging etc. correctly if your device needs it. Then you pass it off
0176    to a chip probe routine -- either JEDEC or CFI probe or both -- via
0177    do_map_probe(). If a chip is recognised, the probe code will invoke the
0178    appropriate chip driver (if present) and return a struct mtd_info.
0179    At which point, you fill in the mtd->module with your own module
0180    address, and register it with the MTD core code. Or you could partition
0181    it and register the partitions instead, or keep it for your own private
0182    use; whatever.
0183 
0184    The mtd->priv field will point to the struct map_info, and any further
0185    private data required by the chip driver is linked from the
0186    mtd->priv->fldrv_priv field. This allows the map driver to get at
0187    the destructor function map->fldrv_destroy() when it's tired
0188    of living.
0189 */
0190 
0191 struct map_info {
0192     const char *name;
0193     unsigned long size;
0194     resource_size_t phys;
0195 #define NO_XIP (-1UL)
0196 
0197     void __iomem *virt;
0198     void *cached;
0199 
0200     int swap; /* this mapping's byte-swapping requirement */
0201     int bankwidth; /* in octets. This isn't necessarily the width
0202                of actual bus cycles -- it's the repeat interval
0203               in bytes, before you are talking to the first chip again.
0204               */
0205 
0206 #ifdef CONFIG_MTD_COMPLEX_MAPPINGS
0207     map_word (*read)(struct map_info *, unsigned long);
0208     void (*copy_from)(struct map_info *, void *, unsigned long, ssize_t);
0209 
0210     void (*write)(struct map_info *, const map_word, unsigned long);
0211     void (*copy_to)(struct map_info *, unsigned long, const void *, ssize_t);
0212 
0213     /* We can perhaps put in 'point' and 'unpoint' methods, if we really
0214        want to enable XIP for non-linear mappings. Not yet though. */
0215 #endif
0216     /* It's possible for the map driver to use cached memory in its
0217        copy_from implementation (and _only_ with copy_from).  However,
0218        when the chip driver knows some flash area has changed contents,
0219        it will signal it to the map driver through this routine to let
0220        the map driver invalidate the corresponding cache as needed.
0221        If there is no cache to care about this can be set to NULL. */
0222     void (*inval_cache)(struct map_info *, unsigned long, ssize_t);
0223 
0224     /* This will be called with 1 as parameter when the first map user
0225      * needs VPP, and called with 0 when the last user exits. The map
0226      * core maintains a reference counter, and assumes that VPP is a
0227      * global resource applying to all mapped flash chips on the system.
0228      */
0229     void (*set_vpp)(struct map_info *, int);
0230 
0231     unsigned long pfow_base;
0232     unsigned long map_priv_1;
0233     unsigned long map_priv_2;
0234     struct device_node *device_node;
0235     void *fldrv_priv;
0236     struct mtd_chip_driver *fldrv;
0237 };
0238 
0239 struct mtd_chip_driver {
0240     struct mtd_info *(*probe)(struct map_info *map);
0241     void (*destroy)(struct mtd_info *);
0242     struct module *module;
0243     char *name;
0244     struct list_head list;
0245 };
0246 
0247 void register_mtd_chip_driver(struct mtd_chip_driver *);
0248 void unregister_mtd_chip_driver(struct mtd_chip_driver *);
0249 
0250 struct mtd_info *do_map_probe(const char *name, struct map_info *map);
0251 void map_destroy(struct mtd_info *mtd);
0252 
0253 #define ENABLE_VPP(map) do { if (map->set_vpp) map->set_vpp(map, 1); } while (0)
0254 #define DISABLE_VPP(map) do { if (map->set_vpp) map->set_vpp(map, 0); } while (0)
0255 
0256 #define INVALIDATE_CACHED_RANGE(map, from, size) \
0257     do { if (map->inval_cache) map->inval_cache(map, from, size); } while (0)
0258 
0259 #define map_word_equal(map, val1, val2)                 \
0260 ({                                  \
0261     int i, ret = 1;                         \
0262     for (i = 0; i < map_words(map); i++)                \
0263         if ((val1).x[i] != (val2).x[i]) {           \
0264             ret = 0;                    \
0265             break;                      \
0266         }                           \
0267     ret;                                \
0268 })
0269 
0270 #define map_word_and(map, val1, val2)                   \
0271 ({                                  \
0272     map_word r;                         \
0273     int i;                              \
0274     for (i = 0; i < map_words(map); i++)                \
0275         r.x[i] = (val1).x[i] & (val2).x[i];         \
0276     r;                              \
0277 })
0278 
0279 #define map_word_clr(map, val1, val2)                   \
0280 ({                                  \
0281     map_word r;                         \
0282     int i;                              \
0283     for (i = 0; i < map_words(map); i++)                \
0284         r.x[i] = (val1).x[i] & ~(val2).x[i];            \
0285     r;                              \
0286 })
0287 
0288 #define map_word_or(map, val1, val2)                    \
0289 ({                                  \
0290     map_word r;                         \
0291     int i;                              \
0292     for (i = 0; i < map_words(map); i++)                \
0293         r.x[i] = (val1).x[i] | (val2).x[i];         \
0294     r;                              \
0295 })
0296 
0297 #define map_word_andequal(map, val1, val2, val3)            \
0298 ({                                  \
0299     int i, ret = 1;                         \
0300     for (i = 0; i < map_words(map); i++) {              \
0301         if (((val1).x[i] & (val2).x[i]) != (val3).x[i]) {   \
0302             ret = 0;                    \
0303             break;                      \
0304         }                           \
0305     }                               \
0306     ret;                                \
0307 })
0308 
0309 #define map_word_bitsset(map, val1, val2)               \
0310 ({                                  \
0311     int i, ret = 0;                         \
0312     for (i = 0; i < map_words(map); i++) {              \
0313         if ((val1).x[i] & (val2).x[i]) {            \
0314             ret = 1;                    \
0315             break;                      \
0316         }                           \
0317     }                               \
0318     ret;                                \
0319 })
0320 
0321 static inline map_word map_word_load(struct map_info *map, const void *ptr)
0322 {
0323     map_word r;
0324 
0325     if (map_bankwidth_is_1(map))
0326         r.x[0] = *(unsigned char *)ptr;
0327     else if (map_bankwidth_is_2(map))
0328         r.x[0] = get_unaligned((uint16_t *)ptr);
0329     else if (map_bankwidth_is_4(map))
0330         r.x[0] = get_unaligned((uint32_t *)ptr);
0331 #if BITS_PER_LONG >= 64
0332     else if (map_bankwidth_is_8(map))
0333         r.x[0] = get_unaligned((uint64_t *)ptr);
0334 #endif
0335     else if (map_bankwidth_is_large(map))
0336         memcpy(r.x, ptr, map->bankwidth);
0337     else
0338         BUG();
0339 
0340     return r;
0341 }
0342 
0343 static inline map_word map_word_load_partial(struct map_info *map, map_word orig, const unsigned char *buf, int start, int len)
0344 {
0345     int i;
0346 
0347     if (map_bankwidth_is_large(map)) {
0348         char *dest = (char *)&orig;
0349 
0350         memcpy(dest+start, buf, len);
0351     } else {
0352         for (i = start; i < start+len; i++) {
0353             int bitpos;
0354 
0355 #ifdef __LITTLE_ENDIAN
0356             bitpos = i * 8;
0357 #else /* __BIG_ENDIAN */
0358             bitpos = (map_bankwidth(map) - 1 - i) * 8;
0359 #endif
0360             orig.x[0] &= ~(0xff << bitpos);
0361             orig.x[0] |= (unsigned long)buf[i-start] << bitpos;
0362         }
0363     }
0364     return orig;
0365 }
0366 
0367 #if BITS_PER_LONG < 64
0368 #define MAP_FF_LIMIT 4
0369 #else
0370 #define MAP_FF_LIMIT 8
0371 #endif
0372 
0373 static inline map_word map_word_ff(struct map_info *map)
0374 {
0375     map_word r;
0376     int i;
0377 
0378     if (map_bankwidth(map) < MAP_FF_LIMIT) {
0379         int bw = 8 * map_bankwidth(map);
0380 
0381         r.x[0] = (1UL << bw) - 1;
0382     } else {
0383         for (i = 0; i < map_words(map); i++)
0384             r.x[i] = ~0UL;
0385     }
0386     return r;
0387 }
0388 
0389 static inline map_word inline_map_read(struct map_info *map, unsigned long ofs)
0390 {
0391     map_word r;
0392 
0393     if (map_bankwidth_is_1(map))
0394         r.x[0] = __raw_readb(map->virt + ofs);
0395     else if (map_bankwidth_is_2(map))
0396         r.x[0] = __raw_readw(map->virt + ofs);
0397     else if (map_bankwidth_is_4(map))
0398         r.x[0] = __raw_readl(map->virt + ofs);
0399 #if BITS_PER_LONG >= 64
0400     else if (map_bankwidth_is_8(map))
0401         r.x[0] = __raw_readq(map->virt + ofs);
0402 #endif
0403     else if (map_bankwidth_is_large(map))
0404         memcpy_fromio(r.x, map->virt + ofs, map->bankwidth);
0405     else
0406         BUG();
0407 
0408     return r;
0409 }
0410 
0411 static inline void inline_map_write(struct map_info *map, const map_word datum, unsigned long ofs)
0412 {
0413     if (map_bankwidth_is_1(map))
0414         __raw_writeb(datum.x[0], map->virt + ofs);
0415     else if (map_bankwidth_is_2(map))
0416         __raw_writew(datum.x[0], map->virt + ofs);
0417     else if (map_bankwidth_is_4(map))
0418         __raw_writel(datum.x[0], map->virt + ofs);
0419 #if BITS_PER_LONG >= 64
0420     else if (map_bankwidth_is_8(map))
0421         __raw_writeq(datum.x[0], map->virt + ofs);
0422 #endif
0423     else if (map_bankwidth_is_large(map))
0424         memcpy_toio(map->virt+ofs, datum.x, map->bankwidth);
0425     else
0426         BUG();
0427     mb();
0428 }
0429 
0430 static inline void inline_map_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
0431 {
0432     if (map->cached)
0433         memcpy(to, (char *)map->cached + from, len);
0434     else
0435         memcpy_fromio(to, map->virt + from, len);
0436 }
0437 
0438 static inline void inline_map_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
0439 {
0440     memcpy_toio(map->virt + to, from, len);
0441 }
0442 
0443 #ifdef CONFIG_MTD_COMPLEX_MAPPINGS
0444 #define map_read(map, ofs) (map)->read(map, ofs)
0445 #define map_copy_from(map, to, from, len) (map)->copy_from(map, to, from, len)
0446 #define map_write(map, datum, ofs) (map)->write(map, datum, ofs)
0447 #define map_copy_to(map, to, from, len) (map)->copy_to(map, to, from, len)
0448 
0449 extern void simple_map_init(struct map_info *);
0450 #define map_is_linear(map) (map->phys != NO_XIP)
0451 
0452 #else
0453 #define map_read(map, ofs) inline_map_read(map, ofs)
0454 #define map_copy_from(map, to, from, len) inline_map_copy_from(map, to, from, len)
0455 #define map_write(map, datum, ofs) inline_map_write(map, datum, ofs)
0456 #define map_copy_to(map, to, from, len) inline_map_copy_to(map, to, from, len)
0457 
0458 
0459 #define simple_map_init(map) BUG_ON(!map_bankwidth_supported((map)->bankwidth))
0460 #define map_is_linear(map) ({ (void)(map); 1; })
0461 
0462 #endif /* !CONFIG_MTD_COMPLEX_MAPPINGS */
0463 
0464 #endif /* __LINUX_MTD_MAP_H__ */