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