首页 > 系统相关 >01-[Linux][regmap]regmap模块介绍

01-[Linux][regmap]regmap模块介绍

时间:2023-08-09 16:01:50浏览次数:43  
标签:01 struct int unsigned bool Linux regmap reg

1、什么是regmap?

Linux引入regmap是为了统一管理内核的i2c,spi等总线,将i2c、spi驱动做了一次重构,把I/O读写的重复逻辑在regmap中实现。只需初始化时指定总线类型、寄存器位宽等关键参数,即可通过regmap模型接口来操作器件寄存器。

将i2c、spi、mmio、irq等抽象出统一接口regmap_read,regmap_write,regmap_update_bits等接口,从而提高代码的可重用性;regmap是在Linux内核为减少慢速I/O驱动上的重复逻辑,提供的一种通用接口来操作底层硬件寄存器的模型框架。

此外,如果在regmap中使用cache,会减少底层低速I/O的操作次数,提高访问效率,但是会降低操作的实时性。

2、regmap的架构


regmap框架主要分为三层,如上图所示:

  • 底层物理总线:regmap对不同的物理总线进行封装,目前regmap支持的物理总线有i2c、i3c、spi、mmio、sccb等
  • regmap核心层:用于实现regmap,链接API抽象层和物理层
  • regmap API抽象层,向驱动编写人员提供API接口,驱动编写人员使用这些API接口来操作具体的芯片设备,也是驱动编写人员重点要掌握的。

3、regmap数据结构

相关的代码路径:

include/linux/regmap.h
drivers/base/regmap/

3.1 regmap结构体

Linux内核将regmap框架抽象为regmap结构体,如下:

Path:drivers/base/regmap/internal.h
struct regmap {
	union {
		struct mutex mutex;
		struct {
			spinlock_t spinlock;
			unsigned long spinlock_flags;
		};
		struct {
			raw_spinlock_t raw_spinlock;
			unsigned long raw_spinlock_flags;
		};
	};
	regmap_lock lock;
	regmap_unlock unlock;
	void *lock_arg; /* This is passed to lock/unlock functions */
	gfp_t alloc_flags;
	unsigned int reg_base;

	struct device *dev; /* Device we do I/O on */
	void *work_buf;     /* Scratch buffer used to format I/O */
	struct regmap_format format;  /* Buffer format */
	const struct regmap_bus *bus;
	void *bus_context;
	const char *name;

	bool async;
	spinlock_t async_lock;
	wait_queue_head_t async_waitq;
	struct list_head async_list;
	struct list_head async_free;
	int async_ret;

#ifdef CONFIG_DEBUG_FS
	bool debugfs_disable;
	struct dentry *debugfs;
	const char *debugfs_name;

	unsigned int debugfs_reg_len;
	unsigned int debugfs_val_len;
	unsigned int debugfs_tot_len;

	struct list_head debugfs_off_cache;
	struct mutex cache_lock;
#endif

	unsigned int max_register;
	bool (*writeable_reg)(struct device *dev, unsigned int reg);
	bool (*readable_reg)(struct device *dev, unsigned int reg);
	bool (*volatile_reg)(struct device *dev, unsigned int reg);
	bool (*precious_reg)(struct device *dev, unsigned int reg);
	bool (*writeable_noinc_reg)(struct device *dev, unsigned int reg);
	bool (*readable_noinc_reg)(struct device *dev, unsigned int reg);
	const struct regmap_access_table *wr_table;
	const struct regmap_access_table *rd_table;
	const struct regmap_access_table *volatile_table;
	const struct regmap_access_table *precious_table;
	const struct regmap_access_table *wr_noinc_table;
	const struct regmap_access_table *rd_noinc_table;

	int (*reg_read)(void *context, unsigned int reg, unsigned int *val);
	int (*reg_write)(void *context, unsigned int reg, unsigned int val);
	int (*reg_update_bits)(void *context, unsigned int reg,
			       unsigned int mask, unsigned int val);
	/* Bulk read/write */
	int (*read)(void *context, const void *reg_buf, size_t reg_size,
		    void *val_buf, size_t val_size);
	int (*write)(void *context, const void *data, size_t count);

	bool defer_caching;

	unsigned long read_flag_mask;
	unsigned long write_flag_mask;

	/* number of bits to (left) shift the reg value when formatting*/
	int reg_shift;
	int reg_stride;
	int reg_stride_order;

