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