18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright © 2000-2010 David Woodhouse <dwmw2@infradead.org> et al.
48c2ecf20Sopenharmony_ci */
58c2ecf20Sopenharmony_ci
68c2ecf20Sopenharmony_ci/* Overhauled routines for dealing with different mmap regions of flash */
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci#ifndef __LINUX_MTD_MAP_H__
98c2ecf20Sopenharmony_ci#define __LINUX_MTD_MAP_H__
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci#include <linux/types.h>
128c2ecf20Sopenharmony_ci#include <linux/list.h>
138c2ecf20Sopenharmony_ci#include <linux/string.h>
148c2ecf20Sopenharmony_ci#include <linux/bug.h>
158c2ecf20Sopenharmony_ci#include <linux/kernel.h>
168c2ecf20Sopenharmony_ci#include <linux/io.h>
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_ci#include <asm/unaligned.h>
198c2ecf20Sopenharmony_ci#include <asm/barrier.h>
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_ci#ifdef CONFIG_MTD_MAP_BANK_WIDTH_1
228c2ecf20Sopenharmony_ci#define map_bankwidth(map) 1
238c2ecf20Sopenharmony_ci#define map_bankwidth_is_1(map) (map_bankwidth(map) == 1)
248c2ecf20Sopenharmony_ci#define map_bankwidth_is_large(map) (0)
258c2ecf20Sopenharmony_ci#define map_words(map) (1)
268c2ecf20Sopenharmony_ci#define MAX_MAP_BANKWIDTH 1
278c2ecf20Sopenharmony_ci#else
288c2ecf20Sopenharmony_ci#define map_bankwidth_is_1(map) (0)
298c2ecf20Sopenharmony_ci#endif
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_ci#ifdef CONFIG_MTD_MAP_BANK_WIDTH_2
328c2ecf20Sopenharmony_ci# ifdef map_bankwidth
338c2ecf20Sopenharmony_ci#  undef map_bankwidth
348c2ecf20Sopenharmony_ci#  define map_bankwidth(map) ((map)->bankwidth)
358c2ecf20Sopenharmony_ci# else
368c2ecf20Sopenharmony_ci#  define map_bankwidth(map) 2
378c2ecf20Sopenharmony_ci#  define map_bankwidth_is_large(map) (0)
388c2ecf20Sopenharmony_ci#  define map_words(map) (1)
398c2ecf20Sopenharmony_ci# endif
408c2ecf20Sopenharmony_ci#define map_bankwidth_is_2(map) (map_bankwidth(map) == 2)
418c2ecf20Sopenharmony_ci#undef MAX_MAP_BANKWIDTH
428c2ecf20Sopenharmony_ci#define MAX_MAP_BANKWIDTH 2
438c2ecf20Sopenharmony_ci#else
448c2ecf20Sopenharmony_ci#define map_bankwidth_is_2(map) (0)
458c2ecf20Sopenharmony_ci#endif
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_ci#ifdef CONFIG_MTD_MAP_BANK_WIDTH_4
488c2ecf20Sopenharmony_ci# ifdef map_bankwidth
498c2ecf20Sopenharmony_ci#  undef map_bankwidth
508c2ecf20Sopenharmony_ci#  define map_bankwidth(map) ((map)->bankwidth)
518c2ecf20Sopenharmony_ci# else
528c2ecf20Sopenharmony_ci#  define map_bankwidth(map) 4
538c2ecf20Sopenharmony_ci#  define map_bankwidth_is_large(map) (0)
548c2ecf20Sopenharmony_ci#  define map_words(map) (1)
558c2ecf20Sopenharmony_ci# endif
568c2ecf20Sopenharmony_ci#define map_bankwidth_is_4(map) (map_bankwidth(map) == 4)
578c2ecf20Sopenharmony_ci#undef MAX_MAP_BANKWIDTH
588c2ecf20Sopenharmony_ci#define MAX_MAP_BANKWIDTH 4
598c2ecf20Sopenharmony_ci#else
608c2ecf20Sopenharmony_ci#define map_bankwidth_is_4(map) (0)
618c2ecf20Sopenharmony_ci#endif
628c2ecf20Sopenharmony_ci
638c2ecf20Sopenharmony_ci/* ensure we never evaluate anything shorted than an unsigned long
648c2ecf20Sopenharmony_ci * to zero, and ensure we'll never miss the end of an comparison (bjd) */
658c2ecf20Sopenharmony_ci
668c2ecf20Sopenharmony_ci#define map_calc_words(map) ((map_bankwidth(map) + (sizeof(unsigned long)-1)) / sizeof(unsigned long))
678c2ecf20Sopenharmony_ci
688c2ecf20Sopenharmony_ci#ifdef CONFIG_MTD_MAP_BANK_WIDTH_8
698c2ecf20Sopenharmony_ci# ifdef map_bankwidth
708c2ecf20Sopenharmony_ci#  undef map_bankwidth
718c2ecf20Sopenharmony_ci#  define map_bankwidth(map) ((map)->bankwidth)
728c2ecf20Sopenharmony_ci#  if BITS_PER_LONG < 64
738c2ecf20Sopenharmony_ci#   undef map_bankwidth_is_large
748c2ecf20Sopenharmony_ci#   define map_bankwidth_is_large(map) (map_bankwidth(map) > BITS_PER_LONG/8)
758c2ecf20Sopenharmony_ci#   undef map_words
768c2ecf20Sopenharmony_ci#   define map_words(map) map_calc_words(map)
778c2ecf20Sopenharmony_ci#  endif
788c2ecf20Sopenharmony_ci# else
798c2ecf20Sopenharmony_ci#  define map_bankwidth(map) 8
808c2ecf20Sopenharmony_ci#  define map_bankwidth_is_large(map) (BITS_PER_LONG < 64)
818c2ecf20Sopenharmony_ci#  define map_words(map) map_calc_words(map)
828c2ecf20Sopenharmony_ci# endif
838c2ecf20Sopenharmony_ci#define map_bankwidth_is_8(map) (map_bankwidth(map) == 8)
848c2ecf20Sopenharmony_ci#undef MAX_MAP_BANKWIDTH
858c2ecf20Sopenharmony_ci#define MAX_MAP_BANKWIDTH 8
868c2ecf20Sopenharmony_ci#else
878c2ecf20Sopenharmony_ci#define map_bankwidth_is_8(map) (0)
888c2ecf20Sopenharmony_ci#endif
898c2ecf20Sopenharmony_ci
908c2ecf20Sopenharmony_ci#ifdef CONFIG_MTD_MAP_BANK_WIDTH_16
918c2ecf20Sopenharmony_ci# ifdef map_bankwidth
928c2ecf20Sopenharmony_ci#  undef map_bankwidth
938c2ecf20Sopenharmony_ci#  define map_bankwidth(map) ((map)->bankwidth)
948c2ecf20Sopenharmony_ci#  undef map_bankwidth_is_large
958c2ecf20Sopenharmony_ci#  define map_bankwidth_is_large(map) (map_bankwidth(map) > BITS_PER_LONG/8)
968c2ecf20Sopenharmony_ci#  undef map_words
978c2ecf20Sopenharmony_ci#  define map_words(map) map_calc_words(map)
988c2ecf20Sopenharmony_ci# else
998c2ecf20Sopenharmony_ci#  define map_bankwidth(map) 16
1008c2ecf20Sopenharmony_ci#  define map_bankwidth_is_large(map) (1)
1018c2ecf20Sopenharmony_ci#  define map_words(map) map_calc_words(map)
1028c2ecf20Sopenharmony_ci# endif
1038c2ecf20Sopenharmony_ci#define map_bankwidth_is_16(map) (map_bankwidth(map) == 16)
1048c2ecf20Sopenharmony_ci#undef MAX_MAP_BANKWIDTH
1058c2ecf20Sopenharmony_ci#define MAX_MAP_BANKWIDTH 16
1068c2ecf20Sopenharmony_ci#else
1078c2ecf20Sopenharmony_ci#define map_bankwidth_is_16(map) (0)
1088c2ecf20Sopenharmony_ci#endif
1098c2ecf20Sopenharmony_ci
1108c2ecf20Sopenharmony_ci#ifdef CONFIG_MTD_MAP_BANK_WIDTH_32
1118c2ecf20Sopenharmony_ci/* always use indirect access for 256-bit to preserve kernel stack */
1128c2ecf20Sopenharmony_ci# undef map_bankwidth
1138c2ecf20Sopenharmony_ci# define map_bankwidth(map) ((map)->bankwidth)
1148c2ecf20Sopenharmony_ci# undef map_bankwidth_is_large
1158c2ecf20Sopenharmony_ci# define map_bankwidth_is_large(map) (map_bankwidth(map) > BITS_PER_LONG/8)
1168c2ecf20Sopenharmony_ci# undef map_words
1178c2ecf20Sopenharmony_ci# define map_words(map) map_calc_words(map)
1188c2ecf20Sopenharmony_ci#define map_bankwidth_is_32(map) (map_bankwidth(map) == 32)
1198c2ecf20Sopenharmony_ci#undef MAX_MAP_BANKWIDTH
1208c2ecf20Sopenharmony_ci#define MAX_MAP_BANKWIDTH 32
1218c2ecf20Sopenharmony_ci#else
1228c2ecf20Sopenharmony_ci#define map_bankwidth_is_32(map) (0)
1238c2ecf20Sopenharmony_ci#endif
1248c2ecf20Sopenharmony_ci
1258c2ecf20Sopenharmony_ci#ifndef map_bankwidth
1268c2ecf20Sopenharmony_ci#ifdef CONFIG_MTD
1278c2ecf20Sopenharmony_ci#warning "No CONFIG_MTD_MAP_BANK_WIDTH_xx selected. No NOR chip support can work"
1288c2ecf20Sopenharmony_ci#endif
1298c2ecf20Sopenharmony_cistatic inline int map_bankwidth(void *map)
1308c2ecf20Sopenharmony_ci{
1318c2ecf20Sopenharmony_ci	BUG();
1328c2ecf20Sopenharmony_ci	return 0;
1338c2ecf20Sopenharmony_ci}
1348c2ecf20Sopenharmony_ci#define map_bankwidth_is_large(map) (0)
1358c2ecf20Sopenharmony_ci#define map_words(map) (0)
1368c2ecf20Sopenharmony_ci#define MAX_MAP_BANKWIDTH 1
1378c2ecf20Sopenharmony_ci#endif
1388c2ecf20Sopenharmony_ci
1398c2ecf20Sopenharmony_cistatic inline int map_bankwidth_supported(int w)
1408c2ecf20Sopenharmony_ci{
1418c2ecf20Sopenharmony_ci	switch (w) {
1428c2ecf20Sopenharmony_ci#ifdef CONFIG_MTD_MAP_BANK_WIDTH_1
1438c2ecf20Sopenharmony_ci	case 1:
1448c2ecf20Sopenharmony_ci#endif
1458c2ecf20Sopenharmony_ci#ifdef CONFIG_MTD_MAP_BANK_WIDTH_2
1468c2ecf20Sopenharmony_ci	case 2:
1478c2ecf20Sopenharmony_ci#endif
1488c2ecf20Sopenharmony_ci#ifdef CONFIG_MTD_MAP_BANK_WIDTH_4
1498c2ecf20Sopenharmony_ci	case 4:
1508c2ecf20Sopenharmony_ci#endif
1518c2ecf20Sopenharmony_ci#ifdef CONFIG_MTD_MAP_BANK_WIDTH_8
1528c2ecf20Sopenharmony_ci	case 8:
1538c2ecf20Sopenharmony_ci#endif
1548c2ecf20Sopenharmony_ci#ifdef CONFIG_MTD_MAP_BANK_WIDTH_16
1558c2ecf20Sopenharmony_ci	case 16:
1568c2ecf20Sopenharmony_ci#endif
1578c2ecf20Sopenharmony_ci#ifdef CONFIG_MTD_MAP_BANK_WIDTH_32
1588c2ecf20Sopenharmony_ci	case 32:
1598c2ecf20Sopenharmony_ci#endif
1608c2ecf20Sopenharmony_ci		return 1;
1618c2ecf20Sopenharmony_ci
1628c2ecf20Sopenharmony_ci	default:
1638c2ecf20Sopenharmony_ci		return 0;
1648c2ecf20Sopenharmony_ci	}
1658c2ecf20Sopenharmony_ci}
1668c2ecf20Sopenharmony_ci
1678c2ecf20Sopenharmony_ci#define MAX_MAP_LONGS (((MAX_MAP_BANKWIDTH * 8) + BITS_PER_LONG - 1) / BITS_PER_LONG)
1688c2ecf20Sopenharmony_ci
1698c2ecf20Sopenharmony_citypedef union {
1708c2ecf20Sopenharmony_ci	unsigned long x[MAX_MAP_LONGS];
1718c2ecf20Sopenharmony_ci} map_word;
1728c2ecf20Sopenharmony_ci
1738c2ecf20Sopenharmony_ci/* The map stuff is very simple. You fill in your struct map_info with
1748c2ecf20Sopenharmony_ci   a handful of routines for accessing the device, making sure they handle
1758c2ecf20Sopenharmony_ci   paging etc. correctly if your device needs it. Then you pass it off
1768c2ecf20Sopenharmony_ci   to a chip probe routine -- either JEDEC or CFI probe or both -- via
1778c2ecf20Sopenharmony_ci   do_map_probe(). If a chip is recognised, the probe code will invoke the
1788c2ecf20Sopenharmony_ci   appropriate chip driver (if present) and return a struct mtd_info.
1798c2ecf20Sopenharmony_ci   At which point, you fill in the mtd->module with your own module
1808c2ecf20Sopenharmony_ci   address, and register it with the MTD core code. Or you could partition
1818c2ecf20Sopenharmony_ci   it and register the partitions instead, or keep it for your own private
1828c2ecf20Sopenharmony_ci   use; whatever.
1838c2ecf20Sopenharmony_ci
1848c2ecf20Sopenharmony_ci   The mtd->priv field will point to the struct map_info, and any further
1858c2ecf20Sopenharmony_ci   private data required by the chip driver is linked from the
1868c2ecf20Sopenharmony_ci   mtd->priv->fldrv_priv field. This allows the map driver to get at
1878c2ecf20Sopenharmony_ci   the destructor function map->fldrv_destroy() when it's tired
1888c2ecf20Sopenharmony_ci   of living.
1898c2ecf20Sopenharmony_ci*/
1908c2ecf20Sopenharmony_ci
1918c2ecf20Sopenharmony_cistruct map_info {
1928c2ecf20Sopenharmony_ci	const char *name;
1938c2ecf20Sopenharmony_ci	unsigned long size;
1948c2ecf20Sopenharmony_ci	resource_size_t phys;
1958c2ecf20Sopenharmony_ci#define NO_XIP (-1UL)
1968c2ecf20Sopenharmony_ci
1978c2ecf20Sopenharmony_ci	void __iomem *virt;
1988c2ecf20Sopenharmony_ci	void *cached;
1998c2ecf20Sopenharmony_ci
2008c2ecf20Sopenharmony_ci	int swap; /* this mapping's byte-swapping requirement */
2018c2ecf20Sopenharmony_ci	int bankwidth; /* in octets. This isn't necessarily the width
2028c2ecf20Sopenharmony_ci		       of actual bus cycles -- it's the repeat interval
2038c2ecf20Sopenharmony_ci		      in bytes, before you are talking to the first chip again.
2048c2ecf20Sopenharmony_ci		      */
2058c2ecf20Sopenharmony_ci
2068c2ecf20Sopenharmony_ci#ifdef CONFIG_MTD_COMPLEX_MAPPINGS
2078c2ecf20Sopenharmony_ci	map_word (*read)(struct map_info *, unsigned long);
2088c2ecf20Sopenharmony_ci	void (*copy_from)(struct map_info *, void *, unsigned long, ssize_t);
2098c2ecf20Sopenharmony_ci
2108c2ecf20Sopenharmony_ci	void (*write)(struct map_info *, const map_word, unsigned long);
2118c2ecf20Sopenharmony_ci	void (*copy_to)(struct map_info *, unsigned long, const void *, ssize_t);
2128c2ecf20Sopenharmony_ci
2138c2ecf20Sopenharmony_ci	/* We can perhaps put in 'point' and 'unpoint' methods, if we really
2148c2ecf20Sopenharmony_ci	   want to enable XIP for non-linear mappings. Not yet though. */
2158c2ecf20Sopenharmony_ci#endif
2168c2ecf20Sopenharmony_ci	/* It's possible for the map driver to use cached memory in its
2178c2ecf20Sopenharmony_ci	   copy_from implementation (and _only_ with copy_from).  However,
2188c2ecf20Sopenharmony_ci	   when the chip driver knows some flash area has changed contents,
2198c2ecf20Sopenharmony_ci	   it will signal it to the map driver through this routine to let
2208c2ecf20Sopenharmony_ci	   the map driver invalidate the corresponding cache as needed.
2218c2ecf20Sopenharmony_ci	   If there is no cache to care about this can be set to NULL. */
2228c2ecf20Sopenharmony_ci	void (*inval_cache)(struct map_info *, unsigned long, ssize_t);
2238c2ecf20Sopenharmony_ci
2248c2ecf20Sopenharmony_ci	/* This will be called with 1 as parameter when the first map user
2258c2ecf20Sopenharmony_ci	 * needs VPP, and called with 0 when the last user exits. The map
2268c2ecf20Sopenharmony_ci	 * core maintains a reference counter, and assumes that VPP is a
2278c2ecf20Sopenharmony_ci	 * global resource applying to all mapped flash chips on the system.
2288c2ecf20Sopenharmony_ci	 */
2298c2ecf20Sopenharmony_ci	void (*set_vpp)(struct map_info *, int);
2308c2ecf20Sopenharmony_ci
2318c2ecf20Sopenharmony_ci	unsigned long pfow_base;
2328c2ecf20Sopenharmony_ci	unsigned long map_priv_1;
2338c2ecf20Sopenharmony_ci	unsigned long map_priv_2;
2348c2ecf20Sopenharmony_ci	struct device_node *device_node;
2358c2ecf20Sopenharmony_ci	void *fldrv_priv;
2368c2ecf20Sopenharmony_ci	struct mtd_chip_driver *fldrv;
2378c2ecf20Sopenharmony_ci};
2388c2ecf20Sopenharmony_ci
2398c2ecf20Sopenharmony_cistruct mtd_chip_driver {
2408c2ecf20Sopenharmony_ci	struct mtd_info *(*probe)(struct map_info *map);
2418c2ecf20Sopenharmony_ci	void (*destroy)(struct mtd_info *);
2428c2ecf20Sopenharmony_ci	struct module *module;
2438c2ecf20Sopenharmony_ci	char *name;
2448c2ecf20Sopenharmony_ci	struct list_head list;
2458c2ecf20Sopenharmony_ci};
2468c2ecf20Sopenharmony_ci
2478c2ecf20Sopenharmony_civoid register_mtd_chip_driver(struct mtd_chip_driver *);
2488c2ecf20Sopenharmony_civoid unregister_mtd_chip_driver(struct mtd_chip_driver *);
2498c2ecf20Sopenharmony_ci
2508c2ecf20Sopenharmony_cistruct mtd_info *do_map_probe(const char *name, struct map_info *map);
2518c2ecf20Sopenharmony_civoid map_destroy(struct mtd_info *mtd);
2528c2ecf20Sopenharmony_ci
2538c2ecf20Sopenharmony_ci#define ENABLE_VPP(map) do { if (map->set_vpp) map->set_vpp(map, 1); } while (0)
2548c2ecf20Sopenharmony_ci#define DISABLE_VPP(map) do { if (map->set_vpp) map->set_vpp(map, 0); } while (0)
2558c2ecf20Sopenharmony_ci
2568c2ecf20Sopenharmony_ci#define INVALIDATE_CACHED_RANGE(map, from, size) \
2578c2ecf20Sopenharmony_ci	do { if (map->inval_cache) map->inval_cache(map, from, size); } while (0)
2588c2ecf20Sopenharmony_ci
2598c2ecf20Sopenharmony_ci#define map_word_equal(map, val1, val2)					\
2608c2ecf20Sopenharmony_ci({									\
2618c2ecf20Sopenharmony_ci	int i, ret = 1;							\
2628c2ecf20Sopenharmony_ci	for (i = 0; i < map_words(map); i++)				\
2638c2ecf20Sopenharmony_ci		if ((val1).x[i] != (val2).x[i]) {			\
2648c2ecf20Sopenharmony_ci			ret = 0;					\
2658c2ecf20Sopenharmony_ci			break;						\
2668c2ecf20Sopenharmony_ci		}							\
2678c2ecf20Sopenharmony_ci	ret;								\
2688c2ecf20Sopenharmony_ci})
2698c2ecf20Sopenharmony_ci
2708c2ecf20Sopenharmony_ci#define map_word_and(map, val1, val2)					\
2718c2ecf20Sopenharmony_ci({									\
2728c2ecf20Sopenharmony_ci	map_word r;							\
2738c2ecf20Sopenharmony_ci	int i;								\
2748c2ecf20Sopenharmony_ci	for (i = 0; i < map_words(map); i++)				\
2758c2ecf20Sopenharmony_ci		r.x[i] = (val1).x[i] & (val2).x[i];			\
2768c2ecf20Sopenharmony_ci	r;								\
2778c2ecf20Sopenharmony_ci})
2788c2ecf20Sopenharmony_ci
2798c2ecf20Sopenharmony_ci#define map_word_clr(map, val1, val2)					\
2808c2ecf20Sopenharmony_ci({									\
2818c2ecf20Sopenharmony_ci	map_word r;							\
2828c2ecf20Sopenharmony_ci	int i;								\
2838c2ecf20Sopenharmony_ci	for (i = 0; i < map_words(map); i++)				\
2848c2ecf20Sopenharmony_ci		r.x[i] = (val1).x[i] & ~(val2).x[i];			\
2858c2ecf20Sopenharmony_ci	r;								\
2868c2ecf20Sopenharmony_ci})
2878c2ecf20Sopenharmony_ci
2888c2ecf20Sopenharmony_ci#define map_word_or(map, val1, val2)					\
2898c2ecf20Sopenharmony_ci({									\
2908c2ecf20Sopenharmony_ci	map_word r;							\
2918c2ecf20Sopenharmony_ci	int i;								\
2928c2ecf20Sopenharmony_ci	for (i = 0; i < map_words(map); i++)				\
2938c2ecf20Sopenharmony_ci		r.x[i] = (val1).x[i] | (val2).x[i];			\
2948c2ecf20Sopenharmony_ci	r;								\
2958c2ecf20Sopenharmony_ci})
2968c2ecf20Sopenharmony_ci
2978c2ecf20Sopenharmony_ci#define map_word_andequal(map, val1, val2, val3)			\
2988c2ecf20Sopenharmony_ci({									\
2998c2ecf20Sopenharmony_ci	int i, ret = 1;							\
3008c2ecf20Sopenharmony_ci	for (i = 0; i < map_words(map); i++) {				\
3018c2ecf20Sopenharmony_ci		if (((val1).x[i] & (val2).x[i]) != (val3).x[i]) {	\
3028c2ecf20Sopenharmony_ci			ret = 0;					\
3038c2ecf20Sopenharmony_ci			break;						\
3048c2ecf20Sopenharmony_ci		}							\
3058c2ecf20Sopenharmony_ci	}								\
3068c2ecf20Sopenharmony_ci	ret;								\
3078c2ecf20Sopenharmony_ci})
3088c2ecf20Sopenharmony_ci
3098c2ecf20Sopenharmony_ci#define map_word_bitsset(map, val1, val2)				\
3108c2ecf20Sopenharmony_ci({									\
3118c2ecf20Sopenharmony_ci	int i, ret = 0;							\
3128c2ecf20Sopenharmony_ci	for (i = 0; i < map_words(map); i++) {				\
3138c2ecf20Sopenharmony_ci		if ((val1).x[i] & (val2).x[i]) {			\
3148c2ecf20Sopenharmony_ci			ret = 1;					\
3158c2ecf20Sopenharmony_ci			break;						\
3168c2ecf20Sopenharmony_ci		}							\
3178c2ecf20Sopenharmony_ci	}								\
3188c2ecf20Sopenharmony_ci	ret;								\
3198c2ecf20Sopenharmony_ci})
3208c2ecf20Sopenharmony_ci
3218c2ecf20Sopenharmony_cistatic inline map_word map_word_load(struct map_info *map, const void *ptr)
3228c2ecf20Sopenharmony_ci{
3238c2ecf20Sopenharmony_ci	map_word r;
3248c2ecf20Sopenharmony_ci
3258c2ecf20Sopenharmony_ci	if (map_bankwidth_is_1(map))
3268c2ecf20Sopenharmony_ci		r.x[0] = *(unsigned char *)ptr;
3278c2ecf20Sopenharmony_ci	else if (map_bankwidth_is_2(map))
3288c2ecf20Sopenharmony_ci		r.x[0] = get_unaligned((uint16_t *)ptr);
3298c2ecf20Sopenharmony_ci	else if (map_bankwidth_is_4(map))
3308c2ecf20Sopenharmony_ci		r.x[0] = get_unaligned((uint32_t *)ptr);
3318c2ecf20Sopenharmony_ci#if BITS_PER_LONG >= 64
3328c2ecf20Sopenharmony_ci	else if (map_bankwidth_is_8(map))
3338c2ecf20Sopenharmony_ci		r.x[0] = get_unaligned((uint64_t *)ptr);
3348c2ecf20Sopenharmony_ci#endif
3358c2ecf20Sopenharmony_ci	else if (map_bankwidth_is_large(map))
3368c2ecf20Sopenharmony_ci		memcpy(r.x, ptr, map->bankwidth);
3378c2ecf20Sopenharmony_ci	else
3388c2ecf20Sopenharmony_ci		BUG();
3398c2ecf20Sopenharmony_ci
3408c2ecf20Sopenharmony_ci	return r;
3418c2ecf20Sopenharmony_ci}
3428c2ecf20Sopenharmony_ci
3438c2ecf20Sopenharmony_cistatic inline map_word map_word_load_partial(struct map_info *map, map_word orig, const unsigned char *buf, int start, int len)
3448c2ecf20Sopenharmony_ci{
3458c2ecf20Sopenharmony_ci	int i;
3468c2ecf20Sopenharmony_ci
3478c2ecf20Sopenharmony_ci	if (map_bankwidth_is_large(map)) {
3488c2ecf20Sopenharmony_ci		char *dest = (char *)&orig;
3498c2ecf20Sopenharmony_ci
3508c2ecf20Sopenharmony_ci		memcpy(dest+start, buf, len);
3518c2ecf20Sopenharmony_ci	} else {
3528c2ecf20Sopenharmony_ci		for (i = start; i < start+len; i++) {
3538c2ecf20Sopenharmony_ci			int bitpos;
3548c2ecf20Sopenharmony_ci
3558c2ecf20Sopenharmony_ci#ifdef __LITTLE_ENDIAN
3568c2ecf20Sopenharmony_ci			bitpos = i * 8;
3578c2ecf20Sopenharmony_ci#else /* __BIG_ENDIAN */
3588c2ecf20Sopenharmony_ci			bitpos = (map_bankwidth(map) - 1 - i) * 8;
3598c2ecf20Sopenharmony_ci#endif
3608c2ecf20Sopenharmony_ci			orig.x[0] &= ~(0xff << bitpos);
3618c2ecf20Sopenharmony_ci			orig.x[0] |= (unsigned long)buf[i-start] << bitpos;
3628c2ecf20Sopenharmony_ci		}
3638c2ecf20Sopenharmony_ci	}
3648c2ecf20Sopenharmony_ci	return orig;
3658c2ecf20Sopenharmony_ci}
3668c2ecf20Sopenharmony_ci
3678c2ecf20Sopenharmony_ci#if BITS_PER_LONG < 64
3688c2ecf20Sopenharmony_ci#define MAP_FF_LIMIT 4
3698c2ecf20Sopenharmony_ci#else
3708c2ecf20Sopenharmony_ci#define MAP_FF_LIMIT 8
3718c2ecf20Sopenharmony_ci#endif
3728c2ecf20Sopenharmony_ci
3738c2ecf20Sopenharmony_cistatic inline map_word map_word_ff(struct map_info *map)
3748c2ecf20Sopenharmony_ci{
3758c2ecf20Sopenharmony_ci	map_word r;
3768c2ecf20Sopenharmony_ci	int i;
3778c2ecf20Sopenharmony_ci
3788c2ecf20Sopenharmony_ci	if (map_bankwidth(map) < MAP_FF_LIMIT) {
3798c2ecf20Sopenharmony_ci		int bw = 8 * map_bankwidth(map);
3808c2ecf20Sopenharmony_ci
3818c2ecf20Sopenharmony_ci		r.x[0] = (1UL << bw) - 1;
3828c2ecf20Sopenharmony_ci	} else {
3838c2ecf20Sopenharmony_ci		for (i = 0; i < map_words(map); i++)
3848c2ecf20Sopenharmony_ci			r.x[i] = ~0UL;
3858c2ecf20Sopenharmony_ci	}
3868c2ecf20Sopenharmony_ci	return r;
3878c2ecf20Sopenharmony_ci}
3888c2ecf20Sopenharmony_ci
3898c2ecf20Sopenharmony_cistatic inline map_word inline_map_read(struct map_info *map, unsigned long ofs)
3908c2ecf20Sopenharmony_ci{
3918c2ecf20Sopenharmony_ci	map_word r;
3928c2ecf20Sopenharmony_ci
3938c2ecf20Sopenharmony_ci	if (map_bankwidth_is_1(map))
3948c2ecf20Sopenharmony_ci		r.x[0] = __raw_readb(map->virt + ofs);
3958c2ecf20Sopenharmony_ci	else if (map_bankwidth_is_2(map))
3968c2ecf20Sopenharmony_ci		r.x[0] = __raw_readw(map->virt + ofs);
3978c2ecf20Sopenharmony_ci	else if (map_bankwidth_is_4(map))
3988c2ecf20Sopenharmony_ci		r.x[0] = __raw_readl(map->virt + ofs);
3998c2ecf20Sopenharmony_ci#if BITS_PER_LONG >= 64
4008c2ecf20Sopenharmony_ci	else if (map_bankwidth_is_8(map))
4018c2ecf20Sopenharmony_ci		r.x[0] = __raw_readq(map->virt + ofs);
4028c2ecf20Sopenharmony_ci#endif
4038c2ecf20Sopenharmony_ci	else if (map_bankwidth_is_large(map))
4048c2ecf20Sopenharmony_ci		memcpy_fromio(r.x, map->virt + ofs, map->bankwidth);
4058c2ecf20Sopenharmony_ci	else
4068c2ecf20Sopenharmony_ci		BUG();
4078c2ecf20Sopenharmony_ci
4088c2ecf20Sopenharmony_ci	return r;
4098c2ecf20Sopenharmony_ci}
4108c2ecf20Sopenharmony_ci
4118c2ecf20Sopenharmony_cistatic inline void inline_map_write(struct map_info *map, const map_word datum, unsigned long ofs)
4128c2ecf20Sopenharmony_ci{
4138c2ecf20Sopenharmony_ci	if (map_bankwidth_is_1(map))
4148c2ecf20Sopenharmony_ci		__raw_writeb(datum.x[0], map->virt + ofs);
4158c2ecf20Sopenharmony_ci	else if (map_bankwidth_is_2(map))
4168c2ecf20Sopenharmony_ci		__raw_writew(datum.x[0], map->virt + ofs);
4178c2ecf20Sopenharmony_ci	else if (map_bankwidth_is_4(map))
4188c2ecf20Sopenharmony_ci		__raw_writel(datum.x[0], map->virt + ofs);
4198c2ecf20Sopenharmony_ci#if BITS_PER_LONG >= 64
4208c2ecf20Sopenharmony_ci	else if (map_bankwidth_is_8(map))
4218c2ecf20Sopenharmony_ci		__raw_writeq(datum.x[0], map->virt + ofs);
4228c2ecf20Sopenharmony_ci#endif
4238c2ecf20Sopenharmony_ci	else if (map_bankwidth_is_large(map))
4248c2ecf20Sopenharmony_ci		memcpy_toio(map->virt+ofs, datum.x, map->bankwidth);
4258c2ecf20Sopenharmony_ci	else
4268c2ecf20Sopenharmony_ci		BUG();
4278c2ecf20Sopenharmony_ci	mb();
4288c2ecf20Sopenharmony_ci}
4298c2ecf20Sopenharmony_ci
4308c2ecf20Sopenharmony_cistatic inline void inline_map_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
4318c2ecf20Sopenharmony_ci{
4328c2ecf20Sopenharmony_ci	if (map->cached)
4338c2ecf20Sopenharmony_ci		memcpy(to, (char *)map->cached + from, len);
4348c2ecf20Sopenharmony_ci	else
4358c2ecf20Sopenharmony_ci		memcpy_fromio(to, map->virt + from, len);
4368c2ecf20Sopenharmony_ci}
4378c2ecf20Sopenharmony_ci
4388c2ecf20Sopenharmony_cistatic inline void inline_map_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
4398c2ecf20Sopenharmony_ci{
4408c2ecf20Sopenharmony_ci	memcpy_toio(map->virt + to, from, len);
4418c2ecf20Sopenharmony_ci}
4428c2ecf20Sopenharmony_ci
4438c2ecf20Sopenharmony_ci#ifdef CONFIG_MTD_COMPLEX_MAPPINGS
4448c2ecf20Sopenharmony_ci#define map_read(map, ofs) (map)->read(map, ofs)
4458c2ecf20Sopenharmony_ci#define map_copy_from(map, to, from, len) (map)->copy_from(map, to, from, len)
4468c2ecf20Sopenharmony_ci#define map_write(map, datum, ofs) (map)->write(map, datum, ofs)
4478c2ecf20Sopenharmony_ci#define map_copy_to(map, to, from, len) (map)->copy_to(map, to, from, len)
4488c2ecf20Sopenharmony_ci
4498c2ecf20Sopenharmony_ciextern void simple_map_init(struct map_info *);
4508c2ecf20Sopenharmony_ci#define map_is_linear(map) (map->phys != NO_XIP)
4518c2ecf20Sopenharmony_ci
4528c2ecf20Sopenharmony_ci#else
4538c2ecf20Sopenharmony_ci#define map_read(map, ofs) inline_map_read(map, ofs)
4548c2ecf20Sopenharmony_ci#define map_copy_from(map, to, from, len) inline_map_copy_from(map, to, from, len)
4558c2ecf20Sopenharmony_ci#define map_write(map, datum, ofs) inline_map_write(map, datum, ofs)
4568c2ecf20Sopenharmony_ci#define map_copy_to(map, to, from, len) inline_map_copy_to(map, to, from, len)
4578c2ecf20Sopenharmony_ci
4588c2ecf20Sopenharmony_ci
4598c2ecf20Sopenharmony_ci#define simple_map_init(map) BUG_ON(!map_bankwidth_supported((map)->bankwidth))
4608c2ecf20Sopenharmony_ci#define map_is_linear(map) ({ (void)(map); 1; })
4618c2ecf20Sopenharmony_ci
4628c2ecf20Sopenharmony_ci#endif /* !CONFIG_MTD_COMPLEX_MAPPINGS */
4638c2ecf20Sopenharmony_ci
4648c2ecf20Sopenharmony_ci#endif /* __LINUX_MTD_MAP_H__ */
465