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