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
31#include <asm/unaligned.h>
32#include <asm/io.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# ifdef map_bankwidth
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# else
133# define map_bankwidth(map) 32
134# define map_bankwidth_is_large(map) (1)
135# define map_words(map) map_calc_words(map)
136# endif
137#define map_bankwidth_is_32(map) (map_bankwidth(map) == 32)
138#undef MAX_MAP_BANKWIDTH
139#define MAX_MAP_BANKWIDTH 32
140#else
141#define map_bankwidth_is_32(map) (0)
142#endif
143
144#ifndef map_bankwidth
145#warning "No CONFIG_MTD_MAP_BANK_WIDTH_xx selected. No NOR chip support can work"
146static inline int map_bankwidth(void *map)
147{
148 BUG();
149 return 0;
150}
151#define map_bankwidth_is_large(map) (0)
152#define map_words(map) (0)
153#define MAX_MAP_BANKWIDTH 1
154#endif
155
156static inline int map_bankwidth_supported(int w)
157{
158 switch (w) {
159#ifdef CONFIG_MTD_MAP_BANK_WIDTH_1
160 case 1:
161#endif
162#ifdef CONFIG_MTD_MAP_BANK_WIDTH_2
163 case 2:
164#endif
165#ifdef CONFIG_MTD_MAP_BANK_WIDTH_4
166 case 4:
167#endif
168#ifdef CONFIG_MTD_MAP_BANK_WIDTH_8
169 case 8:
170#endif
171#ifdef CONFIG_MTD_MAP_BANK_WIDTH_16
172 case 16:
173#endif
174#ifdef CONFIG_MTD_MAP_BANK_WIDTH_32
175 case 32:
176#endif
177 return 1;
178
179 default:
180 return 0;
181 }
182}
183
184#define MAX_MAP_LONGS ( ((MAX_MAP_BANKWIDTH*8) + BITS_PER_LONG - 1) / BITS_PER_LONG )
185
186typedef union {
187 unsigned long x[MAX_MAP_LONGS];
188} map_word;
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208struct map_info {
209 const char *name;
210 unsigned long size;
211 resource_size_t phys;
212#define NO_XIP (-1UL)
213
214 void __iomem *virt;
215 void *cached;
216
217 int swap;
218 int bankwidth;
219
220
221
222
223#ifdef CONFIG_MTD_COMPLEX_MAPPINGS
224 map_word (*read)(struct map_info *, unsigned long);
225 void (*copy_from)(struct map_info *, void *, unsigned long, ssize_t);
226
227 void (*write)(struct map_info *, const map_word, unsigned long);
228 void (*copy_to)(struct map_info *, unsigned long, const void *, ssize_t);
229
230
231
232#endif
233
234
235
236
237
238
239 void (*inval_cache)(struct map_info *, unsigned long, ssize_t);
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 void *fldrv_priv;
249 struct mtd_chip_driver *fldrv;
250};
251
252struct mtd_chip_driver {
253 struct mtd_info *(*probe)(struct map_info *map);
254 void (*destroy)(struct mtd_info *);
255 struct module *module;
256 char *name;
257 struct list_head list;
258};
259
260void register_mtd_chip_driver(struct mtd_chip_driver *);
261void unregister_mtd_chip_driver(struct mtd_chip_driver *);
262
263struct mtd_info *do_map_probe(const char *name, struct map_info *map);
264void map_destroy(struct mtd_info *mtd);
265
266#define ENABLE_VPP(map) do { if(map->set_vpp) map->set_vpp(map, 1); } while(0)
267#define DISABLE_VPP(map) do { if(map->set_vpp) map->set_vpp(map, 0); } while(0)
268
269#define INVALIDATE_CACHED_RANGE(map, from, size) \
270 do { if(map->inval_cache) map->inval_cache(map, from, size); } while(0)
271
272
273static inline int map_word_equal(struct map_info *map, map_word val1, map_word val2)
274{
275 int i;
276 for (i=0; i<map_words(map); i++) {
277 if (val1.x[i] != val2.x[i])
278 return 0;
279 }
280 return 1;
281}
282
283static inline map_word map_word_and(struct map_info *map, map_word val1, map_word val2)
284{
285 map_word r;
286 int i;
287
288 for (i=0; i<map_words(map); i++) {
289 r.x[i] = val1.x[i] & val2.x[i];
290 }
291 return r;
292}
293
294static inline map_word map_word_clr(struct map_info *map, map_word val1, map_word val2)
295{
296 map_word r;
297 int i;
298
299 for (i=0; i<map_words(map); i++) {
300 r.x[i] = val1.x[i] & ~val2.x[i];
301 }
302 return r;
303}
304
305static inline map_word map_word_or(struct map_info *map, map_word val1, map_word val2)
306{
307 map_word r;
308 int i;
309
310 for (i=0; i<map_words(map); i++) {
311 r.x[i] = val1.x[i] | val2.x[i];
312 }
313 return r;
314}
315
316#define map_word_andequal(m, a, b, z) map_word_equal(m, z, map_word_and(m, a, b))
317
318static inline int map_word_bitsset(struct map_info *map, map_word val1, map_word val2)
319{
320 int i;
321
322 for (i=0; i<map_words(map); i++) {
323 if (val1.x[i] & val2.x[i])
324 return 1;
325 }
326 return 0;
327}
328
329static inline map_word map_word_load(struct map_info *map, const void *ptr)
330{
331 map_word r;
332
333 if (map_bankwidth_is_1(map))
334 r.x[0] = *(unsigned char *)ptr;
335 else if (map_bankwidth_is_2(map))
336 r.x[0] = get_unaligned((uint16_t *)ptr);
337 else if (map_bankwidth_is_4(map))
338 r.x[0] = get_unaligned((uint32_t *)ptr);
339#if BITS_PER_LONG >= 64
340 else if (map_bankwidth_is_8(map))
341 r.x[0] = get_unaligned((uint64_t *)ptr);
342#endif
343 else if (map_bankwidth_is_large(map))
344 memcpy(r.x, ptr, map->bankwidth);
345
346 return r;
347}
348
349static inline map_word map_word_load_partial(struct map_info *map, map_word orig, const unsigned char *buf, int start, int len)
350{
351 int i;
352
353 if (map_bankwidth_is_large(map)) {
354 char *dest = (char *)&orig;
355 memcpy(dest+start, buf, len);
356 } else {
357 for (i=start; i < start+len; i++) {
358 int bitpos;
359#ifdef __LITTLE_ENDIAN
360 bitpos = i*8;
361#else
362 bitpos = (map_bankwidth(map)-1-i)*8;
363#endif
364 orig.x[0] &= ~(0xff << bitpos);
365 orig.x[0] |= buf[i-start] << bitpos;
366 }
367 }
368 return orig;
369}
370
371#if BITS_PER_LONG < 64
372#define MAP_FF_LIMIT 4
373#else
374#define MAP_FF_LIMIT 8
375#endif
376
377static inline map_word map_word_ff(struct map_info *map)
378{
379 map_word r;
380 int i;
381
382 if (map_bankwidth(map) < MAP_FF_LIMIT) {
383 int bw = 8 * map_bankwidth(map);
384 r.x[0] = (1 << bw) - 1;
385 } else {
386 for (i=0; i<map_words(map); i++)
387 r.x[i] = ~0UL;
388 }
389 return r;
390}
391
392static inline map_word inline_map_read(struct map_info *map, unsigned long ofs)
393{
394 map_word r;
395
396 if (map_bankwidth_is_1(map))
397 r.x[0] = __raw_readb(map->virt + ofs);
398 else if (map_bankwidth_is_2(map))
399 r.x[0] = __raw_readw(map->virt + ofs);
400 else if (map_bankwidth_is_4(map))
401 r.x[0] = __raw_readl(map->virt + ofs);
402#if BITS_PER_LONG >= 64
403 else if (map_bankwidth_is_8(map))
404 r.x[0] = __raw_readq(map->virt + ofs);
405#endif
406 else if (map_bankwidth_is_large(map))
407 memcpy_fromio(r.x, map->virt+ofs, map->bankwidth);
408 else
409 BUG();
410
411 return r;
412}
413
414static inline void inline_map_write(struct map_info *map, const map_word datum, unsigned long ofs)
415{
416 if (map_bankwidth_is_1(map))
417 __raw_writeb(datum.x[0], map->virt + ofs);
418 else if (map_bankwidth_is_2(map))
419 __raw_writew(datum.x[0], map->virt + ofs);
420 else if (map_bankwidth_is_4(map))
421 __raw_writel(datum.x[0], map->virt + ofs);
422#if BITS_PER_LONG >= 64
423 else if (map_bankwidth_is_8(map))
424 __raw_writeq(datum.x[0], map->virt + ofs);
425#endif
426 else if (map_bankwidth_is_large(map))
427 memcpy_toio(map->virt+ofs, datum.x, map->bankwidth);
428 mb();
429}
430
431static inline void inline_map_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
432{
433 if (map->cached)
434 memcpy(to, (char *)map->cached + from, len);
435 else
436 memcpy_fromio(to, map->virt + from, len);
437}
438
439static inline void inline_map_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
440{
441 memcpy_toio(map->virt + to, from, len);
442}
443
444#ifdef CONFIG_MTD_COMPLEX_MAPPINGS
445#define map_read(map, ofs) (map)->read(map, ofs)
446#define map_copy_from(map, to, from, len) (map)->copy_from(map, to, from, len)
447#define map_write(map, datum, ofs) (map)->write(map, datum, ofs)
448#define map_copy_to(map, to, from, len) (map)->copy_to(map, to, from, len)
449
450extern void simple_map_init(struct map_info *);
451#define map_is_linear(map) (map->phys != NO_XIP)
452
453#else
454#define map_read(map, ofs) inline_map_read(map, ofs)
455#define map_copy_from(map, to, from, len) inline_map_copy_from(map, to, from, len)
456#define map_write(map, datum, ofs) inline_map_write(map, datum, ofs)
457#define map_copy_to(map, to, from, len) inline_map_copy_to(map, to, from, len)
458
459
460#define simple_map_init(map) BUG_ON(!map_bankwidth_supported((map)->bankwidth))
461#define map_is_linear(map) ({ (void)(map); 1; })
462
463#endif
464
465#endif
466