设备驱动中的regmap

regmap是Linux 3.1引入的特性,旨在减少慢速I/O驱动的重复逻辑,提供通用接口操作硬件寄存器。它包括regmap_config、regcache_ops、regmap_bus和regmap结构体,通过这些组件,驱动可以更高效地读写寄存器,同时减少了底层I/O操作。regmap_config定义设备寄存器配置,regcache_ops管理缓存类型,regmap_bus处理总线操作,regmap结构体则用于具体的I/O调度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

regmap 机制是在 Linux 3.1 加入进来的特性。主要目的是减少慢速 I/O 驱动上的重复逻辑,提供一种通用的接口来操作底层硬件上的寄存器。其实这就是内核做的一次重构。regmap 除了能做到统一的 I/O 接口,还可以在驱动和硬件 IC 之间做一层缓存,从而能减少底层 I/O 的操作次数。

以一个 I2C 设备为例。读写一个寄存器,肯定需要用到i2c_transfer这样的 I2C 函数。为了方便,一般的驱动中,会在这之上再写一个 Wrapper,然后通过调用这个 Wrapper 来读写寄存器。比如如下这个读取寄存器的函数:


static int xxx_i2c_read_reg(struct i2c_client *client, u8 reg, u8 *val)
{
    struct i2c_msg msg[] = {
        {
            .addr = client->addr,
            .flags = 0,
            .len = 1,
            .buf = &reg,
        },
        {
            .addr = client->addr,
            .flags = I2C_M_RD,
            .len = 1,
            .buf = val,
        },
    };

    return i2c_transfer(client->adapter, msg, 2);
}

而如果 regmap 的方式来实现,对于上面这种读寄存器操作,其实现如下:

// first step: define regmap_config
static const struct regmap_config xxx_regmap_config = {
    .reg_bits = 10,
    .val_bits = 14,

    .max_register = 40,
    .cache_type = REGCACHE_RBTREE,

    .volatile_reg = false,
    .readable_reg = false,
};

// second step: initialize regmap in driver loading
regmap = regmap_init_i2c(i2c_client, &xxx_regmap_config);

// third step: register operations
regmap_read(regmap, XXX_REG, &value);

第一步就是定义 IC 的一些寄存器信息。比如:位宽,地址位宽,寄存器总数等。然后在驱动加载的时候,初始化 regmap,这样就可以正常调用 regmap 的 API 了。

可以看到,为了让慢速 I/O 能够专注于自身的逻辑,内核把 SPI, I2C 等总线操作方式全部封装在 regmap 里,这样驱动若要做 I/O 操作,直接调用 regmap 的函数就可以了。

regmap_config

struct regmap_config结构体代表一个设备的寄存器配置信息,在做 Regmap 初始化时,驱动就需要把这个结构体传给 Regmap。这个结构体的定义在 include/linux/regmap.h,其中包含该设备的寄存器数量,寄存器位宽,缓存类型,读写属性等。

这一层是直接和驱动对接的。Regmap 根据传进来的regmap_config初始化对应的缓存和总线操作接口,驱动就可以正常调用 regmap_writeregmap_read函数。

3.2 regmap_ops


/**
 * Configuration for the register map of a device.
 *
 * @name: Optional name of the regmap. Useful when a device has multiple
 *        register regions.
 *
 * @reg_bits: Number of bits in a register address, mandatory.
 * @reg_stride: The register address stride. Valid register addresses are a
 *              multiple of this value. If set to 0, a value of 1 will be
 *              used.
 * @pad_bits: Number of bits of padding between register and value.
 * @val_bits: Number of bits in a register value, mandatory.
 *
 * @writeable_reg: Optional callback returning true if the register
 *         can be written to. If this field is NULL but wr_table
 *         (see below) is not, the check is performed on such table
 *                 (a register is writeable if it belongs to one of the ranges
 *                  specified by wr_table).
 * @readable_reg: Optional callback returning true if the register
 *        can be read from. If this field is NULL but rd_table
 *         (see below) is not, the check is performed on such table
 *                 (a register is readable if it belongs to one of the ranges
 *                  specified by rd_table).
 * @volatile_reg: Optional callback returning true if the register
 *        value can't be cached. If this field is NULL but
 *        volatile_table (see below) is not, the check is performed on
 *                such table (a register is volatile if it belongs to one of
 *                the ranges specified by volatile_table).
 * @precious_reg: Optional callback returning true if the register
 *        should not be read outside of a call from the driver
 *        (e.g., a clear on read interrupt status register). If this
 *                field is NULL but precious_table (see below) is not, the
 *                check is performed on such table (a register is precious if
 *                it belongs to one of the ranges specified by precious_table).
 * @lock:     Optional lock callback (overrides regmap's default lock
 *        function, based on spinlock or mutex).
 * <
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值