1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22#ifndef __LINUX_MTD_MAP_H__
23#define __LINUX_MTD_MAP_H__
24
25#include <linux/types.h>
26#include <linux/list.h>
27#include <linux/string.h>
28#include <linux/bug.h>
29#include <linux/kernel.h>
30#include <linux/io.h>
31
32#include <asm/unaligned.h>
33#include <asm/barrier.h>
34
35#ifdef CONFIG_MTD_MAP_BANK_WIDTH_1
36#define map_bankwidth(map) 1
37#define map_bankwidth_is_1(map) (map_bankwidth(map) == 1)
38#define map_bankwidth_is_large(map) (0)
39#define map_words(map) (1)
40#define MAX_MAP_BANKWIDTH 1
41#else
42#define map_bankwidth_is_1(map) (0)
43#endif
44
45#ifdef CONFIG_MTD_MAP_BANK_WIDTH_2
46# ifdef map_bankwidth
47# undef map_bankwidth
48# define map_bankwidth(map) ((map)->bankwidth)
49# else
50# define map_bankwidth(map) 2
51# define map_bankwidth_is_large(map) (0)
52# define map_words(map) (1)
53# endif
54#define map_bankwidth_is_2(map) (map_bankwidth(map) == 2)
55#undef MAX_MAP_BANKWIDTH
56#define MAX_MAP_BANKWIDTH 2
57#else
58#define map_bankwidth_is_2(map) (0)
59#endif
60
61#ifdef CONFIG_MTD_MAP_BANK_WIDTH_4
62# ifdef map_bankwidth
63# undef map_bankwidth
64# define map_bankwidth(map) ((map)->bankwidth)
65# else
66# define map_bankwidth(map) 4
67# define map_bankwidth_is_large(map) (0)
68# define map_words(map) (1)
69# endif
70#define map_bankwidth_is_4(map) (map_bankwidth(map) == 4)
71#undef MAX_MAP_BANKWIDTH
72#define MAX_MAP_BANKWIDTH 4
73#else
74#define map_bankwidth_is_4(map) (0)
75#endif
76
77
78
79
80#define map_calc_words(map) ((map_bankwidth(map) + (sizeof(unsigned long)-1)) / sizeof(unsigned long))
81
82#ifdef CONFIG_MTD_MAP_BANK_WIDTH_8
83# ifdef map_bankwidth
84# undef map_bankwidth
85# define map_bankwidth(map) ((map)->bankwidth)
86# if BITS_PER_LONG < 64
87# undef map_bankwidth_is_large
88# define map_bankwidth_is_large(map) (map_bankwidth(map) > BITS_PER_LONG/8)
89# undef map_words
90# define map_words(map) map_calc_words(map)
91# endif
92# else
93# define map_bankwidth(map) 8
94# define map_bankwidth_is_large(map) (BITS_PER_LONG < 64)
95# define map_words(map) map_calc_words(map)
96# endif
97#define map_bankwidth_is_8(map) (map_bankwidth(map) == 8)
98#undef MAX_MAP_BANKWIDTH
99#define MAX_MAP_BANKWIDTH 8
100#else
101#define map_bankwidth_is_8(map) (0)
102#endif
103
104#ifdef CONFIG_MTD_MAP_BANK_WIDTH_16
105# ifdef map_bankwidth
106# undef map_bankwidth
107# define map_bankwidth(map) ((map)->bankwidth)
108# undef map_bankwidth_is_large
109# define map_bankwidth_is_large(map) (map_bankwidth(map) > BITS_PER_LONG/8)
110# undef map_words
111# define map_words(map) map_calc_words(map)
112# else
113# define map_bankwidth(map) 16
114# define map_bankwidth_is_large(map) (1)
115# define map_words(map) map_calc_words(map)
116# endif
117#define map_bankwidth_is_16(map) (map_bankwidth(map) == 16)
118#undef MAX_MAP_BANKWIDTH
119#define MAX_MAP_BANKWIDTH 16
120#else
121#define map_bankwidth_is_16(map) (0)
122#endif
123
124#ifdef CONFIG_MTD_MAP_BANK_WIDTH_32
125
126# undef map_bankwidth
127# define map_bankwidth(map) ((map)->bankwidth)
128# undef map_bankwidth_is_large
129# define map_bankwidth_is_large(map) (map_bankwidth(map) > BITS_PER_LONG/8)
130# undef map_words
131# define map_words(map) map_calc_words(map)
132#define map_bankwidth_is_32(map) (map_bankwidth(map) == 32)
133#undef MAX_MAP_BANKWIDTH
134#define MAX_MAP_BANKWIDTH 32
135#else
136#define map_bankwidth_is_32(map) (0)
137#endif
138
139#ifndef map_bankwidth
140#ifdef CONFIG_MTD
141#warning "No CONFIG_MTD_MAP_BANK_WIDTH_xx selected. No NOR chip support can work"
142#endif
143static inline int map_bankwidth(void *map)
144{
145 BUG();
146 return 0;
147}
148#define map_bankwidth_is_large(map) (0)
149#define map_words(map) (0)
150#define MAX_MAP_BANKWIDTH 1
151#endif
152
153static inline int map_bankwidth_supported(int w)
154{
155 switch (w) {
156#ifdef CONFIG_MTD_MAP_BANK_WIDTH_1
157 case 1:
158#endif
159#ifdef CONFIG_MTD_MAP_BANK_WIDTH_2
160 case 2:
161#endif
162#ifdef CONFIG_MTD_MAP_BANK_WIDTH_4
163 case 4:
164#endif
165#ifdef CONFIG_MTD_MAP_BANK_WIDTH_8
166 case 8:
167#endif
168#ifdef CONFIG_MTD_MAP_BANK_WIDTH_16
169 case 16:
170#endif
171#ifdef CONFIG_MTD_MAP_BANK_WIDTH_32
172 case 32:
173#endif
174 return 1;
175
176 default:
177 return 0;
178 }
179}
180
181#define MAX_MAP_LONGS (((MAX_MAP_BANKWIDTH * 8) + BITS_PER_LONG - 1) / BITS_PER_LONG)
182
183typedef union {
184 unsigned long x[MAX_MAP_LONGS];
185} map_word;
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205struct map_info {
206 const char *name;
207 unsigned long size;
208 resource_size_t phys;
209#define NO_XIP (-1UL)
210
211 void __iomem *virt;
212 void *cached;
213
214 int swap;
215 int bankwidth;
216
217
218
219
220#ifdef CONFIG_MTD_COMPLEX_MAPPINGS
221 map_word (*read)(struct map_info *, unsigned long);
222 void (*copy_from)(struct map_info *, void *, unsigned long, ssize_t);
223
224 void (*write)(struct map_info *, const map_word, unsigned long);
225 void (*copy_to)(struct map_info *, unsigned long, const void *, ssize_t);
226
227
228
229#endif
230
231
232
233
234
235
236 void (*inval_cache)(struct map_info *, unsigned long, ssize_t);
237
238
239
240
241
242
243 void (*set_vpp)(struct map_info *, int);
244
245 unsigned long pfow_base;
246 unsigned long map_priv_1;
247 unsigned long map_priv_2;
248 struct device_node *device_node;
249 void *fldrv_priv;
250 struct mtd_chip_driver *fldrv;
251};
252
253struct mtd_chip_driver {
254 struct mtd_info *(*probe)(struct map_info *map);
255 void (*destroy)(struct mtd_info *);
256 struct module *module;
257 char *name;
258 struct list_head list;
259};
260
261void register_mtd_chip_driver(struct mtd_chip_driver *);
262void unregister_mtd_chip_driver(struct mtd_chip_driver *);
263
264struct mtd_info *do_map_probe(const char *name, struct map_info *map);
265void map_destroy(struct mtd_info *mtd);
266
267#define ENABLE_VPP(map) do { if (map->set_vpp) map->set_vpp(map, 1); } while (0)
268#define DISABLE_VPP(map) do { if (map->set_vpp) map->set_vpp(map, 0); } while (0)
269
270#define INVALIDATE_CACHED_RANGE(map, from, size) \
271 do { if (map->inval_cache) map->inval_cache(map, from, size); } while (0)
272
273#define map_word_equal(map, val1, val2) \
274({ \
275 int i, ret = 1; \
276 for (i = 0; i < map_words(map); i++) \
277 if ((val1).x[i] != (val2).x[i]) { \
278 ret = 0; \
279 break; \
280 } \
281 ret; \
282})
283
284#define map_word_and(map, val1, val2) \
285({ \
286 map_word r; \
287 int i; \
288 for (i = 0; i < map_words(map); i++) \
289 r.x[i] = (val1).x[i] & (val2).x[i]; \
290 r; \
291})
292
293#define map_word_clr(map, val1, val2) \
294({ \
295 map_word r; \
296 int i; \
297 for (i = 0; i < map_words(map); i++) \
298 r.x[i] = (val1).x[i] & ~(val2).x[i]; \
299 r; \
300})
301
302#define map_word_or(map, val1, val2) \
303({ \
304 map_word r; \
305 int i; \
306 for (i = 0; i < map_words(map); i++) \
307 r.x[i] = (val1).x[i] | (val2).x[i]; \
308 r; \
309})
310
311#define map_word_andequal(map, val1, val2, val3) \
312({ \
313 int i, ret = 1; \
314 for (i = 0; i < map_words(map); i++) { \
315 if (((val1).x[i] & (val2).x[i]) != (val3).x[i]) { \
316 ret = 0; \
317 break; \
318 } \
319 } \
320 ret; \
321})
322
323#define map_word_bitsset(map, val1, val2) \
324({ \
325 int i, ret = 0; \
326 for (i = 0; i < map_words(map); i++) { \
327 if ((val1).x[i] & (val2).x[i]) { \
328 ret = 1; \
329 break; \
330 } \
331 } \
332 ret; \
333})
334
335static inline map_word map_word_load(struct map_info *map, const void *ptr)
336{
337 map_word r;
338
339 if (map_bankwidth_is_1(map))
340 r.x[0] = *(unsigned char *)ptr;
341 else if (map_bankwidth_is_2(map))
342 r.x[0] = get_unaligned((uint16_t *)ptr);
343 else if (map_bankwidth_is_4(map))
344 r.x[0] = get_unaligned((uint32_t *)ptr);
345#if BITS_PER_LONG >= 64
346 else if (map_bankwidth_is_8(map))
347 r.x[0] = get_unaligned((uint64_t *)ptr);
348#endif
349 else if (map_bankwidth_is_large(map))
350 memcpy(r.x, ptr, map->bankwidth);
351 else
352 BUG();
353
354 return r;
355}
356
357static inline map_word map_word_load_partial(struct map_info *map, map_word orig, const unsigned char *buf, int start, int len)
358{
359 int i;
360
361 if (map_bankwidth_is_large(map)) {
362 char *dest = (char *)&orig;
363
364 memcpy(dest+start, buf, len);
365 } else {
366 for (i = start; i < start+len; i++) {
367 int bitpos;
368
369#ifdef __LITTLE_ENDIAN
370 bitpos = i * 8;
371#else
372 bitpos = (map_bankwidth(map) - 1 - i) * 8;
373#endif
374 orig.x[0] &= ~(0xff << bitpos);
375 orig.x[0] |= (unsigned long)buf[i-start] << bitpos;
376 }
377 }
378 return orig;
379}
380
381#if BITS_PER_LONG < 64
382#define MAP_FF_LIMIT 4
383#else
384#define MAP_FF_LIMIT 8
385#endif
386
387static inline map_word map_word_ff(struct map_info *map)
388{
389 map_word r;
390 int i;
391
392 if (map_bankwidth(map) < MAP_FF_LIMIT) {
393 int bw = 8 * map_bankwidth(map);
394
395 r.x[0] = (1UL << bw) - 1;
396 } else {
397 for (i = 0; i < map_words(map); i++)
398 r.x[i] = ~0UL;
399 }
400 return r;
401}
402
403static inline map_word inline_map_read(struct map_info *map, unsigned long ofs)
404{
405 map_word r;
406
407 if (map_bankwidth_is_1(map))
408 r.x[0] = __raw_readb(map->virt + ofs);
409 else if (map_bankwidth_is_2(map))
410 r.x[0] = __raw_readw(map->virt + ofs);
411 else if (map_bankwidth_is_4(map))
412 r.x[0] = __raw_readl(map->virt + ofs);
413#if BITS_PER_LONG >= 64
414 else if (map_bankwidth_is_8(map))
415 r.x[0] = __raw_readq(map->virt + ofs);
416#endif
417 else if (map_bankwidth_is_large(map))
418 memcpy_fromio(r.x, map->virt + ofs, map->bankwidth);
419 else
420 BUG();
421
422 return r;
423}
424
425static inline void inline_map_write(struct map_info *map, const map_word datum, unsigned long ofs)
426{
427 if (map_bankwidth_is_1(map))
428 __raw_writeb(datum.x[0], map->virt + ofs);
429 else if (map_bankwidth_is_2(map))
430 __raw_writew(datum.x[0], map->virt + ofs);
431 else if (map_bankwidth_is_4(map))
432 __raw_writel(datum.x[0], map->virt + ofs);
433#if BITS_PER_LONG >= 64
434 else if (map_bankwidth_is_8(map))
435 __raw_writeq(datum.x[0], map->virt + ofs);
436#endif
437 else if (map_bankwidth_is_large(map))
438 memcpy_toio(map->virt+ofs, datum.x, map->bankwidth);
439 else
440 BUG();
441 mb();
442}
443
444static inline void inline_map_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
445{
446 if (map->cached)
447 memcpy(to, (char *)map->cached + from, len);
448 else
449 memcpy_fromio(to, map->virt + from, len);
450}
451
452static inline void inline_map_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
453{
454 memcpy_toio(map->virt + to, from, len);
455}
456
457#ifdef CONFIG_MTD_COMPLEX_MAPPINGS
458#define map_read(map, ofs) (map)->read(map, ofs)
459#define map_copy_from(map, to, from, len) (map)->copy_from(map, to, from, len)
460#define map_write(map, datum, ofs) (map)->write(map, datum, ofs)
461#define map_copy_to(map, to, from, len) (map)->copy_to(map, to, from, len)
462
463extern void simple_map_init(struct map_info *);
464#define map_is_linear(map) (map->phys != NO_XIP)
465
466#else
467#define map_read(map, ofs) inline_map_read(map, ofs)
468#define map_copy_from(map, to, from, len) inline_map_copy_from(map, to, from, len)
469#define map_write(map, datum, ofs) inline_map_write(map, datum, ofs)
470#define map_copy_to(map, to, from, len) inline_map_copy_to(map, to, from, len)
471
472
473#define simple_map_init(map) BUG_ON(!map_bankwidth_supported((map)->bankwidth))
474#define map_is_linear(map) ({ (void)(map); 1; })
475
476#endif
477
478#endif
479