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