linux/include/linux/mtd/map.h
<<
>>
Prefs
   1
   2/* Overhauled routines for dealing with different mmap regions of flash */
   3
   4#ifndef __LINUX_MTD_MAP_H__
   5#define __LINUX_MTD_MAP_H__
   6
   7#include <linux/types.h>
   8#include <linux/list.h>
   9#include <linux/string.h>
  10
  11#include <linux/mtd/compatmac.h>
  12
  13#include <asm/unaligned.h>
  14#include <asm/system.h>
  15#include <asm/io.h>
  16
  17#ifdef CONFIG_MTD_MAP_BANK_WIDTH_1
  18#define map_bankwidth(map) 1
  19#define map_bankwidth_is_1(map) (map_bankwidth(map) == 1)
  20#define map_bankwidth_is_large(map) (0)
  21#define map_words(map) (1)
  22#define MAX_MAP_BANKWIDTH 1
  23#else
  24#define map_bankwidth_is_1(map) (0)
  25#endif
  26
  27#ifdef CONFIG_MTD_MAP_BANK_WIDTH_2
  28# ifdef map_bankwidth
  29#  undef map_bankwidth
  30#  define map_bankwidth(map) ((map)->bankwidth)
  31# else
  32#  define map_bankwidth(map) 2
  33#  define map_bankwidth_is_large(map) (0)
  34#  define map_words(map) (1)
  35# endif
  36#define map_bankwidth_is_2(map) (map_bankwidth(map) == 2)
  37#undef MAX_MAP_BANKWIDTH
  38#define MAX_MAP_BANKWIDTH 2
  39#else
  40#define map_bankwidth_is_2(map) (0)
  41#endif
  42
  43#ifdef CONFIG_MTD_MAP_BANK_WIDTH_4
  44# ifdef map_bankwidth
  45#  undef map_bankwidth
  46#  define map_bankwidth(map) ((map)->bankwidth)
  47# else
  48#  define map_bankwidth(map) 4
  49#  define map_bankwidth_is_large(map) (0)
  50#  define map_words(map) (1)
  51# endif
  52#define map_bankwidth_is_4(map) (map_bankwidth(map) == 4)
  53#undef MAX_MAP_BANKWIDTH
  54#define MAX_MAP_BANKWIDTH 4
  55#else
  56#define map_bankwidth_is_4(map) (0)
  57#endif
  58
  59/* ensure we never evaluate anything shorted than an unsigned long
  60 * to zero, and ensure we'll never miss the end of an comparison (bjd) */
  61
  62#define map_calc_words(map) ((map_bankwidth(map) + (sizeof(unsigned long)-1))/ sizeof(unsigned long))
  63
  64#ifdef CONFIG_MTD_MAP_BANK_WIDTH_8
  65# ifdef map_bankwidth
  66#  undef map_bankwidth
  67#  define map_bankwidth(map) ((map)->bankwidth)
  68#  if BITS_PER_LONG < 64
  69#   undef map_bankwidth_is_large
  70#   define map_bankwidth_is_large(map) (map_bankwidth(map) > BITS_PER_LONG/8)
  71#   undef map_words
  72#   define map_words(map) map_calc_words(map)
  73#  endif
  74# else
  75#  define map_bankwidth(map) 8
  76#  define map_bankwidth_is_large(map) (BITS_PER_LONG < 64)
  77#  define map_words(map) map_calc_words(map)
  78# endif
  79#define map_bankwidth_is_8(map) (map_bankwidth(map) == 8)
  80#undef MAX_MAP_BANKWIDTH
  81#define MAX_MAP_BANKWIDTH 8
  82#else
  83#define map_bankwidth_is_8(map) (0)
  84#endif
  85
  86#ifdef CONFIG_MTD_MAP_BANK_WIDTH_16
  87# ifdef map_bankwidth
  88#  undef map_bankwidth
  89#  define map_bankwidth(map) ((map)->bankwidth)
  90#  undef map_bankwidth_is_large
  91#  define map_bankwidth_is_large(map) (map_bankwidth(map) > BITS_PER_LONG/8)
  92#  undef map_words
  93#  define map_words(map) map_calc_words(map)
  94# else
  95#  define map_bankwidth(map) 16
  96#  define map_bankwidth_is_large(map) (1)
  97#  define map_words(map) map_calc_words(map)
  98# endif
  99#define map_bankwidth_is_16(map) (map_bankwidth(map) == 16)
 100#undef MAX_MAP_BANKWIDTH
 101#define MAX_MAP_BANKWIDTH 16
 102#else
 103#define map_bankwidth_is_16(map) (0)
 104#endif
 105
 106#ifdef CONFIG_MTD_MAP_BANK_WIDTH_32
 107# ifdef map_bankwidth
 108#  undef map_bankwidth
 109#  define map_bankwidth(map) ((map)->bankwidth)
 110#  undef map_bankwidth_is_large
 111#  define map_bankwidth_is_large(map) (map_bankwidth(map) > BITS_PER_LONG/8)
 112#  undef map_words
 113#  define map_words(map) map_calc_words(map)
 114# else
 115#  define map_bankwidth(map) 32
 116#  define map_bankwidth_is_large(map) (1)
 117#  define map_words(map) map_calc_words(map)
 118# endif
 119#define map_bankwidth_is_32(map) (map_bankwidth(map) == 32)
 120#undef MAX_MAP_BANKWIDTH
 121#define MAX_MAP_BANKWIDTH 32
 122#else
 123#define map_bankwidth_is_32(map) (0)
 124#endif
 125
 126#ifndef map_bankwidth
 127#warning "No CONFIG_MTD_MAP_BANK_WIDTH_xx selected. No NOR chip support can work"
 128static inline int map_bankwidth(void *map)
 129{
 130        BUG();
 131        return 0;
 132}
 133#define map_bankwidth_is_large(map) (0)
 134#define map_words(map) (0)
 135#define MAX_MAP_BANKWIDTH 1
 136#endif
 137
 138static inline int map_bankwidth_supported(int w)
 139{
 140        switch (w) {
 141#ifdef CONFIG_MTD_MAP_BANK_WIDTH_1
 142        case 1:
 143#endif
 144#ifdef CONFIG_MTD_MAP_BANK_WIDTH_2
 145        case 2:
 146#endif
 147#ifdef CONFIG_MTD_MAP_BANK_WIDTH_4
 148        case 4:
 149#endif
 150#ifdef CONFIG_MTD_MAP_BANK_WIDTH_8
 151        case 8:
 152#endif
 153#ifdef CONFIG_MTD_MAP_BANK_WIDTH_16
 154        case 16:
 155#endif
 156#ifdef CONFIG_MTD_MAP_BANK_WIDTH_32
 157        case 32:
 158#endif
 159                return 1;
 160
 161        default:
 162                return 0;
 163        }
 164}
 165
 166#define MAX_MAP_LONGS ( ((MAX_MAP_BANKWIDTH*8) + BITS_PER_LONG - 1) / BITS_PER_LONG )
 167
 168typedef union {
 169        unsigned long x[MAX_MAP_LONGS];
 170} map_word;
 171
 172/* The map stuff is very simple. You fill in your struct map_info with
 173   a handful of routines for accessing the device, making sure they handle
 174   paging etc. correctly if your device needs it. Then you pass it off
 175   to a chip probe routine -- either JEDEC or CFI probe or both -- via
 176   do_map_probe(). If a chip is recognised, the probe code will invoke the
 177   appropriate chip driver (if present) and return a struct mtd_info.
 178   At which point, you fill in the mtd->module with your own module
 179   address, and register it with the MTD core code. Or you could partition
 180   it and register the partitions instead, or keep it for your own private
 181   use; whatever.
 182
 183   The mtd->priv field will point to the struct map_info, and any further
 184   private data required by the chip driver is linked from the
 185   mtd->priv->fldrv_priv field. This allows the map driver to get at
 186   the destructor function map->fldrv_destroy() when it's tired
 187   of living.
 188*/
 189
 190struct map_info {
 191        const char *name;
 192        unsigned long size;
 193        resource_size_t phys;
 194#define NO_XIP (-1UL)
 195
 196        void __iomem *virt;
 197        void *cached;
 198
 199        int bankwidth; /* in octets. This isn't necessarily the width
 200                       of actual bus cycles -- it's the repeat interval
 201                      in bytes, before you are talking to the first chip again.
 202                      */
 203
 204#ifdef CONFIG_MTD_COMPLEX_MAPPINGS
 205        map_word (*read)(struct map_info *, unsigned long);
 206        void (*copy_from)(struct map_info *, void *, unsigned long, ssize_t);
 207
 208        void (*write)(struct map_info *, const map_word, unsigned long);
 209        void (*copy_to)(struct map_info *, unsigned long, const void *, ssize_t);
 210
 211        /* We can perhaps put in 'point' and 'unpoint' methods, if we really
 212           want to enable XIP for non-linear mappings. Not yet though. */
 213#endif
 214        /* It's possible for the map driver to use cached memory in its
 215           copy_from implementation (and _only_ with copy_from).  However,
 216           when the chip driver knows some flash area has changed contents,
 217           it will signal it to the map driver through this routine to let
 218           the map driver invalidate the corresponding cache as needed.
 219           If there is no cache to care about this can be set to NULL. */
 220        void (*inval_cache)(struct map_info *, unsigned long, ssize_t);
 221
 222        /* set_vpp() must handle being reentered -- enable, enable, disable
 223           must leave it enabled. */
 224        void (*set_vpp)(struct map_info *, int);
 225
 226        unsigned long map_priv_1;
 227        unsigned long map_priv_2;
 228        void *fldrv_priv;
 229        struct mtd_chip_driver *fldrv;
 230};
 231
 232struct mtd_chip_driver {
 233        struct mtd_info *(*probe)(struct map_info *map);
 234        void (*destroy)(struct mtd_info *);
 235        struct module *module;
 236        char *name;
 237        struct list_head list;
 238};
 239
 240void register_mtd_chip_driver(struct mtd_chip_driver *);
 241void unregister_mtd_chip_driver(struct mtd_chip_driver *);
 242
 243struct mtd_info *do_map_probe(const char *name, struct map_info *map);
 244void map_destroy(struct mtd_info *mtd);
 245
 246#define ENABLE_VPP(map) do { if(map->set_vpp) map->set_vpp(map, 1); } while(0)
 247#define DISABLE_VPP(map) do { if(map->set_vpp) map->set_vpp(map, 0); } while(0)
 248
 249#define INVALIDATE_CACHED_RANGE(map, from, size) \
 250        do { if(map->inval_cache) map->inval_cache(map, from, size); } while(0)
 251
 252
 253static inline int map_word_equal(struct map_info *map, map_word val1, map_word val2)
 254{
 255        int i;
 256        for (i=0; i<map_words(map); i++) {
 257                if (val1.x[i] != val2.x[i])
 258                        return 0;
 259        }
 260        return 1;
 261}
 262
 263static inline map_word map_word_and(struct map_info *map, map_word val1, map_word val2)
 264{
 265        map_word r;
 266        int i;
 267
 268        for (i=0; i<map_words(map); i++) {
 269                r.x[i] = val1.x[i] & val2.x[i];
 270        }
 271        return r;
 272}
 273
 274static inline map_word map_word_clr(struct map_info *map, map_word val1, map_word val2)
 275{
 276        map_word r;
 277        int i;
 278
 279        for (i=0; i<map_words(map); i++) {
 280                r.x[i] = val1.x[i] & ~val2.x[i];
 281        }
 282        return r;
 283}
 284
 285static inline map_word map_word_or(struct map_info *map, map_word val1, map_word val2)
 286{
 287        map_word r;
 288        int i;
 289
 290        for (i=0; i<map_words(map); i++) {
 291                r.x[i] = val1.x[i] | val2.x[i];
 292        }
 293        return r;
 294}
 295
 296#define map_word_andequal(m, a, b, z) map_word_equal(m, z, map_word_and(m, a, b))
 297
 298static inline int map_word_bitsset(struct map_info *map, map_word val1, map_word val2)
 299{
 300        int i;
 301
 302        for (i=0; i<map_words(map); i++) {
 303                if (val1.x[i] & val2.x[i])
 304                        return 1;
 305        }
 306        return 0;
 307}
 308
 309static inline map_word map_word_load(struct map_info *map, const void *ptr)
 310{
 311        map_word r;
 312
 313        if (map_bankwidth_is_1(map))
 314                r.x[0] = *(unsigned char *)ptr;
 315        else if (map_bankwidth_is_2(map))
 316                r.x[0] = get_unaligned((uint16_t *)ptr);
 317        else if (map_bankwidth_is_4(map))
 318                r.x[0] = get_unaligned((uint32_t *)ptr);
 319#if BITS_PER_LONG >= 64
 320        else if (map_bankwidth_is_8(map))
 321                r.x[0] = get_unaligned((uint64_t *)ptr);
 322#endif
 323        else if (map_bankwidth_is_large(map))
 324                memcpy(r.x, ptr, map->bankwidth);
 325
 326        return r;
 327}
 328
 329static inline map_word map_word_load_partial(struct map_info *map, map_word orig, const unsigned char *buf, int start, int len)
 330{
 331        int i;
 332
 333        if (map_bankwidth_is_large(map)) {
 334                char *dest = (char *)&orig;
 335                memcpy(dest+start, buf, len);
 336        } else {
 337                for (i=start; i < start+len; i++) {
 338                        int bitpos;
 339#ifdef __LITTLE_ENDIAN
 340                        bitpos = i*8;
 341#else /* __BIG_ENDIAN */
 342                        bitpos = (map_bankwidth(map)-1-i)*8;
 343#endif
 344                        orig.x[0] &= ~(0xff << bitpos);
 345                        orig.x[0] |= buf[i-start] << bitpos;
 346                }
 347        }
 348        return orig;
 349}
 350
 351#if BITS_PER_LONG < 64
 352#define MAP_FF_LIMIT 4
 353#else
 354#define MAP_FF_LIMIT 8
 355#endif
 356
 357static inline map_word map_word_ff(struct map_info *map)
 358{
 359        map_word r;
 360        int i;
 361
 362        if (map_bankwidth(map) < MAP_FF_LIMIT) {
 363                int bw = 8 * map_bankwidth(map);
 364                r.x[0] = (1 << bw) - 1;
 365        } else {
 366                for (i=0; i<map_words(map); i++)
 367                        r.x[i] = ~0UL;
 368        }
 369        return r;
 370}
 371
 372static inline map_word inline_map_read(struct map_info *map, unsigned long ofs)
 373{
 374        map_word r;
 375
 376        if (map_bankwidth_is_1(map))
 377                r.x[0] = __raw_readb(map->virt + ofs);
 378        else if (map_bankwidth_is_2(map))
 379                r.x[0] = __raw_readw(map->virt + ofs);
 380        else if (map_bankwidth_is_4(map))
 381                r.x[0] = __raw_readl(map->virt + ofs);
 382#if BITS_PER_LONG >= 64
 383        else if (map_bankwidth_is_8(map))
 384                r.x[0] = __raw_readq(map->virt + ofs);
 385#endif
 386        else if (map_bankwidth_is_large(map))
 387                memcpy_fromio(r.x, map->virt+ofs, map->bankwidth);
 388
 389        return r;
 390}
 391
 392static inline void inline_map_write(struct map_info *map, const map_word datum, unsigned long ofs)
 393{
 394        if (map_bankwidth_is_1(map))
 395                __raw_writeb(datum.x[0], map->virt + ofs);
 396        else if (map_bankwidth_is_2(map))
 397                __raw_writew(datum.x[0], map->virt + ofs);
 398        else if (map_bankwidth_is_4(map))
 399                __raw_writel(datum.x[0], map->virt + ofs);
 400#if BITS_PER_LONG >= 64
 401        else if (map_bankwidth_is_8(map))
 402                __raw_writeq(datum.x[0], map->virt + ofs);
 403#endif
 404        else if (map_bankwidth_is_large(map))
 405                memcpy_toio(map->virt+ofs, datum.x, map->bankwidth);
 406        mb();
 407}
 408
 409static inline void inline_map_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
 410{
 411        if (map->cached)
 412                memcpy(to, (char *)map->cached + from, len);
 413        else
 414                memcpy_fromio(to, map->virt + from, len);
 415}
 416
 417static inline void inline_map_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
 418{
 419        memcpy_toio(map->virt + to, from, len);
 420}
 421
 422#ifdef CONFIG_MTD_COMPLEX_MAPPINGS
 423#define map_read(map, ofs) (map)->read(map, ofs)
 424#define map_copy_from(map, to, from, len) (map)->copy_from(map, to, from, len)
 425#define map_write(map, datum, ofs) (map)->write(map, datum, ofs)
 426#define map_copy_to(map, to, from, len) (map)->copy_to(map, to, from, len)
 427
 428extern void simple_map_init(struct map_info *);
 429#define map_is_linear(map) (map->phys != NO_XIP)
 430
 431#else
 432#define map_read(map, ofs) inline_map_read(map, ofs)
 433#define map_copy_from(map, to, from, len) inline_map_copy_from(map, to, from, len)
 434#define map_write(map, datum, ofs) inline_map_write(map, datum, ofs)
 435#define map_copy_to(map, to, from, len) inline_map_copy_to(map, to, from, len)
 436
 437
 438#define simple_map_init(map) BUG_ON(!map_bankwidth_supported((map)->bankwidth))
 439#define map_is_linear(map) ({ (void)(map); 1; })
 440
 441#endif /* !CONFIG_MTD_COMPLEX_MAPPINGS */
 442
 443#endif /* __LINUX_MTD_MAP_H__ */
 444
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.