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
274static inline int map_word_equal(struct map_info *map, map_word val1, map_word val2)
275{
276 int i;
277
278 for (i = 0; i < map_words(map); i++) {
279 if (val1.x[i] != val2.x[i])
280 return 0;
281 }
282
283 return 1;
284}
285
286static inline map_word map_word_and(struct map_info *map, map_word val1, map_word val2)
287{
288 map_word r;
289 int i;
290
291 for (i = 0; i < map_words(map); i++)
292 r.x[i] = val1.x[i] & val2.x[i];
293
294 return r;
295}
296
297static inline map_word map_word_clr(struct map_info *map, map_word val1, map_word val2)
298{
299 map_word r;
300 int i;
301
302 for (i = 0; i < map_words(map); i++)
303 r.x[i] = val1.x[i] & ~val2.x[i];
304
305 return r;
306}
307
308static inline map_word map_word_or(struct map_info *map, map_word val1, map_word val2)
309{
310 map_word r;
311 int i;
312
313 for (i = 0; i < map_words(map); i++)
314 r.x[i] = val1.x[i] | val2.x[i];
315
316 return r;
317}
318
319static inline int map_word_andequal(struct map_info *map, map_word val1, map_word val2, map_word val3)
320{
321 int i;
322
323 for (i = 0; i < map_words(map); i++) {
324 if ((val1.x[i] & val2.x[i]) != val3.x[i])
325 return 0;
326 }
327
328 return 1;
329}
330
331static inline int map_word_bitsset(struct map_info *map, map_word val1, map_word val2)
332{
333 int i;
334
335 for (i = 0; i < map_words(map); i++) {
336 if (val1.x[i] & val2.x[i])
337 return 1;
338 }
339
340 return 0;
341}
342
343static inline map_word map_word_load(struct map_info *map, const void *ptr)
344{
345 map_word r;
346
347 if (map_bankwidth_is_1(map))
348 r.x[0] = *(unsigned char *)ptr;
349 else if (map_bankwidth_is_2(map))
350 r.x[0] = get_unaligned((uint16_t *)ptr);
351 else if (map_bankwidth_is_4(map))
352 r.x[0] = get_unaligned((uint32_t *)ptr);
353#if BITS_PER_LONG >= 64
354 else if (map_bankwidth_is_8(map))
355 r.x[0] = get_unaligned((uint64_t *)ptr);
356#endif
357 else if (map_bankwidth_is_large(map))
358 memcpy(r.x, ptr, map->bankwidth);
359 else
360 BUG();
361
362 return r;
363}
364
365static inline map_word map_word_load_partial(struct map_info *map, map_word orig, const unsigned char *buf, int start, int len)
366{
367 int i;
368
369 if (map_bankwidth_is_large(map)) {
370 char *dest = (char *)&orig;
371
372 memcpy(dest+start, buf, len);
373 } else {
374 for (i = start; i < start+len; i++) {
375 int bitpos;
376
377#ifdef __LITTLE_ENDIAN
378 bitpos = i * 8;
379#else
380 bitpos = (map_bankwidth(map) - 1 - i) * 8;
381#endif
382 orig.x[0] &= ~(0xff << bitpos);
383 orig.x[0] |= (unsigned long)buf[i-start] << bitpos;
384 }
385 }
386 return orig;
387}
388
389#if BITS_PER_LONG < 64
390#define MAP_FF_LIMIT 4
391#else
392#define MAP_FF_LIMIT 8
393#endif
394
395static inline map_word map_word_ff(struct map_info *map)
396{
397 map_word r;
398 int i;
399
400 if (map_bankwidth(map) < MAP_FF_LIMIT) {
401 int bw = 8 * map_bankwidth(map);
402
403 r.x[0] = (1UL << bw) - 1;
404 } else {
405 for (i = 0; i < map_words(map); i++)
406 r.x[i] = ~0UL;
407 }
408 return r;
409}
410
411static inline map_word inline_map_read(struct map_info *map, unsigned long ofs)
412{
413 map_word r;
414
415 if (map_bankwidth_is_1(map))
416 r.x[0] = __raw_readb(map->virt + ofs);
417 else if (map_bankwidth_is_2(map))
418 r.x[0] = __raw_readw(map->virt + ofs);
419 else if (map_bankwidth_is_4(map))
420 r.x[0] = __raw_readl(map->virt + ofs);
421#if BITS_PER_LONG >= 64
422 else if (map_bankwidth_is_8(map))
423 r.x[0] = __raw_readq(map->virt + ofs);
424#endif
425 else if (map_bankwidth_is_large(map))
426 memcpy_fromio(r.x, map->virt + ofs, map->bankwidth);
427 else
428 BUG();
429
430 return r;
431}
432
433static inline void inline_map_write(struct map_info *map, const map_word datum, unsigned long ofs)
434{
435 if (map_bankwidth_is_1(map))
436 __raw_writeb(datum.x[0], map->virt + ofs);
437 else if (map_bankwidth_is_2(map))
438 __raw_writew(datum.x[0], map->virt + ofs);
439 else if (map_bankwidth_is_4(map))
440 __raw_writel(datum.x[0], map->virt + ofs);
441#if BITS_PER_LONG >= 64
442 else if (map_bankwidth_is_8(map))
443 __raw_writeq(datum.x[0], map->virt + ofs);
444#endif
445 else if (map_bankwidth_is_large(map))
446 memcpy_toio(map->virt+ofs, datum.x, map->bankwidth);
447 else
448 BUG();
449 mb();
450}
451
452static inline void inline_map_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
453{
454 if (map->cached)
455 memcpy(to, (char *)map->cached + from, len);
456 else
457 memcpy_fromio(to, map->virt + from, len);
458}
459
460static inline void inline_map_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
461{
462 memcpy_toio(map->virt + to, from, len);
463}
464
465#ifdef CONFIG_MTD_COMPLEX_MAPPINGS
466#define map_read(map, ofs) (map)->read(map, ofs)
467#define map_copy_from(map, to, from, len) (map)->copy_from(map, to, from, len)
468#define map_write(map, datum, ofs) (map)->write(map, datum, ofs)
469#define map_copy_to(map, to, from, len) (map)->copy_to(map, to, from, len)
470
471extern void simple_map_init(struct map_info *);
472#define map_is_linear(map) (map->phys != NO_XIP)
473
474#else
475#define map_read(map, ofs) inline_map_read(map, ofs)
476#define map_copy_from(map, to, from, len) inline_map_copy_from(map, to, from, len)
477#define map_write(map, datum, ofs) inline_map_write(map, datum, ofs)
478#define map_copy_to(map, to, from, len) inline_map_copy_to(map, to, from, len)
479
480
481#define simple_map_init(map) BUG_ON(!map_bankwidth_supported((map)->bankwidth))
482#define map_is_linear(map) ({ (void)(map); 1; })
483
484#endif
485
486#endif
487