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