regmap demo

文章介绍了Linux内核中的regmap结构及其在设备驱动中的使用,通过示例展示了如何初始化和操作内存映射寄存器。讨论了`structregmap_config`的关键成员以及不同模块如I2C、MDIO和SPI的集成方式。
摘要由CSDN通过智能技术生成

最近调试模块,用到了regmap,事后了解了一下,觉得还是有点意思的东西

以下是最新的linux源码对于regmap_config的结构,可以看到函数指针以及一些变量
源码中直接搜索"struct regmap_config"是可以搜到其他模块是如何使用这个变量的
也就能看到初始化的时候,初始化了哪些变量.(能看到这里的应该不用一个个解释了吧)

struct regmap_config {
	const char *name;

	int reg_bits;
	int reg_stride;
	int reg_shift;
	unsigned int reg_base;
	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);
	bool (*writeable_noinc_reg)(struct device *dev, unsigned int reg);
	bool (*readable_noinc_reg)(struct device *dev, unsigned int reg);

	bool disable_locking;
	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);
	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);
	size_t max_raw_read;
	size_t max_raw_write;

	bool fast_io;
	bool io_port;

	unsigned int max_register;
	bool max_register_is_0;
	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;
	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;

	unsigned long read_flag_mask;
	unsigned long write_flag_mask;
	bool zero_flag_mask;

	bool use_single_read;
	bool use_single_write;
	bool use_relaxed_mmio;
	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;

	bool use_hwlock;
	bool use_raw_spinlock;
	unsigned int hwlock_id;
	unsigned int hwlock_mode;

	bool can_sleep;
};

上面的结构是一个基础模块

//可以直接使用下面这个宏初始化ragmap
#define devm_regmap_init(dev, bus, bus_context, config)			\
	__regmap_lockdep_wrapper(__devm_regmap_init, #config,		\
				dev, bus, bus_context, config)

//实际的源码中还提供了一些二次封装的实现
#define devm_regmap_init_i2c(i2c, config)				\
	__regmap_lockdep_wrapper(__devm_regmap_init_i2c, #config,	\
				i2c, config)

#define devm_regmap_init_mdio(mdio_dev, config)				\
	__regmap_lockdep_wrapper(__devm_regmap_init_mdio, #config,	\
				mdio_dev, config)

#define devm_regmap_init_spi(dev, config)				\
	__regmap_lockdep_wrapper(__devm_regmap_init_spi, #config,	\
				dev, config)

/*等等等, 可以配合其他模块使用*/

以下是一个demo

/*
这个demo中,我没有注册设备,而是以模块的形式,创建了一个device的结构体用来初始化regmap
目的是为了简单尝试一下regmap的功能,可能不太规范(我还记得我第一任师傅说...我野路子太多了,哈哈)
简单理解一下功能,不深挖细节哈
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/errno.h>
#include <linux/regmap.h>

#define TEST_MEM_SIZE 256

static void *test_regmap_ptr;

static struct device test_device;

/* void *context is init param test_regmap_ptr */
static int test_reg_read(void *context, unsigned int reg, unsigned int *val)
{
	uint32_t *base = (uint32_t *)(context);

	*val = *(base + (reg/4));

	return 0;
}

static int test_reg_write(void *context, unsigned int reg, unsigned int val)
{
	uint32_t *base = (uint32_t *)(context);

	*(base + (reg/4)) = val;

	return 0;
}

static const struct regmap_config config = {
	.reg_bits = 32,
	.reg_stride = 4,
	.val_bits = 32,
	.max_register = 0xFC,
	.reg_read = test_reg_read,
	.reg_write = test_reg_write,
	.fast_io = true,
};

/*
 * This demo just init a memory as rw
 * no other function, more sample need to check linux source code
 */
static int __init test_regmap_init(void)
{
	int val;
	test_regmap_ptr = kmalloc(TEST_MEM_SIZE, GFP_KERNEL);
	printk("%s: my_test\n", __func__);

	device_initialize(&test_device);
	dev_set_name(&test_device, "test_device");

	dev_info(&test_device, "This is info\n");
	dev_dbg(&test_device, "This is debug\n");
	dev_notice(&test_device, "This is notice\n");
	dev_warn(&test_device, "This is warn\n");

//	val = device_add(&test_device);
//	if (val) {
//		dev_err(&test_device,
//			"device add failed: %d", val);
//	}

	/*create test_regmap_ptr, as context to init regmap */
	struct regmap *map = devm_regmap_init(&test_device, NULL, test_regmap_ptr, &config);

	regmap_read(map, 0x00, &val);
printk("0x00:val=%x\n",val);
	regmap_read(map, 0x04, &val);
printk("0x04:val=%x\n",val);
	regmap_write(map, 0x00, 0x11);
	regmap_write(map, 0x04, 0x22);
	regmap_read(map, 0x00, &val);
printk("0x00:val=%x\n",val);
	regmap_read(map, 0x04, &val);
printk("0x04:val=%x\n",val);
	return 0;
}

static void __exit test_regmap_exit(void)
{

}

module_init(test_regmap_init);
module_exit(test_regmap_exit);

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值