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