18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Register map access API internal header 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright 2011 Wolfson Microelectronics plc 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> 88c2ecf20Sopenharmony_ci */ 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#ifndef _REGMAP_INTERNAL_H 118c2ecf20Sopenharmony_ci#define _REGMAP_INTERNAL_H 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci#include <linux/device.h> 148c2ecf20Sopenharmony_ci#include <linux/regmap.h> 158c2ecf20Sopenharmony_ci#include <linux/fs.h> 168c2ecf20Sopenharmony_ci#include <linux/list.h> 178c2ecf20Sopenharmony_ci#include <linux/wait.h> 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_cistruct regmap; 208c2ecf20Sopenharmony_cistruct regcache_ops; 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_cistruct regmap_debugfs_off_cache { 238c2ecf20Sopenharmony_ci struct list_head list; 248c2ecf20Sopenharmony_ci off_t min; 258c2ecf20Sopenharmony_ci off_t max; 268c2ecf20Sopenharmony_ci unsigned int base_reg; 278c2ecf20Sopenharmony_ci unsigned int max_reg; 288c2ecf20Sopenharmony_ci}; 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_cistruct regmap_format { 318c2ecf20Sopenharmony_ci size_t buf_size; 328c2ecf20Sopenharmony_ci size_t reg_bytes; 338c2ecf20Sopenharmony_ci size_t pad_bytes; 348c2ecf20Sopenharmony_ci size_t val_bytes; 358c2ecf20Sopenharmony_ci void (*format_write)(struct regmap *map, 368c2ecf20Sopenharmony_ci unsigned int reg, unsigned int val); 378c2ecf20Sopenharmony_ci void (*format_reg)(void *buf, unsigned int reg, unsigned int shift); 388c2ecf20Sopenharmony_ci void (*format_val)(void *buf, unsigned int val, unsigned int shift); 398c2ecf20Sopenharmony_ci unsigned int (*parse_val)(const void *buf); 408c2ecf20Sopenharmony_ci void (*parse_inplace)(void *buf); 418c2ecf20Sopenharmony_ci}; 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_cistruct regmap_async { 448c2ecf20Sopenharmony_ci struct list_head list; 458c2ecf20Sopenharmony_ci struct regmap *map; 468c2ecf20Sopenharmony_ci void *work_buf; 478c2ecf20Sopenharmony_ci}; 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_cistruct regmap { 508c2ecf20Sopenharmony_ci union { 518c2ecf20Sopenharmony_ci struct mutex mutex; 528c2ecf20Sopenharmony_ci struct { 538c2ecf20Sopenharmony_ci spinlock_t spinlock; 548c2ecf20Sopenharmony_ci unsigned long spinlock_flags; 558c2ecf20Sopenharmony_ci }; 568c2ecf20Sopenharmony_ci }; 578c2ecf20Sopenharmony_ci regmap_lock lock; 588c2ecf20Sopenharmony_ci regmap_unlock unlock; 598c2ecf20Sopenharmony_ci void *lock_arg; /* This is passed to lock/unlock functions */ 608c2ecf20Sopenharmony_ci gfp_t alloc_flags; 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci struct device *dev; /* Device we do I/O on */ 638c2ecf20Sopenharmony_ci void *work_buf; /* Scratch buffer used to format I/O */ 648c2ecf20Sopenharmony_ci struct regmap_format format; /* Buffer format */ 658c2ecf20Sopenharmony_ci const struct regmap_bus *bus; 668c2ecf20Sopenharmony_ci void *bus_context; 678c2ecf20Sopenharmony_ci const char *name; 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ci bool async; 708c2ecf20Sopenharmony_ci spinlock_t async_lock; 718c2ecf20Sopenharmony_ci wait_queue_head_t async_waitq; 728c2ecf20Sopenharmony_ci struct list_head async_list; 738c2ecf20Sopenharmony_ci struct list_head async_free; 748c2ecf20Sopenharmony_ci int async_ret; 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci#ifdef CONFIG_DEBUG_FS 778c2ecf20Sopenharmony_ci bool debugfs_disable; 788c2ecf20Sopenharmony_ci struct dentry *debugfs; 798c2ecf20Sopenharmony_ci const char *debugfs_name; 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci unsigned int debugfs_reg_len; 828c2ecf20Sopenharmony_ci unsigned int debugfs_val_len; 838c2ecf20Sopenharmony_ci unsigned int debugfs_tot_len; 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci struct list_head debugfs_off_cache; 868c2ecf20Sopenharmony_ci struct mutex cache_lock; 878c2ecf20Sopenharmony_ci#endif 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci unsigned int max_register; 908c2ecf20Sopenharmony_ci bool (*writeable_reg)(struct device *dev, unsigned int reg); 918c2ecf20Sopenharmony_ci bool (*readable_reg)(struct device *dev, unsigned int reg); 928c2ecf20Sopenharmony_ci bool (*volatile_reg)(struct device *dev, unsigned int reg); 938c2ecf20Sopenharmony_ci bool (*precious_reg)(struct device *dev, unsigned int reg); 948c2ecf20Sopenharmony_ci bool (*writeable_noinc_reg)(struct device *dev, unsigned int reg); 958c2ecf20Sopenharmony_ci bool (*readable_noinc_reg)(struct device *dev, unsigned int reg); 968c2ecf20Sopenharmony_ci const struct regmap_access_table *wr_table; 978c2ecf20Sopenharmony_ci const struct regmap_access_table *rd_table; 988c2ecf20Sopenharmony_ci const struct regmap_access_table *volatile_table; 998c2ecf20Sopenharmony_ci const struct regmap_access_table *precious_table; 1008c2ecf20Sopenharmony_ci const struct regmap_access_table *wr_noinc_table; 1018c2ecf20Sopenharmony_ci const struct regmap_access_table *rd_noinc_table; 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci int (*reg_read)(void *context, unsigned int reg, unsigned int *val); 1048c2ecf20Sopenharmony_ci int (*reg_write)(void *context, unsigned int reg, unsigned int val); 1058c2ecf20Sopenharmony_ci int (*reg_update_bits)(void *context, unsigned int reg, 1068c2ecf20Sopenharmony_ci unsigned int mask, unsigned int val); 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci bool defer_caching; 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_ci unsigned long read_flag_mask; 1118c2ecf20Sopenharmony_ci unsigned long write_flag_mask; 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_ci /* number of bits to (left) shift the reg value when formatting*/ 1148c2ecf20Sopenharmony_ci int reg_shift; 1158c2ecf20Sopenharmony_ci int reg_stride; 1168c2ecf20Sopenharmony_ci int reg_stride_order; 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci /* regcache specific members */ 1198c2ecf20Sopenharmony_ci const struct regcache_ops *cache_ops; 1208c2ecf20Sopenharmony_ci enum regcache_type cache_type; 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_ci /* number of bytes in reg_defaults_raw */ 1238c2ecf20Sopenharmony_ci unsigned int cache_size_raw; 1248c2ecf20Sopenharmony_ci /* number of bytes per word in reg_defaults_raw */ 1258c2ecf20Sopenharmony_ci unsigned int cache_word_size; 1268c2ecf20Sopenharmony_ci /* number of entries in reg_defaults */ 1278c2ecf20Sopenharmony_ci unsigned int num_reg_defaults; 1288c2ecf20Sopenharmony_ci /* number of entries in reg_defaults_raw */ 1298c2ecf20Sopenharmony_ci unsigned int num_reg_defaults_raw; 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_ci /* if set, only the cache is modified not the HW */ 1328c2ecf20Sopenharmony_ci bool cache_only; 1338c2ecf20Sopenharmony_ci /* if set, only the HW is modified not the cache */ 1348c2ecf20Sopenharmony_ci bool cache_bypass; 1358c2ecf20Sopenharmony_ci /* if set, remember to free reg_defaults_raw */ 1368c2ecf20Sopenharmony_ci bool cache_free; 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_ci struct reg_default *reg_defaults; 1398c2ecf20Sopenharmony_ci const void *reg_defaults_raw; 1408c2ecf20Sopenharmony_ci void *cache; 1418c2ecf20Sopenharmony_ci /* if set, the cache contains newer data than the HW */ 1428c2ecf20Sopenharmony_ci bool cache_dirty; 1438c2ecf20Sopenharmony_ci /* if set, the HW registers are known to match map->reg_defaults */ 1448c2ecf20Sopenharmony_ci bool no_sync_defaults; 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ci struct reg_sequence *patch; 1478c2ecf20Sopenharmony_ci int patch_regs; 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci /* if set, converts bulk read to single read */ 1508c2ecf20Sopenharmony_ci bool use_single_read; 1518c2ecf20Sopenharmony_ci /* if set, converts bulk write to single write */ 1528c2ecf20Sopenharmony_ci bool use_single_write; 1538c2ecf20Sopenharmony_ci /* if set, the device supports multi write mode */ 1548c2ecf20Sopenharmony_ci bool can_multi_write; 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_ci /* if set, raw reads/writes are limited to this size */ 1578c2ecf20Sopenharmony_ci size_t max_raw_read; 1588c2ecf20Sopenharmony_ci size_t max_raw_write; 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci struct rb_root range_tree; 1618c2ecf20Sopenharmony_ci void *selector_work_buf; /* Scratch buffer used for selector */ 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci struct hwspinlock *hwlock; 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_ci /* if set, the regmap core can sleep */ 1668c2ecf20Sopenharmony_ci bool can_sleep; 1678c2ecf20Sopenharmony_ci}; 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_cistruct regcache_ops { 1708c2ecf20Sopenharmony_ci const char *name; 1718c2ecf20Sopenharmony_ci enum regcache_type type; 1728c2ecf20Sopenharmony_ci int (*init)(struct regmap *map); 1738c2ecf20Sopenharmony_ci int (*exit)(struct regmap *map); 1748c2ecf20Sopenharmony_ci#ifdef CONFIG_DEBUG_FS 1758c2ecf20Sopenharmony_ci void (*debugfs_init)(struct regmap *map); 1768c2ecf20Sopenharmony_ci#endif 1778c2ecf20Sopenharmony_ci int (*read)(struct regmap *map, unsigned int reg, unsigned int *value); 1788c2ecf20Sopenharmony_ci int (*write)(struct regmap *map, unsigned int reg, unsigned int value); 1798c2ecf20Sopenharmony_ci int (*sync)(struct regmap *map, unsigned int min, unsigned int max); 1808c2ecf20Sopenharmony_ci int (*drop)(struct regmap *map, unsigned int min, unsigned int max); 1818c2ecf20Sopenharmony_ci}; 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_cibool regmap_cached(struct regmap *map, unsigned int reg); 1848c2ecf20Sopenharmony_cibool regmap_writeable(struct regmap *map, unsigned int reg); 1858c2ecf20Sopenharmony_cibool regmap_readable(struct regmap *map, unsigned int reg); 1868c2ecf20Sopenharmony_cibool regmap_volatile(struct regmap *map, unsigned int reg); 1878c2ecf20Sopenharmony_cibool regmap_precious(struct regmap *map, unsigned int reg); 1888c2ecf20Sopenharmony_cibool regmap_writeable_noinc(struct regmap *map, unsigned int reg); 1898c2ecf20Sopenharmony_cibool regmap_readable_noinc(struct regmap *map, unsigned int reg); 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_ciint _regmap_write(struct regmap *map, unsigned int reg, 1928c2ecf20Sopenharmony_ci unsigned int val); 1938c2ecf20Sopenharmony_ci 1948c2ecf20Sopenharmony_cistruct regmap_range_node { 1958c2ecf20Sopenharmony_ci struct rb_node node; 1968c2ecf20Sopenharmony_ci const char *name; 1978c2ecf20Sopenharmony_ci struct regmap *map; 1988c2ecf20Sopenharmony_ci 1998c2ecf20Sopenharmony_ci unsigned int range_min; 2008c2ecf20Sopenharmony_ci unsigned int range_max; 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_ci unsigned int selector_reg; 2038c2ecf20Sopenharmony_ci unsigned int selector_mask; 2048c2ecf20Sopenharmony_ci int selector_shift; 2058c2ecf20Sopenharmony_ci 2068c2ecf20Sopenharmony_ci unsigned int window_start; 2078c2ecf20Sopenharmony_ci unsigned int window_len; 2088c2ecf20Sopenharmony_ci}; 2098c2ecf20Sopenharmony_ci 2108c2ecf20Sopenharmony_cistruct regmap_field { 2118c2ecf20Sopenharmony_ci struct regmap *regmap; 2128c2ecf20Sopenharmony_ci unsigned int mask; 2138c2ecf20Sopenharmony_ci /* lsb */ 2148c2ecf20Sopenharmony_ci unsigned int shift; 2158c2ecf20Sopenharmony_ci unsigned int reg; 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_ci unsigned int id_size; 2188c2ecf20Sopenharmony_ci unsigned int id_offset; 2198c2ecf20Sopenharmony_ci}; 2208c2ecf20Sopenharmony_ci 2218c2ecf20Sopenharmony_ci#ifdef CONFIG_DEBUG_FS 2228c2ecf20Sopenharmony_ciextern void regmap_debugfs_initcall(void); 2238c2ecf20Sopenharmony_ciextern void regmap_debugfs_init(struct regmap *map); 2248c2ecf20Sopenharmony_ciextern void regmap_debugfs_exit(struct regmap *map); 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_cistatic inline void regmap_debugfs_disable(struct regmap *map) 2278c2ecf20Sopenharmony_ci{ 2288c2ecf20Sopenharmony_ci map->debugfs_disable = true; 2298c2ecf20Sopenharmony_ci} 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_ci#else 2328c2ecf20Sopenharmony_cistatic inline void regmap_debugfs_initcall(void) { } 2338c2ecf20Sopenharmony_cistatic inline void regmap_debugfs_init(struct regmap *map) { } 2348c2ecf20Sopenharmony_cistatic inline void regmap_debugfs_exit(struct regmap *map) { } 2358c2ecf20Sopenharmony_cistatic inline void regmap_debugfs_disable(struct regmap *map) { } 2368c2ecf20Sopenharmony_ci#endif 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_ci/* regcache core declarations */ 2398c2ecf20Sopenharmony_ciint regcache_init(struct regmap *map, const struct regmap_config *config); 2408c2ecf20Sopenharmony_civoid regcache_exit(struct regmap *map); 2418c2ecf20Sopenharmony_ciint regcache_read(struct regmap *map, 2428c2ecf20Sopenharmony_ci unsigned int reg, unsigned int *value); 2438c2ecf20Sopenharmony_ciint regcache_write(struct regmap *map, 2448c2ecf20Sopenharmony_ci unsigned int reg, unsigned int value); 2458c2ecf20Sopenharmony_ciint regcache_sync(struct regmap *map); 2468c2ecf20Sopenharmony_ciint regcache_sync_block(struct regmap *map, void *block, 2478c2ecf20Sopenharmony_ci unsigned long *cache_present, 2488c2ecf20Sopenharmony_ci unsigned int block_base, unsigned int start, 2498c2ecf20Sopenharmony_ci unsigned int end); 2508c2ecf20Sopenharmony_ci 2518c2ecf20Sopenharmony_cistatic inline const void *regcache_get_val_addr(struct regmap *map, 2528c2ecf20Sopenharmony_ci const void *base, 2538c2ecf20Sopenharmony_ci unsigned int idx) 2548c2ecf20Sopenharmony_ci{ 2558c2ecf20Sopenharmony_ci return base + (map->cache_word_size * idx); 2568c2ecf20Sopenharmony_ci} 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_ciunsigned int regcache_get_val(struct regmap *map, const void *base, 2598c2ecf20Sopenharmony_ci unsigned int idx); 2608c2ecf20Sopenharmony_cibool regcache_set_val(struct regmap *map, void *base, unsigned int idx, 2618c2ecf20Sopenharmony_ci unsigned int val); 2628c2ecf20Sopenharmony_ciint regcache_lookup_reg(struct regmap *map, unsigned int reg); 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_ciint _regmap_raw_write(struct regmap *map, unsigned int reg, 2658c2ecf20Sopenharmony_ci const void *val, size_t val_len, bool noinc); 2668c2ecf20Sopenharmony_ci 2678c2ecf20Sopenharmony_civoid regmap_async_complete_cb(struct regmap_async *async, int ret); 2688c2ecf20Sopenharmony_ci 2698c2ecf20Sopenharmony_cienum regmap_endian regmap_get_val_endian(struct device *dev, 2708c2ecf20Sopenharmony_ci const struct regmap_bus *bus, 2718c2ecf20Sopenharmony_ci const struct regmap_config *config); 2728c2ecf20Sopenharmony_ci 2738c2ecf20Sopenharmony_ciextern struct regcache_ops regcache_rbtree_ops; 2748c2ecf20Sopenharmony_ciextern struct regcache_ops regcache_lzo_ops; 2758c2ecf20Sopenharmony_ciextern struct regcache_ops regcache_flat_ops; 2768c2ecf20Sopenharmony_ci 2778c2ecf20Sopenharmony_cistatic inline const char *regmap_name(const struct regmap *map) 2788c2ecf20Sopenharmony_ci{ 2798c2ecf20Sopenharmony_ci if (map->dev) 2808c2ecf20Sopenharmony_ci return dev_name(map->dev); 2818c2ecf20Sopenharmony_ci 2828c2ecf20Sopenharmony_ci return map->name; 2838c2ecf20Sopenharmony_ci} 2848c2ecf20Sopenharmony_ci 2858c2ecf20Sopenharmony_cistatic inline unsigned int regmap_get_offset(const struct regmap *map, 2868c2ecf20Sopenharmony_ci unsigned int index) 2878c2ecf20Sopenharmony_ci{ 2888c2ecf20Sopenharmony_ci if (map->reg_stride_order >= 0) 2898c2ecf20Sopenharmony_ci return index << map->reg_stride_order; 2908c2ecf20Sopenharmony_ci else 2918c2ecf20Sopenharmony_ci return index * map->reg_stride; 2928c2ecf20Sopenharmony_ci} 2938c2ecf20Sopenharmony_ci 2948c2ecf20Sopenharmony_cistatic inline unsigned int regcache_get_index_by_order(const struct regmap *map, 2958c2ecf20Sopenharmony_ci unsigned int reg) 2968c2ecf20Sopenharmony_ci{ 2978c2ecf20Sopenharmony_ci return reg >> map->reg_stride_order; 2988c2ecf20Sopenharmony_ci} 2998c2ecf20Sopenharmony_ci 3008c2ecf20Sopenharmony_ci#endif 301