162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Register map access API internal header
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright 2011 Wolfson Microelectronics plc
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
862306a36Sopenharmony_ci */
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#ifndef _REGMAP_INTERNAL_H
1162306a36Sopenharmony_ci#define _REGMAP_INTERNAL_H
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci#include <linux/device.h>
1462306a36Sopenharmony_ci#include <linux/regmap.h>
1562306a36Sopenharmony_ci#include <linux/fs.h>
1662306a36Sopenharmony_ci#include <linux/list.h>
1762306a36Sopenharmony_ci#include <linux/wait.h>
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_cistruct regmap;
2062306a36Sopenharmony_cistruct regcache_ops;
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_cistruct regmap_debugfs_off_cache {
2362306a36Sopenharmony_ci	struct list_head list;
2462306a36Sopenharmony_ci	off_t min;
2562306a36Sopenharmony_ci	off_t max;
2662306a36Sopenharmony_ci	unsigned int base_reg;
2762306a36Sopenharmony_ci	unsigned int max_reg;
2862306a36Sopenharmony_ci};
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_cistruct regmap_format {
3162306a36Sopenharmony_ci	size_t buf_size;
3262306a36Sopenharmony_ci	size_t reg_bytes;
3362306a36Sopenharmony_ci	size_t pad_bytes;
3462306a36Sopenharmony_ci	size_t val_bytes;
3562306a36Sopenharmony_ci	s8 reg_shift;
3662306a36Sopenharmony_ci	void (*format_write)(struct regmap *map,
3762306a36Sopenharmony_ci			     unsigned int reg, unsigned int val);
3862306a36Sopenharmony_ci	void (*format_reg)(void *buf, unsigned int reg, unsigned int shift);
3962306a36Sopenharmony_ci	void (*format_val)(void *buf, unsigned int val, unsigned int shift);
4062306a36Sopenharmony_ci	unsigned int (*parse_val)(const void *buf);
4162306a36Sopenharmony_ci	void (*parse_inplace)(void *buf);
4262306a36Sopenharmony_ci};
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_cistruct regmap_async {
4562306a36Sopenharmony_ci	struct list_head list;
4662306a36Sopenharmony_ci	struct regmap *map;
4762306a36Sopenharmony_ci	void *work_buf;
4862306a36Sopenharmony_ci};
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_cistruct regmap {
5162306a36Sopenharmony_ci	union {
5262306a36Sopenharmony_ci		struct mutex mutex;
5362306a36Sopenharmony_ci		struct {
5462306a36Sopenharmony_ci			spinlock_t spinlock;
5562306a36Sopenharmony_ci			unsigned long spinlock_flags;
5662306a36Sopenharmony_ci		};
5762306a36Sopenharmony_ci		struct {
5862306a36Sopenharmony_ci			raw_spinlock_t raw_spinlock;
5962306a36Sopenharmony_ci			unsigned long raw_spinlock_flags;
6062306a36Sopenharmony_ci		};
6162306a36Sopenharmony_ci	};
6262306a36Sopenharmony_ci	regmap_lock lock;
6362306a36Sopenharmony_ci	regmap_unlock unlock;
6462306a36Sopenharmony_ci	void *lock_arg; /* This is passed to lock/unlock functions */
6562306a36Sopenharmony_ci	gfp_t alloc_flags;
6662306a36Sopenharmony_ci	unsigned int reg_base;
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ci	struct device *dev; /* Device we do I/O on */
6962306a36Sopenharmony_ci	void *work_buf;     /* Scratch buffer used to format I/O */
7062306a36Sopenharmony_ci	struct regmap_format format;  /* Buffer format */
7162306a36Sopenharmony_ci	const struct regmap_bus *bus;
7262306a36Sopenharmony_ci	void *bus_context;
7362306a36Sopenharmony_ci	const char *name;
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_ci	bool async;
7662306a36Sopenharmony_ci	spinlock_t async_lock;
7762306a36Sopenharmony_ci	wait_queue_head_t async_waitq;
7862306a36Sopenharmony_ci	struct list_head async_list;
7962306a36Sopenharmony_ci	struct list_head async_free;
8062306a36Sopenharmony_ci	int async_ret;
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_ci#ifdef CONFIG_DEBUG_FS
8362306a36Sopenharmony_ci	bool debugfs_disable;
8462306a36Sopenharmony_ci	struct dentry *debugfs;
8562306a36Sopenharmony_ci	const char *debugfs_name;
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ci	unsigned int debugfs_reg_len;
8862306a36Sopenharmony_ci	unsigned int debugfs_val_len;
8962306a36Sopenharmony_ci	unsigned int debugfs_tot_len;
9062306a36Sopenharmony_ci
9162306a36Sopenharmony_ci	struct list_head debugfs_off_cache;
9262306a36Sopenharmony_ci	struct mutex cache_lock;
9362306a36Sopenharmony_ci#endif
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_ci	unsigned int max_register;
9662306a36Sopenharmony_ci	bool (*writeable_reg)(struct device *dev, unsigned int reg);
9762306a36Sopenharmony_ci	bool (*readable_reg)(struct device *dev, unsigned int reg);
9862306a36Sopenharmony_ci	bool (*volatile_reg)(struct device *dev, unsigned int reg);
9962306a36Sopenharmony_ci	bool (*precious_reg)(struct device *dev, unsigned int reg);
10062306a36Sopenharmony_ci	bool (*writeable_noinc_reg)(struct device *dev, unsigned int reg);
10162306a36Sopenharmony_ci	bool (*readable_noinc_reg)(struct device *dev, unsigned int reg);
10262306a36Sopenharmony_ci	const struct regmap_access_table *wr_table;
10362306a36Sopenharmony_ci	const struct regmap_access_table *rd_table;
10462306a36Sopenharmony_ci	const struct regmap_access_table *volatile_table;
10562306a36Sopenharmony_ci	const struct regmap_access_table *precious_table;
10662306a36Sopenharmony_ci	const struct regmap_access_table *wr_noinc_table;
10762306a36Sopenharmony_ci	const struct regmap_access_table *rd_noinc_table;
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_ci	int (*reg_read)(void *context, unsigned int reg, unsigned int *val);
11062306a36Sopenharmony_ci	int (*reg_write)(void *context, unsigned int reg, unsigned int val);
11162306a36Sopenharmony_ci	int (*reg_update_bits)(void *context, unsigned int reg,
11262306a36Sopenharmony_ci			       unsigned int mask, unsigned int val);
11362306a36Sopenharmony_ci	/* Bulk read/write */
11462306a36Sopenharmony_ci	int (*read)(void *context, const void *reg_buf, size_t reg_size,
11562306a36Sopenharmony_ci		    void *val_buf, size_t val_size);
11662306a36Sopenharmony_ci	int (*write)(void *context, const void *data, size_t count);
11762306a36Sopenharmony_ci
11862306a36Sopenharmony_ci	bool defer_caching;
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_ci	unsigned long read_flag_mask;
12162306a36Sopenharmony_ci	unsigned long write_flag_mask;
12262306a36Sopenharmony_ci
12362306a36Sopenharmony_ci	/* number of bits to (left) shift the reg value when formatting*/
12462306a36Sopenharmony_ci	int reg_shift;
12562306a36Sopenharmony_ci	int reg_stride;
12662306a36Sopenharmony_ci	int reg_stride_order;
12762306a36Sopenharmony_ci
12862306a36Sopenharmony_ci	/* If set, will always write field to HW. */
12962306a36Sopenharmony_ci	bool force_write_field;
13062306a36Sopenharmony_ci
13162306a36Sopenharmony_ci	/* regcache specific members */
13262306a36Sopenharmony_ci	const struct regcache_ops *cache_ops;
13362306a36Sopenharmony_ci	enum regcache_type cache_type;
13462306a36Sopenharmony_ci
13562306a36Sopenharmony_ci	/* number of bytes in reg_defaults_raw */
13662306a36Sopenharmony_ci	unsigned int cache_size_raw;
13762306a36Sopenharmony_ci	/* number of bytes per word in reg_defaults_raw */
13862306a36Sopenharmony_ci	unsigned int cache_word_size;
13962306a36Sopenharmony_ci	/* number of entries in reg_defaults */
14062306a36Sopenharmony_ci	unsigned int num_reg_defaults;
14162306a36Sopenharmony_ci	/* number of entries in reg_defaults_raw */
14262306a36Sopenharmony_ci	unsigned int num_reg_defaults_raw;
14362306a36Sopenharmony_ci
14462306a36Sopenharmony_ci	/* if set, only the cache is modified not the HW */
14562306a36Sopenharmony_ci	bool cache_only;
14662306a36Sopenharmony_ci	/* if set, only the HW is modified not the cache */
14762306a36Sopenharmony_ci	bool cache_bypass;
14862306a36Sopenharmony_ci	/* if set, remember to free reg_defaults_raw */
14962306a36Sopenharmony_ci	bool cache_free;
15062306a36Sopenharmony_ci
15162306a36Sopenharmony_ci	struct reg_default *reg_defaults;
15262306a36Sopenharmony_ci	const void *reg_defaults_raw;
15362306a36Sopenharmony_ci	void *cache;
15462306a36Sopenharmony_ci	/* if set, the cache contains newer data than the HW */
15562306a36Sopenharmony_ci	bool cache_dirty;
15662306a36Sopenharmony_ci	/* if set, the HW registers are known to match map->reg_defaults */
15762306a36Sopenharmony_ci	bool no_sync_defaults;
15862306a36Sopenharmony_ci
15962306a36Sopenharmony_ci	struct reg_sequence *patch;
16062306a36Sopenharmony_ci	int patch_regs;
16162306a36Sopenharmony_ci
16262306a36Sopenharmony_ci	/* if set, converts bulk read to single read */
16362306a36Sopenharmony_ci	bool use_single_read;
16462306a36Sopenharmony_ci	/* if set, converts bulk write to single write */
16562306a36Sopenharmony_ci	bool use_single_write;
16662306a36Sopenharmony_ci	/* if set, the device supports multi write mode */
16762306a36Sopenharmony_ci	bool can_multi_write;
16862306a36Sopenharmony_ci
16962306a36Sopenharmony_ci	/* if set, raw reads/writes are limited to this size */
17062306a36Sopenharmony_ci	size_t max_raw_read;
17162306a36Sopenharmony_ci	size_t max_raw_write;
17262306a36Sopenharmony_ci
17362306a36Sopenharmony_ci	struct rb_root range_tree;
17462306a36Sopenharmony_ci	void *selector_work_buf;	/* Scratch buffer used for selector */
17562306a36Sopenharmony_ci
17662306a36Sopenharmony_ci	struct hwspinlock *hwlock;
17762306a36Sopenharmony_ci
17862306a36Sopenharmony_ci	/* if set, the regmap core can sleep */
17962306a36Sopenharmony_ci	bool can_sleep;
18062306a36Sopenharmony_ci};
18162306a36Sopenharmony_ci
18262306a36Sopenharmony_cistruct regcache_ops {
18362306a36Sopenharmony_ci	const char *name;
18462306a36Sopenharmony_ci	enum regcache_type type;
18562306a36Sopenharmony_ci	int (*init)(struct regmap *map);
18662306a36Sopenharmony_ci	int (*exit)(struct regmap *map);
18762306a36Sopenharmony_ci#ifdef CONFIG_DEBUG_FS
18862306a36Sopenharmony_ci	void (*debugfs_init)(struct regmap *map);
18962306a36Sopenharmony_ci#endif
19062306a36Sopenharmony_ci	int (*read)(struct regmap *map, unsigned int reg, unsigned int *value);
19162306a36Sopenharmony_ci	int (*write)(struct regmap *map, unsigned int reg, unsigned int value);
19262306a36Sopenharmony_ci	int (*sync)(struct regmap *map, unsigned int min, unsigned int max);
19362306a36Sopenharmony_ci	int (*drop)(struct regmap *map, unsigned int min, unsigned int max);
19462306a36Sopenharmony_ci};
19562306a36Sopenharmony_ci
19662306a36Sopenharmony_cibool regmap_cached(struct regmap *map, unsigned int reg);
19762306a36Sopenharmony_cibool regmap_writeable(struct regmap *map, unsigned int reg);
19862306a36Sopenharmony_cibool regmap_readable(struct regmap *map, unsigned int reg);
19962306a36Sopenharmony_cibool regmap_volatile(struct regmap *map, unsigned int reg);
20062306a36Sopenharmony_cibool regmap_precious(struct regmap *map, unsigned int reg);
20162306a36Sopenharmony_cibool regmap_writeable_noinc(struct regmap *map, unsigned int reg);
20262306a36Sopenharmony_cibool regmap_readable_noinc(struct regmap *map, unsigned int reg);
20362306a36Sopenharmony_ci
20462306a36Sopenharmony_ciint _regmap_write(struct regmap *map, unsigned int reg,
20562306a36Sopenharmony_ci		  unsigned int val);
20662306a36Sopenharmony_ci
20762306a36Sopenharmony_cistruct regmap_range_node {
20862306a36Sopenharmony_ci	struct rb_node node;
20962306a36Sopenharmony_ci	const char *name;
21062306a36Sopenharmony_ci	struct regmap *map;
21162306a36Sopenharmony_ci
21262306a36Sopenharmony_ci	unsigned int range_min;
21362306a36Sopenharmony_ci	unsigned int range_max;
21462306a36Sopenharmony_ci
21562306a36Sopenharmony_ci	unsigned int selector_reg;
21662306a36Sopenharmony_ci	unsigned int selector_mask;
21762306a36Sopenharmony_ci	int selector_shift;
21862306a36Sopenharmony_ci
21962306a36Sopenharmony_ci	unsigned int window_start;
22062306a36Sopenharmony_ci	unsigned int window_len;
22162306a36Sopenharmony_ci};
22262306a36Sopenharmony_ci
22362306a36Sopenharmony_cistruct regmap_field {
22462306a36Sopenharmony_ci	struct regmap *regmap;
22562306a36Sopenharmony_ci	unsigned int mask;
22662306a36Sopenharmony_ci	/* lsb */
22762306a36Sopenharmony_ci	unsigned int shift;
22862306a36Sopenharmony_ci	unsigned int reg;
22962306a36Sopenharmony_ci
23062306a36Sopenharmony_ci	unsigned int id_size;
23162306a36Sopenharmony_ci	unsigned int id_offset;
23262306a36Sopenharmony_ci};
23362306a36Sopenharmony_ci
23462306a36Sopenharmony_ci#ifdef CONFIG_DEBUG_FS
23562306a36Sopenharmony_ciextern void regmap_debugfs_initcall(void);
23662306a36Sopenharmony_ciextern void regmap_debugfs_init(struct regmap *map);
23762306a36Sopenharmony_ciextern void regmap_debugfs_exit(struct regmap *map);
23862306a36Sopenharmony_ci
23962306a36Sopenharmony_cistatic inline void regmap_debugfs_disable(struct regmap *map)
24062306a36Sopenharmony_ci{
24162306a36Sopenharmony_ci	map->debugfs_disable = true;
24262306a36Sopenharmony_ci}
24362306a36Sopenharmony_ci
24462306a36Sopenharmony_ci#else
24562306a36Sopenharmony_cistatic inline void regmap_debugfs_initcall(void) { }
24662306a36Sopenharmony_cistatic inline void regmap_debugfs_init(struct regmap *map) { }
24762306a36Sopenharmony_cistatic inline void regmap_debugfs_exit(struct regmap *map) { }
24862306a36Sopenharmony_cistatic inline void regmap_debugfs_disable(struct regmap *map) { }
24962306a36Sopenharmony_ci#endif
25062306a36Sopenharmony_ci
25162306a36Sopenharmony_ci/* regcache core declarations */
25262306a36Sopenharmony_ciint regcache_init(struct regmap *map, const struct regmap_config *config);
25362306a36Sopenharmony_civoid regcache_exit(struct regmap *map);
25462306a36Sopenharmony_ciint regcache_read(struct regmap *map,
25562306a36Sopenharmony_ci		       unsigned int reg, unsigned int *value);
25662306a36Sopenharmony_ciint regcache_write(struct regmap *map,
25762306a36Sopenharmony_ci			unsigned int reg, unsigned int value);
25862306a36Sopenharmony_ciint regcache_sync(struct regmap *map);
25962306a36Sopenharmony_ciint regcache_sync_block(struct regmap *map, void *block,
26062306a36Sopenharmony_ci			unsigned long *cache_present,
26162306a36Sopenharmony_ci			unsigned int block_base, unsigned int start,
26262306a36Sopenharmony_ci			unsigned int end);
26362306a36Sopenharmony_cibool regcache_reg_needs_sync(struct regmap *map, unsigned int reg,
26462306a36Sopenharmony_ci			     unsigned int val);
26562306a36Sopenharmony_ci
26662306a36Sopenharmony_cistatic inline const void *regcache_get_val_addr(struct regmap *map,
26762306a36Sopenharmony_ci						const void *base,
26862306a36Sopenharmony_ci						unsigned int idx)
26962306a36Sopenharmony_ci{
27062306a36Sopenharmony_ci	return base + (map->cache_word_size * idx);
27162306a36Sopenharmony_ci}
27262306a36Sopenharmony_ci
27362306a36Sopenharmony_ciunsigned int regcache_get_val(struct regmap *map, const void *base,
27462306a36Sopenharmony_ci			      unsigned int idx);
27562306a36Sopenharmony_civoid regcache_set_val(struct regmap *map, void *base, unsigned int idx,
27662306a36Sopenharmony_ci		      unsigned int val);
27762306a36Sopenharmony_ciint regcache_lookup_reg(struct regmap *map, unsigned int reg);
27862306a36Sopenharmony_ciint regcache_sync_val(struct regmap *map, unsigned int reg, unsigned int val);
27962306a36Sopenharmony_ci
28062306a36Sopenharmony_ciint _regmap_raw_write(struct regmap *map, unsigned int reg,
28162306a36Sopenharmony_ci		      const void *val, size_t val_len, bool noinc);
28262306a36Sopenharmony_ci
28362306a36Sopenharmony_civoid regmap_async_complete_cb(struct regmap_async *async, int ret);
28462306a36Sopenharmony_ci
28562306a36Sopenharmony_cienum regmap_endian regmap_get_val_endian(struct device *dev,
28662306a36Sopenharmony_ci					 const struct regmap_bus *bus,
28762306a36Sopenharmony_ci					 const struct regmap_config *config);
28862306a36Sopenharmony_ci
28962306a36Sopenharmony_ciextern struct regcache_ops regcache_rbtree_ops;
29062306a36Sopenharmony_ciextern struct regcache_ops regcache_maple_ops;
29162306a36Sopenharmony_ciextern struct regcache_ops regcache_flat_ops;
29262306a36Sopenharmony_ci
29362306a36Sopenharmony_cistatic inline const char *regmap_name(const struct regmap *map)
29462306a36Sopenharmony_ci{
29562306a36Sopenharmony_ci	if (map->dev)
29662306a36Sopenharmony_ci		return dev_name(map->dev);
29762306a36Sopenharmony_ci
29862306a36Sopenharmony_ci	return map->name;
29962306a36Sopenharmony_ci}
30062306a36Sopenharmony_ci
30162306a36Sopenharmony_cistatic inline unsigned int regmap_get_offset(const struct regmap *map,
30262306a36Sopenharmony_ci					     unsigned int index)
30362306a36Sopenharmony_ci{
30462306a36Sopenharmony_ci	if (map->reg_stride_order >= 0)
30562306a36Sopenharmony_ci		return index << map->reg_stride_order;
30662306a36Sopenharmony_ci	else
30762306a36Sopenharmony_ci		return index * map->reg_stride;
30862306a36Sopenharmony_ci}
30962306a36Sopenharmony_ci
31062306a36Sopenharmony_cistatic inline unsigned int regcache_get_index_by_order(const struct regmap *map,
31162306a36Sopenharmony_ci						       unsigned int reg)
31262306a36Sopenharmony_ci{
31362306a36Sopenharmony_ci	return reg >> map->reg_stride_order;
31462306a36Sopenharmony_ci}
31562306a36Sopenharmony_ci
31662306a36Sopenharmony_cistruct regmap_ram_data {
31762306a36Sopenharmony_ci	unsigned int *vals;  /* Allocatd by caller */
31862306a36Sopenharmony_ci	bool *read;
31962306a36Sopenharmony_ci	bool *written;
32062306a36Sopenharmony_ci	enum regmap_endian reg_endian;
32162306a36Sopenharmony_ci};
32262306a36Sopenharmony_ci
32362306a36Sopenharmony_ci/*
32462306a36Sopenharmony_ci * Create a test register map with data stored in RAM, not intended
32562306a36Sopenharmony_ci * for practical use.
32662306a36Sopenharmony_ci */
32762306a36Sopenharmony_cistruct regmap *__regmap_init_ram(const struct regmap_config *config,
32862306a36Sopenharmony_ci				 struct regmap_ram_data *data,
32962306a36Sopenharmony_ci				 struct lock_class_key *lock_key,
33062306a36Sopenharmony_ci				 const char *lock_name);
33162306a36Sopenharmony_ci
33262306a36Sopenharmony_ci#define regmap_init_ram(config, data)					\
33362306a36Sopenharmony_ci	__regmap_lockdep_wrapper(__regmap_init_ram, #config, config, data)
33462306a36Sopenharmony_ci
33562306a36Sopenharmony_cistruct regmap *__regmap_init_raw_ram(const struct regmap_config *config,
33662306a36Sopenharmony_ci				     struct regmap_ram_data *data,
33762306a36Sopenharmony_ci				     struct lock_class_key *lock_key,
33862306a36Sopenharmony_ci				     const char *lock_name);
33962306a36Sopenharmony_ci
34062306a36Sopenharmony_ci#define regmap_init_raw_ram(config, data)				\
34162306a36Sopenharmony_ci	__regmap_lockdep_wrapper(__regmap_init_raw_ram, #config, config, data)
34262306a36Sopenharmony_ci
34362306a36Sopenharmony_ci#endif
344