	/* regcache specific members */
	const struct regcache_ops *cache_ops;
	enum regcache_type cache_type;

	/* number of bytes in reg_defaults_raw */
	unsigned int cache_size_raw;
	/* number of bytes per word in reg_defaults_raw */
	unsigned int cache_word_size;
	/* number of entries in reg_defaults */
	unsigned int num_reg_defaults;
	/* number of entries in reg_defaults_raw */
	unsigned int num_reg_defaults_raw;

	/* if set, only the cache is modified not the HW */
	bool cache_only;
	/* if set, only the HW is modified not the cache */
	bool cache_bypass;
	/* if set, remember to free reg_defaults_raw */
	bool cache_free;

	struct reg_default *reg_defaults;
	const void *reg_defaults_raw;
	void *cache;
	/* if set, the cache contains newer data than the HW */
	bool cache_dirty;
	/* if set, the HW registers are known to match map->reg_defaults */
	bool no_sync_defaults;

	struct reg_sequence *patch;
	int patch_regs;

	/* if set, converts bulk read to single read */
	bool use_single_read;
	/* if set, converts bulk write to single write */
	bool use_single_write;
	/* if set, the device supports multi write mode */
	bool can_multi_write;

	/* if set, raw reads/writes are limited to this size */
	size_t max_raw_read;
	size_t max_raw_write;

	struct rb_root range_tree;
	void *selector_work_buf;	/* Scratch buffer used for selector */

	struct hwspinlock *hwlock;

	/* if set, the regmap core can sleep */
	bool can_sleep;
};

使用regmap_init_xxxxx等接口函数,根据regmap_config和bus结构体的数据来初始化regmap结构体。

3.2 regmap_config结构体

// include/linux/regmap.h
struct regmap_config {
    const char *name; // 可选,寄存器名字

    int reg_bits; // 寄存器地址位宽,必须填写
    int reg_stride; // 寄存器操作宽度,比如为1时,所有寄存器可操作,为2时,只有2^n可操作
    int pad_bits;
    int val_bits; // 寄存器值的位宽,必须填写
    // 可选,判断寄存器是否可写,可读,是否可缓冲等回调
    bool (*writeable_reg)(struct device *dev, unsigned int reg);
    bool (*readable_reg)(struct device *dev, unsigned int reg);
    bool (*volatile_reg)(struct device *dev, unsigned int reg);
    bool (*precious_reg)(struct device *dev, unsigned int reg);
    regmap_lock lock;
    regmap_unlock unlock;
    void *lock_arg;
    // 寄存器读写方法,可选
    int (*reg_read)(void *context, unsigned int reg, unsigned int *val);
    int (*reg_write)(void *context, unsigned int reg, unsigned int val);

    bool fast_io;

    unsigned int max_register;
    const struct regmap_access_table *wr_table; //可选,可写寄存器
    const struct regmap_access_table *rd_table;//可选,可读寄存器
    const struct regmap_access_table *volatile_table;
    const struct regmap_access_table *precious_table;
    const struct reg_default *reg_defaults;
    unsigned int num_reg_defaults;
    enum regcache_type cache_type; // 缓冲方式
    const void *reg_defaults_raw;
    unsigned int num_reg_defaults_raw;

    u8 read_flag_mask;
    u8 write_flag_mask;

    bool use_single_rw;
    bool can_multi_write;

    enum regmap_endian reg_format_endian;
    enum regmap_endian val_format_endian;

    const struct regmap_range_cfg *ranges;
    unsigned int num_ranges;
};

4、使用案例

/* 1. 配置信息 */
static const struct regmap_config regmap_config =
{
    .reg_bits = 8,
    .val_bits = 8,
    .max_register = 255,
    .cache_type = REGCACHE_NONE,
    .volatile_reg = false,
};

/* 2. 注册regmap实例 */
regmap = regmap_init_i2c(i2c_client, &regmap_config);

/* 3. 访问操作 */
regmap_raw_read(regmap, reg, &data, size);

/* 4. 注销regmap */
regmap_exit(regmap);

参考链接

1、https://www.cnblogs.com/schips/p/linix_regmap.html
2、https://blog.csdn.net/zhuyong006/article/details/80931397
3、https://blog.csdn.net/qq_44182115/article/details/123331499
4、https://www.cnblogs.com/schips/p/using_regmap_in_linux_kernel.html
5、https://zhuanlan.zhihu.com/p/550695692

标签:01,struct,int,unsigned,bool,Linux,regmap,reg
From: https://www.cnblogs.com/hkcs596/p/17606431.html

相关文章

  • Linux网络服务之网络文件服务(NFS)
    目录1.存储和NFS共享1.1NFS概述1.2存储类型1.3三种存储架构应用场景1.4NFS工作原理2.FTP文件传输协议2.1FTP工作原理介绍2.2常见FTP相关软件1.存储和NFS共享1.1NFS概述NFS(NetworkFileSystem网络文件服务)是文件系统,是操作系统内核来管理的,用于在网络上分享和访问......
  • ​ 2014年6月大学英语六级​作文真题及参考范文
    ​ 文都教育:6月英语六级作文真题及参考范文 2014年6月大学英语六级考试已经结束,文都教育第一时间为大家提供英语六级作文范,供参考。【六级作文真题】Forthispart,youareallowed30minutestowriteanessayexplainingwhyitisunwisetojudgeaperson......
  • 新东方在线:2014年6月四级作文真题范文及解析
    新东方在线:2014年6月四级作文真题范文及解析 题:Supposeaforeignfriendofyoursisgoingtovisityourhometown/yourcampus/China(多题多卷的三个不同),whatisthemostinterestingplaceyouwouldliketotakehim/hertoseeandwhy?范文:Themostinteresting......
  • 2014年6月大学英语四级考试翻译原文与参考译文
    2014-6-14翻译 教育公平:为了促进教育公平,中国已经投入360亿元,用于改善农村地区教育设施和加强中西部地区农村义务教育。这些资金用于改善教学设施、购买书籍,使16万多所中小学收益。资金还用于购置音乐和绘画器材。现在农村和山区的儿童可以与沿海城市的儿童一样上音乐和绘画......
  • 新东方在线:2014年6月英语六级翻译真题答案
    新东方在线:2014年6月英语六级翻译真题答案 翻译一:中文热词通常反映社会变化和文化,有些在外国媒体上愈来愈流行。例如,土豪和大妈都是老词,但已获取了新的意义。土豪以前指欺压佃户和仆人的乡村地主,现在用于指花钱如流水或喜欢炫耀财富的人,也就是说,土豪有钱,但是没有品位......
  • EB-RV1126-DC201开发板实现USB摄像头抓图
    1126的开发板内核已经把USB的驱动配置好了,但是USB摄像头的驱动还没有配置,所以要在内核打开UVC驱动第一步:修改rv1126_defconfig添加以下内容第二步,回到SDK根目录编译第三步:烧录好固件,使用v4l2-ctl-list-devices查看列表,会显示生成新的节点。第四步:识别到新的节点后,就可以用这......
  • Linux各种错误
    1、sudo:aterminalisrequiredtoreadthepassword;eitherusethe-Soptiontoreadfromstandardinorconfigureanaskpasshelpersudo:aterminalisrequiredtoreadthepassword;eitheruse.....问题解决方法2、wget:未找到命令yum-yinstallwget3、由......
  • Linux Ubuntu Helloworld 模块 的编译 插入 删除
    总述:编写.c文件和Makefile文件->make->生成点.ko文件->insmode->lsmode->rmmode. 一、编写Hello.c与Makefile ubuntu@ubuntu-VirtualBox:/$cd~/Desktop/ubuntu@ubuntu-VirtualBox:~/Desktop$cdMooc/ubuntu@ubuntu-VirtualBox:~/Desktop/Mooc$vimhelloworld.cubuntu......
  • P9507 [BalkanOI2018] Popa 题解
    原题传送门题目描述Ghiță有一个下标从\(0\)开始的正整数序列\(S\)。因为他是喀尔巴阡的国王,所以他想要构造一个节点编号为\(0,1,\ldots,N-1\)的二叉树,满足:树的中序遍历按节点编号升序排列。二叉树的中序遍历由以根的左子节点(如果存在)为根形成的子树的中序遍历,根的节......
  • linux配置 崩溃生成core 转储
    ulimit-c查看core文件大小限制0表达不生成ulimit-cunlimited设置为不限制vim/proc/sys/kernel/core_pattern编辑生成规则|/usr/share/apport/apport%p%s%c%d%P%E%p:进程ID(PID)%s:进程名称(通常是可执行文件的名称)%c:命令行参数%d:应用程序的工作目录%P:包含应......